Version in base suite: 10.1.40-1 Base version: tomcat10_10.1.40-1 Target version: tomcat10_10.1.52-1~deb13u1 Base file: /srv/ftp-master.debian.org/ftp/pool/main/t/tomcat10/tomcat10_10.1.40-1.dsc Target file: /srv/ftp-master.debian.org/policy/pool/main/t/tomcat10/tomcat10_10.1.52-1~deb13u1.dsc /srv/release.debian.org/tmp/dJm1BNZuE4/tomcat10-10.1.52/res/install-win/Uninstall.exe.sig |binary /srv/release.debian.org/tmp/dJm1BNZuE4/tomcat10-10.1.52/res/install-win/tomcat-installer.exe.sig |binary /srv/release.debian.org/tmp/dJm1BNZuE4/tomcat10-10.1.52/test/org/apache/tomcat/util/net/ca.jks |binary /srv/release.debian.org/tmp/dJm1BNZuE4/tomcat10-10.1.52/test/org/apache/tomcat/util/net/localhost-crl-rsa.jks |binary /srv/release.debian.org/tmp/dJm1BNZuE4/tomcat10-10.1.52/test/org/apache/tomcat/util/net/localhost-ec.jks |binary /srv/release.debian.org/tmp/dJm1BNZuE4/tomcat10-10.1.52/test/org/apache/tomcat/util/net/localhost-rsa-copy1.jks |binary /srv/release.debian.org/tmp/dJm1BNZuE4/tomcat10-10.1.52/test/org/apache/tomcat/util/net/localhost-rsa.jks |binary /srv/release.debian.org/tmp/dJm1BNZuE4/tomcat10-10.1.52/test/org/apache/tomcat/util/net/user1.jks |binary /srv/release.debian.org/tmp/dJm1BNZuE4/tomcat10-10.1.52/test/org/apache/tomcat/util/net/user2-crl.jks |binary /srv/release.debian.org/tmp/dJm1BNZuE4/tomcat10-10.1.52/test/org/apache/tomcat/util/net/user3-crl-long.jks |binary /srv/release.debian.org/tmp/dJm1BNZuE4/tomcat10-10.1.52/test/webapp/WEB-INF/lib/bug69623-lib.jar |binary /srv/release.debian.org/tmp/dJm1BNZuE4/tomcat10-10.1.52/webapps/docs/architecture/requestProcess/11_nio.png |binary /srv/release.debian.org/tmp/dJm1BNZuE4/tomcat10-10.1.52/webapps/docs/architecture/requestProcess/21_http11.png |binary /srv/release.debian.org/tmp/dJm1BNZuE4/tomcat10-10.1.52/webapps/docs/architecture/requestProcess/31_synchronous.png |binary /srv/release.debian.org/tmp/dJm1BNZuE4/tomcat10-10.1.52/webapps/docs/architecture/requestProcess/41_basic.png |binary /srv/release.debian.org/tmp/dJm1BNZuE4/tomcat10-10.1.52/webapps/docs/architecture/requestProcess/authentication-process.png |binary /srv/release.debian.org/tmp/dJm1BNZuE4/tomcat10-10.1.52/webapps/docs/architecture/requestProcess/request-process.png |binary /srv/release.debian.org/tmp/dJm1BNZuE4/tomcat10-10.1.52/webapps/host-manager/images/favicon.ico |binary /srv/release.debian.org/tmp/dJm1BNZuE4/tomcat10-10.1.52/webapps/manager/images/favicon.ico |binary tomcat10-10.1.52/.github/workflows/ci.yml | 4 tomcat10-10.1.52/.gitignore | 1 tomcat10-10.1.52/BUILDING.txt | 22 tomcat10-10.1.52/CONTRIBUTING.md | 2 tomcat10-10.1.52/MERGE.txt | 6 tomcat10-10.1.52/NOTICE | 2 tomcat10-10.1.52/README.md | 4 tomcat10-10.1.52/RUNNING.txt | 4 tomcat10-10.1.52/bin/catalina.bat | 2 tomcat10-10.1.52/bin/service.bat | 12 tomcat10-10.1.52/build.properties.default | 71 tomcat10-10.1.52/build.properties.release | 8 tomcat10-10.1.52/build.xml | 304 tomcat10-10.1.52/conf/web.xml | 30 tomcat10-10.1.52/debian/changelog | 30 tomcat10-10.1.52/debian/control | 2 tomcat10-10.1.52/debian/copyright | 4 tomcat10-10.1.52/debian/patches/0004-split-deploy-webapps-target-from-deploy-target.patch | 6 tomcat10-10.1.52/debian/patches/0005-skip-test-failures.patch | 4 tomcat10-10.1.52/debian/patches/0009-Use-java.security.policy-file-in-catalina.sh.patch | 8 tomcat10-10.1.52/debian/patches/0010-debianize-build-xml.patch | 6 tomcat10-10.1.52/debian/patches/0013-dont-look-for-build-properties-in-user-home.patch | 4 tomcat10-10.1.52/debian/patches/0018-fix-manager-webapp.patch | 16 tomcat10-10.1.52/debian/patches/0019-add-distribution-to-error-page.patch | 4 tomcat10-10.1.52/debian/patches/0021-dont-test-unsupported-ciphers.patch | 12 tomcat10-10.1.52/debian/patches/0023-disable-shutdown-by-socket.patch | 2 tomcat10-10.1.52/debian/patches/0024-systemd-log-formatter.patch | 3 tomcat10-10.1.52/debian/patches/0025-invalid-configuration-exit-status.patch | 4 tomcat10-10.1.52/debian/patches/0026-easymock4-compatibility.patch | 49 tomcat10-10.1.52/debian/patches/0030-eclipse-jdt-classpath.patch | 12 tomcat10-10.1.52/debian/patches/disable-jacoco.patch | 14 tomcat10-10.1.52/debian/patches/exclude-TestJNDIRealmIntegration.patch | 14 tomcat10-10.1.52/debian/patches/series | 4 tomcat10-10.1.52/java/jakarta/el/ELContextListener.java | 3 tomcat10-10.1.52/java/jakarta/el/ELResolver.java | 3 tomcat10-10.1.52/java/jakarta/el/ExpressionFactory.java | 6 tomcat10-10.1.52/java/jakarta/el/ImportHandler.java | 17 tomcat10-10.1.52/java/jakarta/el/Util.java | 2 tomcat10-10.1.52/java/jakarta/servlet/LocalStrings_ru.properties | 6 tomcat10-10.1.52/java/jakarta/servlet/http/HttpServlet.java | 13 tomcat10-10.1.52/java/jakarta/servlet/http/HttpServletRequest.java | 7 tomcat10-10.1.52/java/jakarta/servlet/http/LocalStrings_ja.properties | 2 tomcat10-10.1.52/java/jakarta/servlet/http/LocalStrings_ru.properties | 21 tomcat10-10.1.52/java/jakarta/servlet/jsp/LocalStrings_ru.properties | 19 tomcat10-10.1.52/java/jakarta/servlet/jsp/tagext/BodyContent.java | 2 tomcat10-10.1.52/java/jakarta/websocket/ContainerProvider.java | 2 tomcat10-10.1.52/java/jakarta/websocket/server/ServerEndpointConfig.java | 2 tomcat10-10.1.52/java/org/apache/catalina/Authenticator.java | 2 tomcat10-10.1.52/java/org/apache/catalina/Cluster.java | 3 tomcat10-10.1.52/java/org/apache/catalina/Contained.java | 5 tomcat10-10.1.52/java/org/apache/catalina/Container.java | 5 tomcat10-10.1.52/java/org/apache/catalina/ContainerEvent.java | 2 tomcat10-10.1.52/java/org/apache/catalina/ContainerListener.java | 2 tomcat10-10.1.52/java/org/apache/catalina/ContainerServlet.java | 2 tomcat10-10.1.52/java/org/apache/catalina/Context.java | 6 tomcat10-10.1.52/java/org/apache/catalina/Engine.java | 2 tomcat10-10.1.52/java/org/apache/catalina/Globals.java | 2 tomcat10-10.1.52/java/org/apache/catalina/Group.java | 2 tomcat10-10.1.52/java/org/apache/catalina/Host.java | 2 tomcat10-10.1.52/java/org/apache/catalina/Lifecycle.java | 2 tomcat10-10.1.52/java/org/apache/catalina/LifecycleEvent.java | 2 tomcat10-10.1.52/java/org/apache/catalina/LifecycleException.java | 2 tomcat10-10.1.52/java/org/apache/catalina/LifecycleListener.java | 6 tomcat10-10.1.52/java/org/apache/catalina/Loader.java | 2 tomcat10-10.1.52/java/org/apache/catalina/Manager.java | 2 tomcat10-10.1.52/java/org/apache/catalina/Pipeline.java | 8 tomcat10-10.1.52/java/org/apache/catalina/Realm.java | 2 tomcat10-10.1.52/java/org/apache/catalina/Role.java | 2 tomcat10-10.1.52/java/org/apache/catalina/Server.java | 2 tomcat10-10.1.52/java/org/apache/catalina/Service.java | 2 tomcat10-10.1.52/java/org/apache/catalina/Session.java | 6 tomcat10-10.1.52/java/org/apache/catalina/SessionEvent.java | 2 tomcat10-10.1.52/java/org/apache/catalina/SessionListener.java | 2 tomcat10-10.1.52/java/org/apache/catalina/Store.java | 22 tomcat10-10.1.52/java/org/apache/catalina/User.java | 2 tomcat10-10.1.52/java/org/apache/catalina/UserDatabase.java | 2 tomcat10-10.1.52/java/org/apache/catalina/Valve.java | 7 tomcat10-10.1.52/java/org/apache/catalina/WebResourceRoot.java | 12 tomcat10-10.1.52/java/org/apache/catalina/WebResourceSet.java | 15 tomcat10-10.1.52/java/org/apache/catalina/Wrapper.java | 2 tomcat10-10.1.52/java/org/apache/catalina/ant/AbstractCatalinaTask.java | 9 tomcat10-10.1.52/java/org/apache/catalina/ant/BaseRedirectorHelperTask.java | 16 tomcat10-10.1.52/java/org/apache/catalina/ant/DeployTask.java | 8 tomcat10-10.1.52/java/org/apache/catalina/ant/JKStatusUpdateTask.java | 2 tomcat10-10.1.52/java/org/apache/catalina/ant/JMXGetTask.java | 2 tomcat10-10.1.52/java/org/apache/catalina/ant/JMXQueryTask.java | 2 tomcat10-10.1.52/java/org/apache/catalina/ant/JMXSetTask.java | 2 tomcat10-10.1.52/java/org/apache/catalina/ant/ListTask.java | 2 tomcat10-10.1.52/java/org/apache/catalina/ant/ReloadTask.java | 2 tomcat10-10.1.52/java/org/apache/catalina/ant/ResourcesTask.java | 2 tomcat10-10.1.52/java/org/apache/catalina/ant/ServerinfoTask.java | 8 tomcat10-10.1.52/java/org/apache/catalina/ant/SessionsTask.java | 5 tomcat10-10.1.52/java/org/apache/catalina/ant/StartTask.java | 2 tomcat10-10.1.52/java/org/apache/catalina/ant/StopTask.java | 2 tomcat10-10.1.52/java/org/apache/catalina/ant/UndeployTask.java | 2 tomcat10-10.1.52/java/org/apache/catalina/ant/ValidatorTask.java | 2 tomcat10-10.1.52/java/org/apache/catalina/ant/jmx/JMXAccessorCondition.java | 2 tomcat10-10.1.52/java/org/apache/catalina/ant/jmx/JMXAccessorCreateTask.java | 6 tomcat10-10.1.52/java/org/apache/catalina/ant/jmx/JMXAccessorEqualsCondition.java | 2 tomcat10-10.1.52/java/org/apache/catalina/ant/jmx/JMXAccessorGetTask.java | 2 tomcat10-10.1.52/java/org/apache/catalina/ant/jmx/JMXAccessorInvokeTask.java | 12 tomcat10-10.1.52/java/org/apache/catalina/ant/jmx/JMXAccessorQueryTask.java | 2 tomcat10-10.1.52/java/org/apache/catalina/ant/jmx/JMXAccessorSetTask.java | 2 tomcat10-10.1.52/java/org/apache/catalina/ant/jmx/JMXAccessorTask.java | 2 tomcat10-10.1.52/java/org/apache/catalina/ant/jmx/JMXAccessorUnregisterTask.java | 2 tomcat10-10.1.52/java/org/apache/catalina/authenticator/AuthenticatorBase.java | 121 tomcat10-10.1.52/java/org/apache/catalina/authenticator/BasicAuthenticator.java | 4 tomcat10-10.1.52/java/org/apache/catalina/authenticator/DigestAuthenticator.java | 23 tomcat10-10.1.52/java/org/apache/catalina/authenticator/FormAuthenticator.java | 73 tomcat10-10.1.52/java/org/apache/catalina/authenticator/LocalStrings.properties | 9 tomcat10-10.1.52/java/org/apache/catalina/authenticator/LocalStrings_fr.properties | 5 tomcat10-10.1.52/java/org/apache/catalina/authenticator/LocalStrings_ja.properties | 5 tomcat10-10.1.52/java/org/apache/catalina/authenticator/LocalStrings_ru.properties | 3 tomcat10-10.1.52/java/org/apache/catalina/authenticator/NonLoginAuthenticator.java | 2 tomcat10-10.1.52/java/org/apache/catalina/authenticator/SSLAuthenticator.java | 80 tomcat10-10.1.52/java/org/apache/catalina/authenticator/SavedRequest.java | 21 tomcat10-10.1.52/java/org/apache/catalina/authenticator/SingleSignOn.java | 109 tomcat10-10.1.52/java/org/apache/catalina/authenticator/SingleSignOnEntry.java | 14 tomcat10-10.1.52/java/org/apache/catalina/authenticator/SingleSignOnListener.java | 14 tomcat10-10.1.52/java/org/apache/catalina/authenticator/SingleSignOnSessionKey.java | 7 tomcat10-10.1.52/java/org/apache/catalina/authenticator/SpnegoAuthenticator.java | 12 tomcat10-10.1.52/java/org/apache/catalina/authenticator/jaspic/AuthConfigFactoryImpl.java | 2 tomcat10-10.1.52/java/org/apache/catalina/authenticator/jaspic/LocalStrings_ru.properties | 2 tomcat10-10.1.52/java/org/apache/catalina/authenticator/jaspic/PersistentProviderRegistrations.java | 4 tomcat10-10.1.52/java/org/apache/catalina/connector/ClientAbortException.java | 2 tomcat10-10.1.52/java/org/apache/catalina/connector/Connector.java | 77 tomcat10-10.1.52/java/org/apache/catalina/connector/CoyoteAdapter.java | 24 tomcat10-10.1.52/java/org/apache/catalina/connector/CoyoteInputStream.java | 2 tomcat10-10.1.52/java/org/apache/catalina/connector/CoyoteOutputStream.java | 3 tomcat10-10.1.52/java/org/apache/catalina/connector/CoyotePrincipal.java | 2 tomcat10-10.1.52/java/org/apache/catalina/connector/CoyoteReader.java | 2 tomcat10-10.1.52/java/org/apache/catalina/connector/CoyoteWriter.java | 20 tomcat10-10.1.52/java/org/apache/catalina/connector/InputBuffer.java | 21 tomcat10-10.1.52/java/org/apache/catalina/connector/LocalStrings.properties | 2 tomcat10-10.1.52/java/org/apache/catalina/connector/LocalStrings_es.properties | 2 tomcat10-10.1.52/java/org/apache/catalina/connector/LocalStrings_fr.properties | 2 tomcat10-10.1.52/java/org/apache/catalina/connector/LocalStrings_ja.properties | 4 tomcat10-10.1.52/java/org/apache/catalina/connector/LocalStrings_ru.properties | 1 tomcat10-10.1.52/java/org/apache/catalina/connector/OutputBuffer.java | 12 tomcat10-10.1.52/java/org/apache/catalina/connector/Request.java | 233 tomcat10-10.1.52/java/org/apache/catalina/connector/RequestFacade.java | 3 tomcat10-10.1.52/java/org/apache/catalina/connector/Response.java | 15 tomcat10-10.1.52/java/org/apache/catalina/connector/ResponseFacade.java | 2 tomcat10-10.1.52/java/org/apache/catalina/core/ApplicationContext.java | 33 tomcat10-10.1.52/java/org/apache/catalina/core/ApplicationContextFacade.java | 2 tomcat10-10.1.52/java/org/apache/catalina/core/ApplicationDispatcher.java | 26 tomcat10-10.1.52/java/org/apache/catalina/core/ApplicationFilterChain.java | 18 tomcat10-10.1.52/java/org/apache/catalina/core/ApplicationFilterConfig.java | 17 tomcat10-10.1.52/java/org/apache/catalina/core/ApplicationFilterFactory.java | 3 tomcat10-10.1.52/java/org/apache/catalina/core/ApplicationHttpRequest.java | 7 tomcat10-10.1.52/java/org/apache/catalina/core/ApplicationHttpResponse.java | 2 tomcat10-10.1.52/java/org/apache/catalina/core/ApplicationPushBuilder.java | 2 tomcat10-10.1.52/java/org/apache/catalina/core/ApplicationRequest.java | 5 tomcat10-10.1.52/java/org/apache/catalina/core/ApplicationResponse.java | 2 tomcat10-10.1.52/java/org/apache/catalina/core/AprLifecycleListener.java | 114 tomcat10-10.1.52/java/org/apache/catalina/core/AprStatus.java | 30 tomcat10-10.1.52/java/org/apache/catalina/core/ContainerBase.java | 8 tomcat10-10.1.52/java/org/apache/catalina/core/DefaultInstanceManager.java | 22 tomcat10-10.1.52/java/org/apache/catalina/core/JreMemoryLeakPreventionListener.java | 6 tomcat10-10.1.52/java/org/apache/catalina/core/LocalStrings.properties | 6 tomcat10-10.1.52/java/org/apache/catalina/core/LocalStrings_ja.properties | 2 tomcat10-10.1.52/java/org/apache/catalina/core/LocalStrings_ru.properties | 5 tomcat10-10.1.52/java/org/apache/catalina/core/NamingContextListener.java | 37 tomcat10-10.1.52/java/org/apache/catalina/core/OpenSSLLifecycleListener.java | 2 tomcat10-10.1.52/java/org/apache/catalina/core/PropertiesRoleMappingListener.java | 4 tomcat10-10.1.52/java/org/apache/catalina/core/StandardContext.java | 55 tomcat10-10.1.52/java/org/apache/catalina/core/StandardContextValve.java | 2 tomcat10-10.1.52/java/org/apache/catalina/core/StandardEngine.java | 2 tomcat10-10.1.52/java/org/apache/catalina/core/StandardEngineValve.java | 2 tomcat10-10.1.52/java/org/apache/catalina/core/StandardHost.java | 19 tomcat10-10.1.52/java/org/apache/catalina/core/StandardHostValve.java | 11 tomcat10-10.1.52/java/org/apache/catalina/core/StandardPipeline.java | 2 tomcat10-10.1.52/java/org/apache/catalina/core/StandardServer.java | 22 tomcat10-10.1.52/java/org/apache/catalina/core/StandardService.java | 2 tomcat10-10.1.52/java/org/apache/catalina/core/StandardWrapper.java | 17 tomcat10-10.1.52/java/org/apache/catalina/core/StandardWrapperFacade.java | 2 tomcat10-10.1.52/java/org/apache/catalina/core/StandardWrapperValve.java | 48 tomcat10-10.1.52/java/org/apache/catalina/core/ThreadLocalLeakPreventionListener.java | 6 tomcat10-10.1.52/java/org/apache/catalina/deploy/NamingResourcesImpl.java | 14 tomcat10-10.1.52/java/org/apache/catalina/filters/Constants.java | 6 tomcat10-10.1.52/java/org/apache/catalina/filters/CorsFilter.java | 18 tomcat10-10.1.52/java/org/apache/catalina/filters/CsrfPreventionFilter.java | 86 tomcat10-10.1.52/java/org/apache/catalina/filters/ExpiresFilter.java | 5 tomcat10-10.1.52/java/org/apache/catalina/filters/RemoteAddrFilter.java | 3 tomcat10-10.1.52/java/org/apache/catalina/filters/RemoteCIDRFilter.java | 60 tomcat10-10.1.52/java/org/apache/catalina/filters/RemoteHostFilter.java | 2 tomcat10-10.1.52/java/org/apache/catalina/filters/RemoteIpFilter.java | 35 tomcat10-10.1.52/java/org/apache/catalina/filters/RequestDumperFilter.java | 2 tomcat10-10.1.52/java/org/apache/catalina/ha/ClusterListener.java | 2 tomcat10-10.1.52/java/org/apache/catalina/ha/ClusterManager.java | 2 tomcat10-10.1.52/java/org/apache/catalina/ha/ClusterRuleSet.java | 4 tomcat10-10.1.52/java/org/apache/catalina/ha/ClusterValve.java | 2 tomcat10-10.1.52/java/org/apache/catalina/ha/authenticator/ClusterSingleSignOn.java | 2 tomcat10-10.1.52/java/org/apache/catalina/ha/backend/HeartbeatListener.java | 16 tomcat10-10.1.52/java/org/apache/catalina/ha/backend/MultiCastSender.java | 8 tomcat10-10.1.52/java/org/apache/catalina/ha/backend/TcpSender.java | 14 tomcat10-10.1.52/java/org/apache/catalina/ha/context/ReplicatedContext.java | 6 tomcat10-10.1.52/java/org/apache/catalina/ha/deploy/FarmWarDeployer.java | 37 tomcat10-10.1.52/java/org/apache/catalina/ha/deploy/FileMessageFactory.java | 2 tomcat10-10.1.52/java/org/apache/catalina/ha/deploy/WarWatcher.java | 2 tomcat10-10.1.52/java/org/apache/catalina/ha/session/BackupManager.java | 6 tomcat10-10.1.52/java/org/apache/catalina/ha/session/ClusterSessionListener.java | 2 tomcat10-10.1.52/java/org/apache/catalina/ha/session/DeltaManager.java | 243 tomcat10-10.1.52/java/org/apache/catalina/ha/session/DeltaRequest.java | 21 tomcat10-10.1.52/java/org/apache/catalina/ha/session/JvmRouteBinderValve.java | 12 tomcat10-10.1.52/java/org/apache/catalina/ha/session/LocalStrings_ja.properties | 2 tomcat10-10.1.52/java/org/apache/catalina/ha/session/SessionMessage.java | 4 tomcat10-10.1.52/java/org/apache/catalina/ha/session/SessionMessageImpl.java | 4 tomcat10-10.1.52/java/org/apache/catalina/ha/tcp/Constants.java | 2 tomcat10-10.1.52/java/org/apache/catalina/ha/tcp/ReplicationValve.java | 18 tomcat10-10.1.52/java/org/apache/catalina/ha/tcp/SendMessageData.java | 3 tomcat10-10.1.52/java/org/apache/catalina/ha/tcp/SimpleTcpCluster.java | 29 tomcat10-10.1.52/java/org/apache/catalina/loader/LocalStrings.properties | 2 tomcat10-10.1.52/java/org/apache/catalina/loader/LocalStrings_fr.properties | 2 tomcat10-10.1.52/java/org/apache/catalina/loader/LocalStrings_ja.properties | 2 tomcat10-10.1.52/java/org/apache/catalina/loader/LocalStrings_ko.properties | 2 tomcat10-10.1.52/java/org/apache/catalina/loader/LocalStrings_zh_CN.properties | 2 tomcat10-10.1.52/java/org/apache/catalina/loader/ResourceEntry.java | 2 tomcat10-10.1.52/java/org/apache/catalina/loader/WebappClassLoaderBase.java | 22 tomcat10-10.1.52/java/org/apache/catalina/loader/WebappLoader.java | 32 tomcat10-10.1.52/java/org/apache/catalina/manager/Constants.java | 3 tomcat10-10.1.52/java/org/apache/catalina/manager/HTMLManagerServlet.java | 26 tomcat10-10.1.52/java/org/apache/catalina/manager/JMXProxyServlet.java | 26 tomcat10-10.1.52/java/org/apache/catalina/manager/JspHelper.java | 2 tomcat10-10.1.52/java/org/apache/catalina/manager/LocalStrings.properties | 3 tomcat10-10.1.52/java/org/apache/catalina/manager/LocalStrings_fr.properties | 3 tomcat10-10.1.52/java/org/apache/catalina/manager/LocalStrings_ja.properties | 5 tomcat10-10.1.52/java/org/apache/catalina/manager/LocalStrings_ko.properties | 1 tomcat10-10.1.52/java/org/apache/catalina/manager/LocalStrings_pt_BR.properties | 3 tomcat10-10.1.52/java/org/apache/catalina/manager/LocalStrings_ru.properties | 2 tomcat10-10.1.52/java/org/apache/catalina/manager/LocalStrings_zh_CN.properties | 1 tomcat10-10.1.52/java/org/apache/catalina/manager/ManagerServlet.java | 67 tomcat10-10.1.52/java/org/apache/catalina/manager/StatusManagerServlet.java | 2 tomcat10-10.1.52/java/org/apache/catalina/manager/StatusTransformer.java | 6 tomcat10-10.1.52/java/org/apache/catalina/manager/host/Constants.java | 2 tomcat10-10.1.52/java/org/apache/catalina/manager/host/HTMLHostManagerServlet.java | 5 tomcat10-10.1.52/java/org/apache/catalina/manager/host/HostManagerServlet.java | 7 tomcat10-10.1.52/java/org/apache/catalina/manager/host/LocalStrings_ja.properties | 4 tomcat10-10.1.52/java/org/apache/catalina/manager/host/LocalStrings_ru.properties | 6 tomcat10-10.1.52/java/org/apache/catalina/manager/host/LocalStrings_zh_CN.properties | 6 tomcat10-10.1.52/java/org/apache/catalina/manager/util/SessionUtils.java | 2 tomcat10-10.1.52/java/org/apache/catalina/mapper/LocalStrings_ru.properties | 19 tomcat10-10.1.52/java/org/apache/catalina/mapper/Mapper.java | 4 tomcat10-10.1.52/java/org/apache/catalina/mapper/MapperListener.java | 3 tomcat10-10.1.52/java/org/apache/catalina/mapper/MappingData.java | 2 tomcat10-10.1.52/java/org/apache/catalina/mbeans/ClassNameMBean.java | 2 tomcat10-10.1.52/java/org/apache/catalina/mbeans/ConnectorMBean.java | 4 tomcat10-10.1.52/java/org/apache/catalina/mbeans/ContextEnvironmentMBean.java | 4 tomcat10-10.1.52/java/org/apache/catalina/mbeans/ContextResourceLinkMBean.java | 4 tomcat10-10.1.52/java/org/apache/catalina/mbeans/ContextResourceMBean.java | 4 tomcat10-10.1.52/java/org/apache/catalina/mbeans/DataSourceUserDatabaseMBean.java | 2 tomcat10-10.1.52/java/org/apache/catalina/mbeans/GlobalResourcesLifecycleListener.java | 2 tomcat10-10.1.52/java/org/apache/catalina/mbeans/GroupMBean.java | 2 tomcat10-10.1.52/java/org/apache/catalina/mbeans/MBeanFactory.java | 4 tomcat10-10.1.52/java/org/apache/catalina/mbeans/MBeanUtils.java | 14 tomcat10-10.1.52/java/org/apache/catalina/mbeans/MemoryUserDatabaseMBean.java | 2 tomcat10-10.1.52/java/org/apache/catalina/mbeans/NamingResourcesMBean.java | 4 tomcat10-10.1.52/java/org/apache/catalina/mbeans/RoleMBean.java | 2 tomcat10-10.1.52/java/org/apache/catalina/mbeans/SparseUserDatabaseMBean.java | 2 tomcat10-10.1.52/java/org/apache/catalina/mbeans/UserMBean.java | 2 tomcat10-10.1.52/java/org/apache/catalina/realm/CombinedRealm.java | 4 tomcat10-10.1.52/java/org/apache/catalina/realm/DataSourceRealm.java | 5 tomcat10-10.1.52/java/org/apache/catalina/realm/GenericPrincipal.java | 2 tomcat10-10.1.52/java/org/apache/catalina/realm/JAASCallbackHandler.java | 7 tomcat10-10.1.52/java/org/apache/catalina/realm/JAASMemoryLoginModule.java | 2 tomcat10-10.1.52/java/org/apache/catalina/realm/JAASRealm.java | 21 tomcat10-10.1.52/java/org/apache/catalina/realm/JNDIRealm.java | 29 tomcat10-10.1.52/java/org/apache/catalina/realm/LocalStrings_ru.properties | 1 tomcat10-10.1.52/java/org/apache/catalina/realm/LockOutRealm.java | 2 tomcat10-10.1.52/java/org/apache/catalina/realm/MemoryRealm.java | 2 tomcat10-10.1.52/java/org/apache/catalina/realm/MemoryRuleSet.java | 2 tomcat10-10.1.52/java/org/apache/catalina/realm/MessageDigestCredentialHandler.java | 18 tomcat10-10.1.52/java/org/apache/catalina/realm/NullRealm.java | 4 tomcat10-10.1.52/java/org/apache/catalina/realm/RealmBase.java | 2 tomcat10-10.1.52/java/org/apache/catalina/realm/UserDatabaseRealm.java | 13 tomcat10-10.1.52/java/org/apache/catalina/security/SecurityClassLoad.java | 2 tomcat10-10.1.52/java/org/apache/catalina/security/SecurityConfig.java | 2 tomcat10-10.1.52/java/org/apache/catalina/security/SecurityListener.java | 3 tomcat10-10.1.52/java/org/apache/catalina/servlets/CGIServlet.java | 290 tomcat10-10.1.52/java/org/apache/catalina/servlets/DefaultServlet.java | 66 tomcat10-10.1.52/java/org/apache/catalina/servlets/LocalStrings.properties | 2 tomcat10-10.1.52/java/org/apache/catalina/servlets/LocalStrings_fr.properties | 3 tomcat10-10.1.52/java/org/apache/catalina/servlets/LocalStrings_ja.properties | 3 tomcat10-10.1.52/java/org/apache/catalina/servlets/LocalStrings_ko.properties | 1 tomcat10-10.1.52/java/org/apache/catalina/servlets/LocalStrings_ru.properties | 1 tomcat10-10.1.52/java/org/apache/catalina/servlets/LocalStrings_zh_CN.properties | 1 tomcat10-10.1.52/java/org/apache/catalina/servlets/WebdavServlet.java | 80 tomcat10-10.1.52/java/org/apache/catalina/session/Constants.java | 2 tomcat10-10.1.52/java/org/apache/catalina/session/DataSourceStore.java | 20 tomcat10-10.1.52/java/org/apache/catalina/session/FileStore.java | 70 tomcat10-10.1.52/java/org/apache/catalina/session/LocalStrings.properties | 8 tomcat10-10.1.52/java/org/apache/catalina/session/LocalStrings_es.properties | 6 tomcat10-10.1.52/java/org/apache/catalina/session/LocalStrings_fr.properties | 6 tomcat10-10.1.52/java/org/apache/catalina/session/LocalStrings_ja.properties | 6 tomcat10-10.1.52/java/org/apache/catalina/session/LocalStrings_ko.properties | 6 tomcat10-10.1.52/java/org/apache/catalina/session/LocalStrings_zh_CN.properties | 6 tomcat10-10.1.52/java/org/apache/catalina/session/ManagerBase.java | 2 tomcat10-10.1.52/java/org/apache/catalina/session/PersistentManager.java | 2 tomcat10-10.1.52/java/org/apache/catalina/session/PersistentManagerBase.java | 42 tomcat10-10.1.52/java/org/apache/catalina/session/StandardManager.java | 4 tomcat10-10.1.52/java/org/apache/catalina/session/StandardSession.java | 7 tomcat10-10.1.52/java/org/apache/catalina/session/StandardSessionFacade.java | 2 tomcat10-10.1.52/java/org/apache/catalina/session/StoreBase.java | 10 tomcat10-10.1.52/java/org/apache/catalina/ssi/ByteArrayServletOutputStream.java | 2 tomcat10-10.1.52/java/org/apache/catalina/ssi/ExpressionParseTree.java | 2 tomcat10-10.1.52/java/org/apache/catalina/ssi/ExpressionTokenizer.java | 2 tomcat10-10.1.52/java/org/apache/catalina/ssi/ResponseIncludeWrapper.java | 5 tomcat10-10.1.52/java/org/apache/catalina/ssi/SSICommand.java | 5 tomcat10-10.1.52/java/org/apache/catalina/ssi/SSIConditional.java | 3 tomcat10-10.1.52/java/org/apache/catalina/ssi/SSIConditionalState.java | 4 tomcat10-10.1.52/java/org/apache/catalina/ssi/SSIConfig.java | 8 tomcat10-10.1.52/java/org/apache/catalina/ssi/SSIEcho.java | 5 tomcat10-10.1.52/java/org/apache/catalina/ssi/SSIExec.java | 12 tomcat10-10.1.52/java/org/apache/catalina/ssi/SSIExternalResolver.java | 4 tomcat10-10.1.52/java/org/apache/catalina/ssi/SSIFilter.java | 2 tomcat10-10.1.52/java/org/apache/catalina/ssi/SSIFlastmod.java | 11 tomcat10-10.1.52/java/org/apache/catalina/ssi/SSIFsize.java | 11 tomcat10-10.1.52/java/org/apache/catalina/ssi/SSIInclude.java | 11 tomcat10-10.1.52/java/org/apache/catalina/ssi/SSIMediator.java | 8 tomcat10-10.1.52/java/org/apache/catalina/ssi/SSIPrintenv.java | 5 tomcat10-10.1.52/java/org/apache/catalina/ssi/SSIProcessor.java | 3 tomcat10-10.1.52/java/org/apache/catalina/ssi/SSIServlet.java | 5 tomcat10-10.1.52/java/org/apache/catalina/ssi/SSIServletExternalResolver.java | 14 tomcat10-10.1.52/java/org/apache/catalina/ssi/SSISet.java | 6 tomcat10-10.1.52/java/org/apache/catalina/ssi/SSIStopProcessingException.java | 4 tomcat10-10.1.52/java/org/apache/catalina/startup/Bootstrap.java | 3 tomcat10-10.1.52/java/org/apache/catalina/startup/Catalina.java | 13 tomcat10-10.1.52/java/org/apache/catalina/startup/CatalinaBaseConfigurationSource.java | 10 tomcat10-10.1.52/java/org/apache/catalina/startup/CatalinaProperties.java | 4 tomcat10-10.1.52/java/org/apache/catalina/startup/ClassLoaderFactory.java | 2 tomcat10-10.1.52/java/org/apache/catalina/startup/Constants.java | 2 tomcat10-10.1.52/java/org/apache/catalina/startup/ContextConfig.java | 47 tomcat10-10.1.52/java/org/apache/catalina/startup/ContextRuleSet.java | 2 tomcat10-10.1.52/java/org/apache/catalina/startup/CopyParentClassLoaderRule.java | 2 tomcat10-10.1.52/java/org/apache/catalina/startup/EngineConfig.java | 2 tomcat10-10.1.52/java/org/apache/catalina/startup/EngineRuleSet.java | 2 tomcat10-10.1.52/java/org/apache/catalina/startup/ExpandWar.java | 16 tomcat10-10.1.52/java/org/apache/catalina/startup/FailedContext.java | 11 tomcat10-10.1.52/java/org/apache/catalina/startup/HomesUserDatabase.java | 2 tomcat10-10.1.52/java/org/apache/catalina/startup/HostConfig.java | 44 tomcat10-10.1.52/java/org/apache/catalina/startup/HostRuleSet.java | 2 tomcat10-10.1.52/java/org/apache/catalina/startup/ListenerCreateRule.java | 2 tomcat10-10.1.52/java/org/apache/catalina/startup/LocalStrings_ja.properties | 2 tomcat10-10.1.52/java/org/apache/catalina/startup/LocalStrings_ru.properties | 4 tomcat10-10.1.52/java/org/apache/catalina/startup/LocalStrings_zh_CN.properties | 4 tomcat10-10.1.52/java/org/apache/catalina/startup/MimeTypeMappings.properties | 9 tomcat10-10.1.52/java/org/apache/catalina/startup/NamingRuleSet.java | 3 tomcat10-10.1.52/java/org/apache/catalina/startup/PasswdUserDatabase.java | 2 tomcat10-10.1.52/java/org/apache/catalina/startup/Tomcat.java | 31 tomcat10-10.1.52/java/org/apache/catalina/startup/Tool.java | 2 tomcat10-10.1.52/java/org/apache/catalina/startup/UserConfig.java | 2 tomcat10-10.1.52/java/org/apache/catalina/startup/UserDatabase.java | 2 tomcat10-10.1.52/java/org/apache/catalina/storeconfig/ConnectorStoreAppender.java | 4 tomcat10-10.1.52/java/org/apache/catalina/storeconfig/LoaderSF.java | 6 tomcat10-10.1.52/java/org/apache/catalina/storeconfig/OpenSSLConfSF.java | 13 tomcat10-10.1.52/java/org/apache/catalina/storeconfig/StandardContextSF.java | 4 tomcat10-10.1.52/java/org/apache/catalina/storeconfig/StoreAppender.java | 6 tomcat10-10.1.52/java/org/apache/catalina/storeconfig/StoreConfigLifecycleListener.java | 4 tomcat10-10.1.52/java/org/apache/catalina/storeconfig/StoreContextAppender.java | 4 tomcat10-10.1.52/java/org/apache/catalina/storeconfig/StoreFactoryBase.java | 6 tomcat10-10.1.52/java/org/apache/catalina/storeconfig/StoreLoader.java | 4 tomcat10-10.1.52/java/org/apache/catalina/tribes/Channel.java | 10 tomcat10-10.1.52/java/org/apache/catalina/tribes/ChannelInterceptor.java | 4 tomcat10-10.1.52/java/org/apache/catalina/tribes/group/ChannelCoordinator.java | 23 tomcat10-10.1.52/java/org/apache/catalina/tribes/group/GroupChannel.java | 14 tomcat10-10.1.52/java/org/apache/catalina/tribes/group/LocalStrings.properties | 1 tomcat10-10.1.52/java/org/apache/catalina/tribes/group/LocalStrings_fr.properties | 1 tomcat10-10.1.52/java/org/apache/catalina/tribes/group/LocalStrings_ja.properties | 1 tomcat10-10.1.52/java/org/apache/catalina/tribes/group/RpcChannel.java | 12 tomcat10-10.1.52/java/org/apache/catalina/tribes/group/interceptors/FragmentationInterceptor.java | 4 tomcat10-10.1.52/java/org/apache/catalina/tribes/group/interceptors/GzipInterceptor.java | 8 tomcat10-10.1.52/java/org/apache/catalina/tribes/group/interceptors/LocalStrings.properties | 2 tomcat10-10.1.52/java/org/apache/catalina/tribes/group/interceptors/LocalStrings_fr.properties | 2 tomcat10-10.1.52/java/org/apache/catalina/tribes/group/interceptors/LocalStrings_ja.properties | 2 tomcat10-10.1.52/java/org/apache/catalina/tribes/group/interceptors/LocalStrings_ru.properties | 1 tomcat10-10.1.52/java/org/apache/catalina/tribes/group/interceptors/MessageDispatchInterceptor.java | 14 tomcat10-10.1.52/java/org/apache/catalina/tribes/group/interceptors/NonBlockingCoordinator.java | 39 tomcat10-10.1.52/java/org/apache/catalina/tribes/group/interceptors/SimpleCoordinator.java | 2 tomcat10-10.1.52/java/org/apache/catalina/tribes/group/interceptors/TcpFailureDetector.java | 10 tomcat10-10.1.52/java/org/apache/catalina/tribes/group/interceptors/TcpPingInterceptor.java | 4 tomcat10-10.1.52/java/org/apache/catalina/tribes/group/interceptors/TwoPhaseCommitInterceptor.java | 4 tomcat10-10.1.52/java/org/apache/catalina/tribes/io/ChannelData.java | 6 tomcat10-10.1.52/java/org/apache/catalina/tribes/io/LocalStrings_ru.properties | 2 tomcat10-10.1.52/java/org/apache/catalina/tribes/io/ObjectReader.java | 4 tomcat10-10.1.52/java/org/apache/catalina/tribes/io/ReplicationStream.java | 5 tomcat10-10.1.52/java/org/apache/catalina/tribes/jmx/LocalStrings_ru.properties | 19 tomcat10-10.1.52/java/org/apache/catalina/tribes/membership/Constants.java | 2 tomcat10-10.1.52/java/org/apache/catalina/tribes/membership/LocalStrings.properties | 1 tomcat10-10.1.52/java/org/apache/catalina/tribes/membership/LocalStrings_fr.properties | 1 tomcat10-10.1.52/java/org/apache/catalina/tribes/membership/LocalStrings_ja.properties | 1 tomcat10-10.1.52/java/org/apache/catalina/tribes/membership/McastService.java | 28 tomcat10-10.1.52/java/org/apache/catalina/tribes/membership/McastServiceImpl.java | 56 tomcat10-10.1.52/java/org/apache/catalina/tribes/membership/Membership.java | 2 tomcat10-10.1.52/java/org/apache/catalina/tribes/membership/StaticMember.java | 4 tomcat10-10.1.52/java/org/apache/catalina/tribes/membership/StaticMembershipProvider.java | 8 tomcat10-10.1.52/java/org/apache/catalina/tribes/membership/StaticMembershipService.java | 4 tomcat10-10.1.52/java/org/apache/catalina/tribes/membership/cloud/CertificateStreamProvider.java | 4 tomcat10-10.1.52/java/org/apache/catalina/tribes/membership/cloud/CloudMembershipService.java | 4 tomcat10-10.1.52/java/org/apache/catalina/tribes/membership/cloud/DNSMembershipProvider.java | 4 tomcat10-10.1.52/java/org/apache/catalina/tribes/membership/cloud/KubernetesMembershipProvider.java | 18 tomcat10-10.1.52/java/org/apache/catalina/tribes/membership/cloud/TokenStreamProvider.java | 4 tomcat10-10.1.52/java/org/apache/catalina/tribes/tipis/AbstractReplicatedMap.java | 53 tomcat10-10.1.52/java/org/apache/catalina/tribes/transport/Constants.java | 2 tomcat10-10.1.52/java/org/apache/catalina/tribes/transport/ReceiverBase.java | 8 tomcat10-10.1.52/java/org/apache/catalina/tribes/transport/RxTaskPool.java | 4 tomcat10-10.1.52/java/org/apache/catalina/tribes/transport/nio/NioReceiver.java | 52 tomcat10-10.1.52/java/org/apache/catalina/tribes/transport/nio/NioReplicationTask.java | 17 tomcat10-10.1.52/java/org/apache/catalina/tribes/transport/nio/NioSender.java | 61 tomcat10-10.1.52/java/org/apache/catalina/tribes/transport/nio/ParallelNioSender.java | 51 tomcat10-10.1.52/java/org/apache/catalina/tribes/transport/nio/PooledParallelSender.java | 4 tomcat10-10.1.52/java/org/apache/catalina/tribes/util/LocalStrings_ru.properties | 19 tomcat10-10.1.52/java/org/apache/catalina/tribes/util/StringManager.java | 18 tomcat10-10.1.52/java/org/apache/catalina/users/AbstractGroup.java | 2 tomcat10-10.1.52/java/org/apache/catalina/users/AbstractRole.java | 2 tomcat10-10.1.52/java/org/apache/catalina/users/AbstractUser.java | 2 tomcat10-10.1.52/java/org/apache/catalina/users/Constants.java | 2 tomcat10-10.1.52/java/org/apache/catalina/users/DataSourceUserDatabaseFactory.java | 2 tomcat10-10.1.52/java/org/apache/catalina/users/GenericGroup.java | 2 tomcat10-10.1.52/java/org/apache/catalina/users/GenericRole.java | 2 tomcat10-10.1.52/java/org/apache/catalina/users/GenericUser.java | 2 tomcat10-10.1.52/java/org/apache/catalina/users/MemoryGroup.java | 2 tomcat10-10.1.52/java/org/apache/catalina/users/MemoryRole.java | 2 tomcat10-10.1.52/java/org/apache/catalina/users/MemoryUser.java | 2 tomcat10-10.1.52/java/org/apache/catalina/users/MemoryUserDatabase.java | 20 tomcat10-10.1.52/java/org/apache/catalina/users/MemoryUserDatabaseFactory.java | 2 tomcat10-10.1.52/java/org/apache/catalina/util/CharsetMapper.java | 2 tomcat10-10.1.52/java/org/apache/catalina/util/CustomObjectInputStream.java | 3 tomcat10-10.1.52/java/org/apache/catalina/util/FilterUtil.java | 12 tomcat10-10.1.52/java/org/apache/catalina/util/IOTools.java | 4 tomcat10-10.1.52/java/org/apache/catalina/util/Introspection.java | 2 tomcat10-10.1.52/java/org/apache/catalina/util/LifecycleBase.java | 12 tomcat10-10.1.52/java/org/apache/catalina/util/ParameterMap.java | 16 tomcat10-10.1.52/java/org/apache/catalina/util/RateLimiterBase.java | 4 tomcat10-10.1.52/java/org/apache/catalina/util/RequestUtil.java | 52 tomcat10-10.1.52/java/org/apache/catalina/util/ResourceSet.java | 2 tomcat10-10.1.52/java/org/apache/catalina/util/ServerInfo.java | 2 tomcat10-10.1.52/java/org/apache/catalina/util/Strftime.java | 3 tomcat10-10.1.52/java/org/apache/catalina/util/TimeBucketCounterBase.java | 6 tomcat10-10.1.52/java/org/apache/catalina/util/URLEncoder.java | 19 tomcat10-10.1.52/java/org/apache/catalina/util/XMLWriter.java | 4 tomcat10-10.1.52/java/org/apache/catalina/valves/AbstractAccessLogValve.java | 132 tomcat10-10.1.52/java/org/apache/catalina/valves/AccessLogValve.java | 28 tomcat10-10.1.52/java/org/apache/catalina/valves/Constants.java | 2 tomcat10-10.1.52/java/org/apache/catalina/valves/CrawlerSessionManagerValve.java | 22 tomcat10-10.1.52/java/org/apache/catalina/valves/ErrorReportValve.java | 17 tomcat10-10.1.52/java/org/apache/catalina/valves/ExtendedAccessLogValve.java | 80 tomcat10-10.1.52/java/org/apache/catalina/valves/JDBCAccessLogValve.java | 3 tomcat10-10.1.52/java/org/apache/catalina/valves/JsonAccessLogValve.java | 7 tomcat10-10.1.52/java/org/apache/catalina/valves/JsonErrorReportValve.java | 7 tomcat10-10.1.52/java/org/apache/catalina/valves/LocalStrings.properties | 7 tomcat10-10.1.52/java/org/apache/catalina/valves/LocalStrings_fr.properties | 9 tomcat10-10.1.52/java/org/apache/catalina/valves/LocalStrings_ja.properties | 9 tomcat10-10.1.52/java/org/apache/catalina/valves/LocalStrings_ru.properties | 5 tomcat10-10.1.52/java/org/apache/catalina/valves/LocalStrings_zh_CN.properties | 2 tomcat10-10.1.52/java/org/apache/catalina/valves/ParameterLimitValve.java | 282 tomcat10-10.1.52/java/org/apache/catalina/valves/PersistentValve.java | 2 tomcat10-10.1.52/java/org/apache/catalina/valves/ProxyErrorReportValve.java | 2 tomcat10-10.1.52/java/org/apache/catalina/valves/RemoteAddrValve.java | 3 tomcat10-10.1.52/java/org/apache/catalina/valves/RemoteHostValve.java | 2 tomcat10-10.1.52/java/org/apache/catalina/valves/RemoteIpValve.java | 21 tomcat10-10.1.52/java/org/apache/catalina/valves/RequestFilterValve.java | 2 tomcat10-10.1.52/java/org/apache/catalina/valves/SemaphoreValve.java | 2 tomcat10-10.1.52/java/org/apache/catalina/valves/StuckThreadDetectionValve.java | 4 tomcat10-10.1.52/java/org/apache/catalina/valves/ValveBase.java | 2 tomcat10-10.1.52/java/org/apache/catalina/valves/rewrite/LocalStrings.properties | 2 tomcat10-10.1.52/java/org/apache/catalina/valves/rewrite/LocalStrings_fr.properties | 2 tomcat10-10.1.52/java/org/apache/catalina/valves/rewrite/LocalStrings_ja.properties | 2 tomcat10-10.1.52/java/org/apache/catalina/valves/rewrite/QuotedStringTokenizer.java | 2 tomcat10-10.1.52/java/org/apache/catalina/valves/rewrite/RandomizedTextRewriteMap.java | 9 tomcat10-10.1.52/java/org/apache/catalina/valves/rewrite/ResolverImpl.java | 34 tomcat10-10.1.52/java/org/apache/catalina/valves/rewrite/RewriteValve.java | 90 tomcat10-10.1.52/java/org/apache/catalina/webresources/AbstractArchiveResourceSet.java | 42 tomcat10-10.1.52/java/org/apache/catalina/webresources/AbstractFileResourceSet.java | 67 tomcat10-10.1.52/java/org/apache/catalina/webresources/AbstractResource.java | 12 tomcat10-10.1.52/java/org/apache/catalina/webresources/AbstractResourceSet.java | 22 tomcat10-10.1.52/java/org/apache/catalina/webresources/AbstractSingleArchiveResource.java | 4 tomcat10-10.1.52/java/org/apache/catalina/webresources/Cache.java | 5 tomcat10-10.1.52/java/org/apache/catalina/webresources/CachedResource.java | 7 tomcat10-10.1.52/java/org/apache/catalina/webresources/DirResourceSet.java | 21 tomcat10-10.1.52/java/org/apache/catalina/webresources/EmptyResource.java | 2 tomcat10-10.1.52/java/org/apache/catalina/webresources/EmptyResourceSet.java | 19 tomcat10-10.1.52/java/org/apache/catalina/webresources/FileResource.java | 4 tomcat10-10.1.52/java/org/apache/catalina/webresources/JarContents.java | 94 tomcat10-10.1.52/java/org/apache/catalina/webresources/JarWarResource.java | 4 tomcat10-10.1.52/java/org/apache/catalina/webresources/JarWarResourceSet.java | 26 tomcat10-10.1.52/java/org/apache/catalina/webresources/LocalStrings.properties | 1 tomcat10-10.1.52/java/org/apache/catalina/webresources/LocalStrings_fr.properties | 1 tomcat10-10.1.52/java/org/apache/catalina/webresources/LocalStrings_ja.properties | 1 tomcat10-10.1.52/java/org/apache/catalina/webresources/LocalStrings_ru.properties | 2 tomcat10-10.1.52/java/org/apache/catalina/webresources/StandardRoot.java | 2 tomcat10-10.1.52/java/org/apache/catalina/webresources/TomcatJarInputStream.java | 2 tomcat10-10.1.52/java/org/apache/coyote/AbstractProcessor.java | 20 tomcat10-10.1.52/java/org/apache/coyote/AbstractProtocol.java | 29 tomcat10-10.1.52/java/org/apache/coyote/ActionCode.java | 2 tomcat10-10.1.52/java/org/apache/coyote/ActionHook.java | 2 tomcat10-10.1.52/java/org/apache/coyote/Adapter.java | 2 tomcat10-10.1.52/java/org/apache/coyote/CompressionConfig.java | 10 tomcat10-10.1.52/java/org/apache/coyote/Constants.java | 2 tomcat10-10.1.52/java/org/apache/coyote/OutputBuffer.java | 2 tomcat10-10.1.52/java/org/apache/coyote/ProtocolHandler.java | 3 tomcat10-10.1.52/java/org/apache/coyote/Request.java | 75 tomcat10-10.1.52/java/org/apache/coyote/RequestInfo.java | 20 tomcat10-10.1.52/java/org/apache/coyote/Response.java | 9 tomcat10-10.1.52/java/org/apache/coyote/ajp/AjpMessage.java | 16 tomcat10-10.1.52/java/org/apache/coyote/ajp/AjpProcessor.java | 81 tomcat10-10.1.52/java/org/apache/coyote/ajp/Constants.java | 20 tomcat10-10.1.52/java/org/apache/coyote/http11/AbstractHttp11Protocol.java | 6 tomcat10-10.1.52/java/org/apache/coyote/http11/Constants.java | 2 tomcat10-10.1.52/java/org/apache/coyote/http11/Http11InputBuffer.java | 5 tomcat10-10.1.52/java/org/apache/coyote/http11/Http11Processor.java | 40 tomcat10-10.1.52/java/org/apache/coyote/http11/InputFilter.java | 2 tomcat10-10.1.52/java/org/apache/coyote/http11/LocalStrings.properties | 1 tomcat10-10.1.52/java/org/apache/coyote/http11/OutputFilter.java | 2 tomcat10-10.1.52/java/org/apache/coyote/http11/filters/ChunkedInputFilter.java | 21 tomcat10-10.1.52/java/org/apache/coyote/http11/filters/ChunkedOutputFilter.java | 2 tomcat10-10.1.52/java/org/apache/coyote/http11/filters/GzipOutputFilter.java | 6 tomcat10-10.1.52/java/org/apache/coyote/http11/filters/IdentityInputFilter.java | 2 tomcat10-10.1.52/java/org/apache/coyote/http11/filters/IdentityOutputFilter.java | 2 tomcat10-10.1.52/java/org/apache/coyote/http11/filters/SavedRequestInputFilter.java | 9 tomcat10-10.1.52/java/org/apache/coyote/http11/filters/VoidInputFilter.java | 2 tomcat10-10.1.52/java/org/apache/coyote/http11/filters/VoidOutputFilter.java | 2 tomcat10-10.1.52/java/org/apache/coyote/http11/upgrade/UpgradeServletInputStream.java | 8 tomcat10-10.1.52/java/org/apache/coyote/http2/AbstractNonZeroStream.java | 4 tomcat10-10.1.52/java/org/apache/coyote/http2/ConnectionSettingsBase.java | 19 tomcat10-10.1.52/java/org/apache/coyote/http2/ConnectionSettingsLocal.java | 5 tomcat10-10.1.52/java/org/apache/coyote/http2/Hpack.java | 33 tomcat10-10.1.52/java/org/apache/coyote/http2/HpackDecoder.java | 7 tomcat10-10.1.52/java/org/apache/coyote/http2/Http2AsyncUpgradeHandler.java | 20 tomcat10-10.1.52/java/org/apache/coyote/http2/Http2Parser.java | 8 tomcat10-10.1.52/java/org/apache/coyote/http2/Http2Protocol.java | 5 tomcat10-10.1.52/java/org/apache/coyote/http2/Http2UpgradeHandler.java | 123 tomcat10-10.1.52/java/org/apache/coyote/http2/LocalStrings.properties | 2 tomcat10-10.1.52/java/org/apache/coyote/http2/LocalStrings_fr.properties | 3 tomcat10-10.1.52/java/org/apache/coyote/http2/LocalStrings_ja.properties | 5 tomcat10-10.1.52/java/org/apache/coyote/http2/RecycledStream.java | 4 tomcat10-10.1.52/java/org/apache/coyote/http2/Stream.java | 27 tomcat10-10.1.52/java/org/apache/coyote/http2/StreamProcessor.java | 19 tomcat10-10.1.52/java/org/apache/el/ExpressionFactoryImpl.java | 3 tomcat10-10.1.52/java/org/apache/el/MethodExpressionImpl.java | 2 tomcat10-10.1.52/java/org/apache/el/ValueExpressionImpl.java | 2 tomcat10-10.1.52/java/org/apache/el/lang/ELArithmetic.java | 4 tomcat10-10.1.52/java/org/apache/el/lang/ELSupport.java | 17 tomcat10-10.1.52/java/org/apache/el/lang/ExpressionBuilder.java | 3 tomcat10-10.1.52/java/org/apache/el/lang/FunctionMapperFactory.java | 3 tomcat10-10.1.52/java/org/apache/el/lang/FunctionMapperImpl.java | 4 tomcat10-10.1.52/java/org/apache/el/parser/ArithmeticNode.java | 3 tomcat10-10.1.52/java/org/apache/el/parser/AstAnd.java | 3 tomcat10-10.1.52/java/org/apache/el/parser/AstBracketSuffix.java | 3 tomcat10-10.1.52/java/org/apache/el/parser/AstChoice.java | 3 tomcat10-10.1.52/java/org/apache/el/parser/AstCompositeExpression.java | 3 tomcat10-10.1.52/java/org/apache/el/parser/AstDeferredExpression.java | 3 tomcat10-10.1.52/java/org/apache/el/parser/AstDiv.java | 3 tomcat10-10.1.52/java/org/apache/el/parser/AstDotSuffix.java | 3 tomcat10-10.1.52/java/org/apache/el/parser/AstDynamicExpression.java | 3 tomcat10-10.1.52/java/org/apache/el/parser/AstEqual.java | 3 tomcat10-10.1.52/java/org/apache/el/parser/AstFalse.java | 3 tomcat10-10.1.52/java/org/apache/el/parser/AstFloatingPoint.java | 3 tomcat10-10.1.52/java/org/apache/el/parser/AstFunction.java | 3 tomcat10-10.1.52/java/org/apache/el/parser/AstGreaterThan.java | 3 tomcat10-10.1.52/java/org/apache/el/parser/AstGreaterThanEqual.java | 3 tomcat10-10.1.52/java/org/apache/el/parser/AstIdentifier.java | 3 tomcat10-10.1.52/java/org/apache/el/parser/AstInteger.java | 3 tomcat10-10.1.52/java/org/apache/el/parser/AstLessThan.java | 3 tomcat10-10.1.52/java/org/apache/el/parser/AstLessThanEqual.java | 3 tomcat10-10.1.52/java/org/apache/el/parser/AstLiteralExpression.java | 3 tomcat10-10.1.52/java/org/apache/el/parser/AstMinus.java | 3 tomcat10-10.1.52/java/org/apache/el/parser/AstMod.java | 3 tomcat10-10.1.52/java/org/apache/el/parser/AstMult.java | 3 tomcat10-10.1.52/java/org/apache/el/parser/AstNegative.java | 3 tomcat10-10.1.52/java/org/apache/el/parser/AstNot.java | 3 tomcat10-10.1.52/java/org/apache/el/parser/AstNotEqual.java | 3 tomcat10-10.1.52/java/org/apache/el/parser/AstNull.java | 3 tomcat10-10.1.52/java/org/apache/el/parser/AstOr.java | 3 tomcat10-10.1.52/java/org/apache/el/parser/AstPlus.java | 3 tomcat10-10.1.52/java/org/apache/el/parser/AstString.java | 3 tomcat10-10.1.52/java/org/apache/el/parser/AstTrue.java | 3 tomcat10-10.1.52/java/org/apache/el/parser/AstValue.java | 7 tomcat10-10.1.52/java/org/apache/el/parser/BooleanNode.java | 3 tomcat10-10.1.52/java/org/apache/el/parser/ELParser.java | 78 tomcat10-10.1.52/java/org/apache/el/parser/ELParser.jjt | 10 tomcat10-10.1.52/java/org/apache/el/parser/ELParserConstants.java | 41 tomcat10-10.1.52/java/org/apache/el/parser/ELParserTokenManager.java | 958 tomcat10-10.1.52/java/org/apache/el/parser/Node.java | 4 tomcat10-10.1.52/java/org/apache/el/parser/NodeVisitor.java | 3 tomcat10-10.1.52/java/org/apache/el/parser/SimpleNode.java | 3 tomcat10-10.1.52/java/org/apache/el/util/MessageFactory.java | 3 tomcat10-10.1.52/java/org/apache/el/util/ReflectionUtil.java | 17 tomcat10-10.1.52/java/org/apache/jasper/Constants.java | 5 tomcat10-10.1.52/java/org/apache/jasper/EmbeddedServletOptions.java | 16 tomcat10-10.1.52/java/org/apache/jasper/JasperException.java | 2 tomcat10-10.1.52/java/org/apache/jasper/JspC.java | 39 tomcat10-10.1.52/java/org/apache/jasper/JspCompilationContext.java | 25 tomcat10-10.1.52/java/org/apache/jasper/Options.java | 12 tomcat10-10.1.52/java/org/apache/jasper/compiler/AntCompiler.java | 7 tomcat10-10.1.52/java/org/apache/jasper/compiler/BeanRepository.java | 3 tomcat10-10.1.52/java/org/apache/jasper/compiler/Collector.java | 4 tomcat10-10.1.52/java/org/apache/jasper/compiler/Compiler.java | 11 tomcat10-10.1.52/java/org/apache/jasper/compiler/DefaultErrorHandler.java | 2 tomcat10-10.1.52/java/org/apache/jasper/compiler/ELFunctionMapper.java | 5 tomcat10-10.1.52/java/org/apache/jasper/compiler/ELNode.java | 3 tomcat10-10.1.52/java/org/apache/jasper/compiler/ELParser.java | 3 tomcat10-10.1.52/java/org/apache/jasper/compiler/ErrorDispatcher.java | 3 tomcat10-10.1.52/java/org/apache/jasper/compiler/ErrorHandler.java | 15 tomcat10-10.1.52/java/org/apache/jasper/compiler/Generator.java | 246 tomcat10-10.1.52/java/org/apache/jasper/compiler/ImplicitTagLibraryInfo.java | 2 tomcat10-10.1.52/java/org/apache/jasper/compiler/JDTCompiler.java | 30 tomcat10-10.1.52/java/org/apache/jasper/compiler/JavaCompiler.java | 11 tomcat10-10.1.52/java/org/apache/jasper/compiler/JavacErrorDetail.java | 3 tomcat10-10.1.52/java/org/apache/jasper/compiler/JspConfig.java | 4 tomcat10-10.1.52/java/org/apache/jasper/compiler/JspDocumentParser.java | 12 tomcat10-10.1.52/java/org/apache/jasper/compiler/JspReader.java | 21 tomcat10-10.1.52/java/org/apache/jasper/compiler/JspRuntimeContext.java | 2 tomcat10-10.1.52/java/org/apache/jasper/compiler/JspUtil.java | 9 tomcat10-10.1.52/java/org/apache/jasper/compiler/Localizer.java | 2 tomcat10-10.1.52/java/org/apache/jasper/compiler/Mark.java | 2 tomcat10-10.1.52/java/org/apache/jasper/compiler/Node.java | 10 tomcat10-10.1.52/java/org/apache/jasper/compiler/PageDataImpl.java | 2 tomcat10-10.1.52/java/org/apache/jasper/compiler/PageInfo.java | 6 tomcat10-10.1.52/java/org/apache/jasper/compiler/Parser.java | 24 tomcat10-10.1.52/java/org/apache/jasper/compiler/ParserController.java | 3 tomcat10-10.1.52/java/org/apache/jasper/compiler/ScriptingVariabler.java | 2 tomcat10-10.1.52/java/org/apache/jasper/compiler/ServletWriter.java | 3 tomcat10-10.1.52/java/org/apache/jasper/compiler/SmapStratum.java | 3 tomcat10-10.1.52/java/org/apache/jasper/compiler/SmapUtil.java | 6 tomcat10-10.1.52/java/org/apache/jasper/compiler/TagFileProcessor.java | 5 tomcat10-10.1.52/java/org/apache/jasper/compiler/TagLibraryInfoImpl.java | 12 tomcat10-10.1.52/java/org/apache/jasper/compiler/TagPluginManager.java | 2 tomcat10-10.1.52/java/org/apache/jasper/compiler/TldCache.java | 2 tomcat10-10.1.52/java/org/apache/jasper/compiler/Validator.java | 7 tomcat10-10.1.52/java/org/apache/jasper/compiler/tagplugin/TagPluginContext.java | 4 tomcat10-10.1.52/java/org/apache/jasper/el/ELContextImpl.java | 4 tomcat10-10.1.52/java/org/apache/jasper/el/ELContextWrapper.java | 2 tomcat10-10.1.52/java/org/apache/jasper/el/JasperELResolver.java | 8 tomcat10-10.1.52/java/org/apache/jasper/el/JspValueExpression.java | 4 tomcat10-10.1.52/java/org/apache/jasper/optimizations/ELInterpreterTagSetters.java | 38 tomcat10-10.1.52/java/org/apache/jasper/optimizations/StringInterpreterEnum.java | 4 tomcat10-10.1.52/java/org/apache/jasper/runtime/BodyContentImpl.java | 9 tomcat10-10.1.52/java/org/apache/jasper/runtime/HttpJspBase.java | 2 tomcat10-10.1.52/java/org/apache/jasper/runtime/JspApplicationContextImpl.java | 4 tomcat10-10.1.52/java/org/apache/jasper/runtime/JspContextWrapper.java | 6 tomcat10-10.1.52/java/org/apache/jasper/runtime/JspFactoryImpl.java | 4 tomcat10-10.1.52/java/org/apache/jasper/runtime/JspFragmentHelper.java | 2 tomcat10-10.1.52/java/org/apache/jasper/runtime/JspRuntimeLibrary.java | 122 tomcat10-10.1.52/java/org/apache/jasper/runtime/JspWriterImpl.java | 10 tomcat10-10.1.52/java/org/apache/jasper/runtime/PageContextImpl.java | 22 tomcat10-10.1.52/java/org/apache/jasper/runtime/ProtectedFunctionMapper.java | 3 tomcat10-10.1.52/java/org/apache/jasper/runtime/ServletResponseWrapperInclude.java | 3 tomcat10-10.1.52/java/org/apache/jasper/runtime/TagHandlerPool.java | 4 tomcat10-10.1.52/java/org/apache/jasper/servlet/JasperLoader.java | 5 tomcat10-10.1.52/java/org/apache/jasper/servlet/JspCServletContext.java | 11 tomcat10-10.1.52/java/org/apache/jasper/servlet/JspServlet.java | 27 tomcat10-10.1.52/java/org/apache/jasper/servlet/JspServletWrapper.java | 43 tomcat10-10.1.52/java/org/apache/jasper/tagplugins/jstl/core/Import.java | 5 tomcat10-10.1.52/java/org/apache/juli/AsyncFileHandler.java | 8 tomcat10-10.1.52/java/org/apache/juli/ClassLoaderLogManager.java | 24 tomcat10-10.1.52/java/org/apache/juli/FileHandler.java | 20 tomcat10-10.1.52/java/org/apache/juli/JdkLoggerFormatter.java | 6 tomcat10-10.1.52/java/org/apache/juli/JsonFormatter.java | 38 tomcat10-10.1.52/java/org/apache/juli/LogUtil.java | 64 tomcat10-10.1.52/java/org/apache/juli/OneLineFormatter.java | 51 tomcat10-10.1.52/java/org/apache/juli/VerbatimFormatter.java | 7 tomcat10-10.1.52/java/org/apache/juli/logging/Log.java | 14 tomcat10-10.1.52/java/org/apache/juli/logging/LogConfigurationException.java | 2 tomcat10-10.1.52/java/org/apache/juli/logging/LogFactory.java | 6 tomcat10-10.1.52/java/org/apache/naming/ContextAccessController.java | 22 tomcat10-10.1.52/java/org/apache/naming/ContextBindings.java | 76 tomcat10-10.1.52/java/org/apache/naming/EjbRef.java | 27 tomcat10-10.1.52/java/org/apache/naming/HandlerRef.java | 24 tomcat10-10.1.52/java/org/apache/naming/LocalStrings.properties | 4 tomcat10-10.1.52/java/org/apache/naming/LocalStrings_cs.properties | 1 tomcat10-10.1.52/java/org/apache/naming/LocalStrings_de.properties | 2 tomcat10-10.1.52/java/org/apache/naming/LocalStrings_es.properties | 3 tomcat10-10.1.52/java/org/apache/naming/LocalStrings_fr.properties | 4 tomcat10-10.1.52/java/org/apache/naming/LocalStrings_ja.properties | 4 tomcat10-10.1.52/java/org/apache/naming/LocalStrings_ko.properties | 2 tomcat10-10.1.52/java/org/apache/naming/LocalStrings_ru.properties | 2 tomcat10-10.1.52/java/org/apache/naming/LocalStrings_zh_CN.properties | 3 tomcat10-10.1.52/java/org/apache/naming/NameParserImpl.java | 8 tomcat10-10.1.52/java/org/apache/naming/NamingContext.java | 195 tomcat10-10.1.52/java/org/apache/naming/NamingContextBindingsEnumeration.java | 20 tomcat10-10.1.52/java/org/apache/naming/NamingContextEnumeration.java | 14 tomcat10-10.1.52/java/org/apache/naming/NamingEntry.java | 5 tomcat10-10.1.52/java/org/apache/naming/ResourceEnvRef.java | 5 tomcat10-10.1.52/java/org/apache/naming/ResourceLinkRef.java | 17 tomcat10-10.1.52/java/org/apache/naming/ResourceRef.java | 42 tomcat10-10.1.52/java/org/apache/naming/SelectorContext.java | 158 tomcat10-10.1.52/java/org/apache/naming/ServiceRef.java | 26 tomcat10-10.1.52/java/org/apache/naming/StringManager.java | 93 tomcat10-10.1.52/java/org/apache/naming/TransactionRef.java | 7 tomcat10-10.1.52/java/org/apache/naming/factory/BeanFactory.java | 35 tomcat10-10.1.52/java/org/apache/naming/factory/Constants.java | 3 tomcat10-10.1.52/java/org/apache/naming/factory/DataSourceLinkFactory.java | 56 tomcat10-10.1.52/java/org/apache/naming/factory/EjbFactory.java | 10 tomcat10-10.1.52/java/org/apache/naming/factory/FactoryBase.java | 40 tomcat10-10.1.52/java/org/apache/naming/factory/LookupFactory.java | 28 tomcat10-10.1.52/java/org/apache/naming/factory/MailSessionFactory.java | 44 tomcat10-10.1.52/java/org/apache/naming/factory/OpenEjbFactory.java | 35 tomcat10-10.1.52/java/org/apache/naming/factory/ResourceEnvFactory.java | 2 tomcat10-10.1.52/java/org/apache/naming/factory/ResourceFactory.java | 18 tomcat10-10.1.52/java/org/apache/naming/factory/ResourceLinkFactory.java | 46 tomcat10-10.1.52/java/org/apache/naming/factory/SendMailFactory.java | 90 tomcat10-10.1.52/java/org/apache/naming/factory/TransactionFactory.java | 2 tomcat10-10.1.52/java/org/apache/naming/factory/webservices/ServiceProxy.java | 21 tomcat10-10.1.52/java/org/apache/naming/factory/webservices/ServiceRefFactory.java | 30 tomcat10-10.1.52/java/org/apache/naming/java/javaURLContextFactory.java | 59 tomcat10-10.1.52/java/org/apache/tomcat/ContextBind.java | 46 tomcat10-10.1.52/java/org/apache/tomcat/InstanceManager.java | 30 tomcat10-10.1.52/java/org/apache/tomcat/InstanceManagerBindings.java | 4 tomcat10-10.1.52/java/org/apache/tomcat/InstrumentableClassLoader.java | 50 tomcat10-10.1.52/java/org/apache/tomcat/Jar.java | 59 tomcat10-10.1.52/java/org/apache/tomcat/JarScanFilter.java | 16 tomcat10-10.1.52/java/org/apache/tomcat/JarScanner.java | 22 tomcat10-10.1.52/java/org/apache/tomcat/JarScannerCallback.java | 31 tomcat10-10.1.52/java/org/apache/tomcat/SimpleInstanceManager.java | 18 tomcat10-10.1.52/java/org/apache/tomcat/buildutil/CheckEol.java | 44 tomcat10-10.1.52/java/org/apache/tomcat/buildutil/MimeTypeMappings.java | 4 tomcat10-10.1.52/java/org/apache/tomcat/buildutil/RepeatableArchive.java | 8 tomcat10-10.1.52/java/org/apache/tomcat/buildutil/Txt2Html.java | 92 tomcat10-10.1.52/java/org/apache/tomcat/buildutil/translate/BackportEnglish.java | 8 tomcat10-10.1.52/java/org/apache/tomcat/buildutil/translate/BackportTranslations.java | 9 tomcat10-10.1.52/java/org/apache/tomcat/buildutil/translate/Import.java | 3 tomcat10-10.1.52/java/org/apache/tomcat/buildutil/translate/Utils.java | 34 tomcat10-10.1.52/java/org/apache/tomcat/dbcp/dbcp2/AbandonedTrace.java | 14 tomcat10-10.1.52/java/org/apache/tomcat/dbcp/dbcp2/BasicDataSource.java | 46 tomcat10-10.1.52/java/org/apache/tomcat/dbcp/dbcp2/BasicDataSourceFactory.java | 81 tomcat10-10.1.52/java/org/apache/tomcat/dbcp/dbcp2/BasicDataSourceMXBean.java | 2 tomcat10-10.1.52/java/org/apache/tomcat/dbcp/dbcp2/ConnectionFactory.java | 8 tomcat10-10.1.52/java/org/apache/tomcat/dbcp/dbcp2/ConnectionFactoryFactory.java | 2 tomcat10-10.1.52/java/org/apache/tomcat/dbcp/dbcp2/Constants.java | 12 tomcat10-10.1.52/java/org/apache/tomcat/dbcp/dbcp2/DataSourceConnectionFactory.java | 12 tomcat10-10.1.52/java/org/apache/tomcat/dbcp/dbcp2/DataSourceMXBean.java | 2 tomcat10-10.1.52/java/org/apache/tomcat/dbcp/dbcp2/DelegatingCallableStatement.java | 2 tomcat10-10.1.52/java/org/apache/tomcat/dbcp/dbcp2/DelegatingConnection.java | 33 tomcat10-10.1.52/java/org/apache/tomcat/dbcp/dbcp2/DelegatingDatabaseMetaData.java | 13 tomcat10-10.1.52/java/org/apache/tomcat/dbcp/dbcp2/DelegatingPreparedStatement.java | 9 tomcat10-10.1.52/java/org/apache/tomcat/dbcp/dbcp2/DelegatingResultSet.java | 21 tomcat10-10.1.52/java/org/apache/tomcat/dbcp/dbcp2/DelegatingStatement.java | 47 tomcat10-10.1.52/java/org/apache/tomcat/dbcp/dbcp2/DriverConnectionFactory.java | 4 tomcat10-10.1.52/java/org/apache/tomcat/dbcp/dbcp2/DriverFactory.java | 4 tomcat10-10.1.52/java/org/apache/tomcat/dbcp/dbcp2/DriverManagerConnectionFactory.java | 16 tomcat10-10.1.52/java/org/apache/tomcat/dbcp/dbcp2/Jdbc41Bridge.java | 12 tomcat10-10.1.52/java/org/apache/tomcat/dbcp/dbcp2/LifetimeExceededException.java | 2 tomcat10-10.1.52/java/org/apache/tomcat/dbcp/dbcp2/ListException.java | 5 tomcat10-10.1.52/java/org/apache/tomcat/dbcp/dbcp2/LocalStrings.properties | 2 tomcat10-10.1.52/java/org/apache/tomcat/dbcp/dbcp2/ObjectNameWrapper.java | 6 tomcat10-10.1.52/java/org/apache/tomcat/dbcp/dbcp2/PStmtKey.java | 196 tomcat10-10.1.52/java/org/apache/tomcat/dbcp/dbcp2/PoolableCallableStatement.java | 2 tomcat10-10.1.52/java/org/apache/tomcat/dbcp/dbcp2/PoolableConnection.java | 44 tomcat10-10.1.52/java/org/apache/tomcat/dbcp/dbcp2/PoolableConnectionFactory.java | 56 tomcat10-10.1.52/java/org/apache/tomcat/dbcp/dbcp2/PoolableConnectionMXBean.java | 2 tomcat10-10.1.52/java/org/apache/tomcat/dbcp/dbcp2/PoolablePreparedStatement.java | 2 tomcat10-10.1.52/java/org/apache/tomcat/dbcp/dbcp2/PoolingConnection.java | 40 tomcat10-10.1.52/java/org/apache/tomcat/dbcp/dbcp2/PoolingDataSource.java | 5 tomcat10-10.1.52/java/org/apache/tomcat/dbcp/dbcp2/PoolingDriver.java | 2 tomcat10-10.1.52/java/org/apache/tomcat/dbcp/dbcp2/SQLExceptionList.java | 6 tomcat10-10.1.52/java/org/apache/tomcat/dbcp/dbcp2/SwallowedExceptionLogger.java | 2 tomcat10-10.1.52/java/org/apache/tomcat/dbcp/dbcp2/Utils.java | 6 tomcat10-10.1.52/java/org/apache/tomcat/dbcp/dbcp2/cpdsadapter/ConnectionImpl.java | 67 tomcat10-10.1.52/java/org/apache/tomcat/dbcp/dbcp2/cpdsadapter/DriverAdapterCPDS.java | 56 tomcat10-10.1.52/java/org/apache/tomcat/dbcp/dbcp2/cpdsadapter/PStmtKeyCPDS.java | 26 tomcat10-10.1.52/java/org/apache/tomcat/dbcp/dbcp2/cpdsadapter/PooledConnectionImpl.java | 157 tomcat10-10.1.52/java/org/apache/tomcat/dbcp/dbcp2/cpdsadapter/package-info.java | 2 tomcat10-10.1.52/java/org/apache/tomcat/dbcp/dbcp2/datasources/AbstractConnectionFactory.java | 147 tomcat10-10.1.52/java/org/apache/tomcat/dbcp/dbcp2/datasources/CPDSConnectionFactory.java | 221 tomcat10-10.1.52/java/org/apache/tomcat/dbcp/dbcp2/datasources/CharArray.java | 26 tomcat10-10.1.52/java/org/apache/tomcat/dbcp/dbcp2/datasources/InstanceKeyDataSource.java | 208 tomcat10-10.1.52/java/org/apache/tomcat/dbcp/dbcp2/datasources/InstanceKeyDataSourceFactory.java | 10 tomcat10-10.1.52/java/org/apache/tomcat/dbcp/dbcp2/datasources/KeyedCPDSConnectionFactory.java | 182 tomcat10-10.1.52/java/org/apache/tomcat/dbcp/dbcp2/datasources/PerUserPoolDataSource.java | 9 tomcat10-10.1.52/java/org/apache/tomcat/dbcp/dbcp2/datasources/PerUserPoolDataSourceFactory.java | 11 tomcat10-10.1.52/java/org/apache/tomcat/dbcp/dbcp2/datasources/PoolKey.java | 7 tomcat10-10.1.52/java/org/apache/tomcat/dbcp/dbcp2/datasources/PooledConnectionAndInfo.java | 2 tomcat10-10.1.52/java/org/apache/tomcat/dbcp/dbcp2/datasources/PooledConnectionManager.java | 31 tomcat10-10.1.52/java/org/apache/tomcat/dbcp/dbcp2/datasources/SharedPoolDataSource.java | 7 tomcat10-10.1.52/java/org/apache/tomcat/dbcp/dbcp2/datasources/SharedPoolDataSourceFactory.java | 4 tomcat10-10.1.52/java/org/apache/tomcat/dbcp/dbcp2/datasources/UserPassKey.java | 20 tomcat10-10.1.52/java/org/apache/tomcat/dbcp/dbcp2/datasources/package-info.java | 2 tomcat10-10.1.52/java/org/apache/tomcat/dbcp/dbcp2/managed/BasicManagedDataSource.java | 11 tomcat10-10.1.52/java/org/apache/tomcat/dbcp/dbcp2/managed/DataSourceXAConnectionFactory.java | 38 tomcat10-10.1.52/java/org/apache/tomcat/dbcp/dbcp2/managed/LocalXAConnectionFactory.java | 20 tomcat10-10.1.52/java/org/apache/tomcat/dbcp/dbcp2/managed/ManagedConnection.java | 34 tomcat10-10.1.52/java/org/apache/tomcat/dbcp/dbcp2/managed/ManagedDataSource.java | 2 tomcat10-10.1.52/java/org/apache/tomcat/dbcp/dbcp2/managed/PoolableManagedConnection.java | 2 tomcat10-10.1.52/java/org/apache/tomcat/dbcp/dbcp2/managed/PoolableManagedConnectionFactory.java | 2 tomcat10-10.1.52/java/org/apache/tomcat/dbcp/dbcp2/managed/SynchronizationAdapter.java | 2 tomcat10-10.1.52/java/org/apache/tomcat/dbcp/dbcp2/managed/TransactionContext.java | 2 tomcat10-10.1.52/java/org/apache/tomcat/dbcp/dbcp2/managed/TransactionContextListener.java | 2 tomcat10-10.1.52/java/org/apache/tomcat/dbcp/dbcp2/managed/TransactionRegistry.java | 2 tomcat10-10.1.52/java/org/apache/tomcat/dbcp/dbcp2/managed/XAConnectionFactory.java | 2 tomcat10-10.1.52/java/org/apache/tomcat/dbcp/dbcp2/managed/package-info.java | 3 tomcat10-10.1.52/java/org/apache/tomcat/dbcp/dbcp2/package-info.java | 2 tomcat10-10.1.52/java/org/apache/tomcat/dbcp/pool2/BaseObject.java | 9 tomcat10-10.1.52/java/org/apache/tomcat/dbcp/pool2/BaseObjectPool.java | 9 tomcat10-10.1.52/java/org/apache/tomcat/dbcp/pool2/DestroyMode.java | 2 tomcat10-10.1.52/java/org/apache/tomcat/dbcp/pool2/KeyedObjectPool.java | 2 tomcat10-10.1.52/java/org/apache/tomcat/dbcp/pool2/KeyedPooledObjectFactory.java | 4 tomcat10-10.1.52/java/org/apache/tomcat/dbcp/pool2/ObjectPool.java | 2 tomcat10-10.1.52/java/org/apache/tomcat/dbcp/pool2/PoolUtils.java | 50 tomcat10-10.1.52/java/org/apache/tomcat/dbcp/pool2/PooledObject.java | 33 tomcat10-10.1.52/java/org/apache/tomcat/dbcp/pool2/PooledObjectFactory.java | 164 tomcat10-10.1.52/java/org/apache/tomcat/dbcp/pool2/PooledObjectState.java | 2 tomcat10-10.1.52/java/org/apache/tomcat/dbcp/pool2/SwallowedExceptionListener.java | 2 tomcat10-10.1.52/java/org/apache/tomcat/dbcp/pool2/TrackedUse.java | 2 tomcat10-10.1.52/java/org/apache/tomcat/dbcp/pool2/UsageTracking.java | 2 tomcat10-10.1.52/java/org/apache/tomcat/dbcp/pool2/impl/AbandonedConfig.java | 2 tomcat10-10.1.52/java/org/apache/tomcat/dbcp/pool2/impl/BaseGenericObjectPool.java | 126 tomcat10-10.1.52/java/org/apache/tomcat/dbcp/pool2/impl/BaseObjectPoolConfig.java | 62 tomcat10-10.1.52/java/org/apache/tomcat/dbcp/pool2/impl/CallStack.java | 2 tomcat10-10.1.52/java/org/apache/tomcat/dbcp/pool2/impl/DefaultEvictionPolicy.java | 11 tomcat10-10.1.52/java/org/apache/tomcat/dbcp/pool2/impl/DefaultPooledObject.java | 2 tomcat10-10.1.52/java/org/apache/tomcat/dbcp/pool2/impl/DefaultPooledObjectInfo.java | 2 tomcat10-10.1.52/java/org/apache/tomcat/dbcp/pool2/impl/DefaultPooledObjectInfoMBean.java | 2 tomcat10-10.1.52/java/org/apache/tomcat/dbcp/pool2/impl/EvictionConfig.java | 2 tomcat10-10.1.52/java/org/apache/tomcat/dbcp/pool2/impl/EvictionPolicy.java | 4 tomcat10-10.1.52/java/org/apache/tomcat/dbcp/pool2/impl/EvictionTimer.java | 35 tomcat10-10.1.52/java/org/apache/tomcat/dbcp/pool2/impl/GenericKeyedObjectPool.java | 257 tomcat10-10.1.52/java/org/apache/tomcat/dbcp/pool2/impl/GenericKeyedObjectPoolConfig.java | 82 tomcat10-10.1.52/java/org/apache/tomcat/dbcp/pool2/impl/GenericKeyedObjectPoolMXBean.java | 2 tomcat10-10.1.52/java/org/apache/tomcat/dbcp/pool2/impl/GenericObjectPool.java | 233 tomcat10-10.1.52/java/org/apache/tomcat/dbcp/pool2/impl/GenericObjectPoolConfig.java | 9 tomcat10-10.1.52/java/org/apache/tomcat/dbcp/pool2/impl/GenericObjectPoolMXBean.java | 2 tomcat10-10.1.52/java/org/apache/tomcat/dbcp/pool2/impl/InterruptibleReentrantLock.java | 8 tomcat10-10.1.52/java/org/apache/tomcat/dbcp/pool2/impl/LinkedBlockingDeque.java | 70 tomcat10-10.1.52/java/org/apache/tomcat/dbcp/pool2/impl/NoOpCallStack.java | 4 tomcat10-10.1.52/java/org/apache/tomcat/dbcp/pool2/impl/PoolImplUtils.java | 34 tomcat10-10.1.52/java/org/apache/tomcat/dbcp/pool2/impl/PooledSoftReference.java | 2 tomcat10-10.1.52/java/org/apache/tomcat/dbcp/pool2/impl/SoftReferenceObjectPool.java | 14 tomcat10-10.1.52/java/org/apache/tomcat/dbcp/pool2/impl/ThrowableCallStack.java | 4 tomcat10-10.1.52/java/org/apache/tomcat/jni/AprStatus.java | 89 tomcat10-10.1.52/java/org/apache/tomcat/jni/Buffer.java | 3 tomcat10-10.1.52/java/org/apache/tomcat/jni/CertificateVerifier.java | 13 tomcat10-10.1.52/java/org/apache/tomcat/jni/FileInfo.java | 7 tomcat10-10.1.52/java/org/apache/tomcat/jni/Library.java | 46 tomcat10-10.1.52/java/org/apache/tomcat/jni/LibraryNotFoundError.java | 10 tomcat10-10.1.52/java/org/apache/tomcat/jni/Pool.java | 15 tomcat10-10.1.52/java/org/apache/tomcat/jni/SSL.java | 529 tomcat10-10.1.52/java/org/apache/tomcat/jni/SSLConf.java | 38 tomcat10-10.1.52/java/org/apache/tomcat/jni/SSLContext.java | 395 tomcat10-10.1.52/java/org/apache/tomcat/jni/Sockaddr.java | 7 tomcat10-10.1.52/java/org/apache/tomcat/util/Diagnostics.java | 166 tomcat10-10.1.52/java/org/apache/tomcat/util/ExceptionUtils.java | 17 tomcat10-10.1.52/java/org/apache/tomcat/util/IntrospectionUtils.java | 200 tomcat10-10.1.52/java/org/apache/tomcat/util/MultiThrowable.java | 17 tomcat10-10.1.52/java/org/apache/tomcat/util/XReflectionIntrospectionUtils.java | 4 tomcat10-10.1.52/java/org/apache/tomcat/util/bcel/Const.java | 16 tomcat10-10.1.52/java/org/apache/tomcat/util/bcel/classfile/Utility.java | 5 tomcat10-10.1.52/java/org/apache/tomcat/util/buf/AbstractChunk.java | 21 tomcat10-10.1.52/java/org/apache/tomcat/util/buf/Ascii.java | 3 tomcat10-10.1.52/java/org/apache/tomcat/util/buf/ByteChunk.java | 27 tomcat10-10.1.52/java/org/apache/tomcat/util/buf/CharChunk.java | 5 tomcat10-10.1.52/java/org/apache/tomcat/util/buf/HexUtils.java | 8 tomcat10-10.1.52/java/org/apache/tomcat/util/buf/MessageBytes.java | 4 tomcat10-10.1.52/java/org/apache/tomcat/util/buf/StringCache.java | 8 tomcat10-10.1.52/java/org/apache/tomcat/util/buf/StringUtils.java | 6 tomcat10-10.1.52/java/org/apache/tomcat/util/buf/UDecoder.java | 8 tomcat10-10.1.52/java/org/apache/tomcat/util/buf/UEncoder.java | 2 tomcat10-10.1.52/java/org/apache/tomcat/util/codec/binary/Base64.java | 267 tomcat10-10.1.52/java/org/apache/tomcat/util/codec/binary/BaseNCodec.java | 167 tomcat10-10.1.52/java/org/apache/tomcat/util/codec/binary/StringUtils.java | 70 tomcat10-10.1.52/java/org/apache/tomcat/util/codec/binary/package-info.java | 4 tomcat10-10.1.52/java/org/apache/tomcat/util/collections/CaseInsensitiveKeyMap.java | 22 tomcat10-10.1.52/java/org/apache/tomcat/util/collections/ConcurrentCache.java | 2 tomcat10-10.1.52/java/org/apache/tomcat/util/collections/ConcurrentLruCache.java | 4 tomcat10-10.1.52/java/org/apache/tomcat/util/collections/ManagedConcurrentWeakHashMap.java | 30 tomcat10-10.1.52/java/org/apache/tomcat/util/collections/SynchronizedQueue.java | 8 tomcat10-10.1.52/java/org/apache/tomcat/util/collections/SynchronizedStack.java | 8 tomcat10-10.1.52/java/org/apache/tomcat/util/compat/Jre20Compat.java | 66 tomcat10-10.1.52/java/org/apache/tomcat/util/compat/Jre21Compat.java | 2 tomcat10-10.1.52/java/org/apache/tomcat/util/compat/Jre22Compat.java | 4 tomcat10-10.1.52/java/org/apache/tomcat/util/compat/JreCompat.java | 30 tomcat10-10.1.52/java/org/apache/tomcat/util/concurrent/KeyedReentrantReadWriteLock.java | 179 tomcat10-10.1.52/java/org/apache/tomcat/util/concurrent/LocalStrings.properties | 19 tomcat10-10.1.52/java/org/apache/tomcat/util/concurrent/LocalStrings_fr.properties | 19 tomcat10-10.1.52/java/org/apache/tomcat/util/concurrent/LocalStrings_ja.properties | 19 tomcat10-10.1.52/java/org/apache/tomcat/util/descriptor/Constants.java | 3 tomcat10-10.1.52/java/org/apache/tomcat/util/descriptor/DigesterFactory.java | 35 tomcat10-10.1.52/java/org/apache/tomcat/util/descriptor/LocalResolver.java | 43 tomcat10-10.1.52/java/org/apache/tomcat/util/descriptor/XmlErrorHandler.java | 9 tomcat10-10.1.52/java/org/apache/tomcat/util/descriptor/XmlIdentifiers.java | 33 tomcat10-10.1.52/java/org/apache/tomcat/util/descriptor/tagplugin/TagPluginParser.java | 7 tomcat10-10.1.52/java/org/apache/tomcat/util/descriptor/tld/ImplicitTldRuleSet.java | 3 tomcat10-10.1.52/java/org/apache/tomcat/util/descriptor/tld/TagFileXml.java | 5 tomcat10-10.1.52/java/org/apache/tomcat/util/descriptor/tld/TagXml.java | 6 tomcat10-10.1.52/java/org/apache/tomcat/util/descriptor/tld/TaglibXml.java | 8 tomcat10-10.1.52/java/org/apache/tomcat/util/descriptor/tld/TldParser.java | 9 tomcat10-10.1.52/java/org/apache/tomcat/util/descriptor/tld/TldResourcePath.java | 30 tomcat10-10.1.52/java/org/apache/tomcat/util/descriptor/tld/TldRuleSet.java | 45 tomcat10-10.1.52/java/org/apache/tomcat/util/descriptor/tld/ValidatorXml.java | 4 tomcat10-10.1.52/java/org/apache/tomcat/util/descriptor/web/ApplicationParameter.java | 13 tomcat10-10.1.52/java/org/apache/tomcat/util/descriptor/web/Constants.java | 3 tomcat10-10.1.52/java/org/apache/tomcat/util/descriptor/web/ContextEjb.java | 9 tomcat10-10.1.52/java/org/apache/tomcat/util/descriptor/web/ContextEnvironment.java | 10 tomcat10-10.1.52/java/org/apache/tomcat/util/descriptor/web/ContextHandler.java | 22 tomcat10-10.1.52/java/org/apache/tomcat/util/descriptor/web/ContextLocalEjb.java | 9 tomcat10-10.1.52/java/org/apache/tomcat/util/descriptor/web/ContextResource.java | 29 tomcat10-10.1.52/java/org/apache/tomcat/util/descriptor/web/ContextResourceEnvRef.java | 11 tomcat10-10.1.52/java/org/apache/tomcat/util/descriptor/web/ContextResourceLink.java | 11 tomcat10-10.1.52/java/org/apache/tomcat/util/descriptor/web/ContextService.java | 58 tomcat10-10.1.52/java/org/apache/tomcat/util/descriptor/web/ContextTransaction.java | 14 tomcat10-10.1.52/java/org/apache/tomcat/util/descriptor/web/ErrorPage.java | 11 tomcat10-10.1.52/java/org/apache/tomcat/util/descriptor/web/FilterDef.java | 27 tomcat10-10.1.52/java/org/apache/tomcat/util/descriptor/web/FilterMap.java | 25 tomcat10-10.1.52/java/org/apache/tomcat/util/descriptor/web/FragmentJarScannerCallback.java | 11 tomcat10-10.1.52/java/org/apache/tomcat/util/descriptor/web/Injectable.java | 2 tomcat10-10.1.52/java/org/apache/tomcat/util/descriptor/web/JspConfigDescriptorImpl.java | 2 tomcat10-10.1.52/java/org/apache/tomcat/util/descriptor/web/JspPropertyGroup.java | 81 tomcat10-10.1.52/java/org/apache/tomcat/util/descriptor/web/JspPropertyGroupDescriptorImpl.java | 10 tomcat10-10.1.52/java/org/apache/tomcat/util/descriptor/web/LocalStrings_es.properties | 1 tomcat10-10.1.52/java/org/apache/tomcat/util/descriptor/web/LoginConfig.java | 42 tomcat10-10.1.52/java/org/apache/tomcat/util/descriptor/web/MessageDestination.java | 17 tomcat10-10.1.52/java/org/apache/tomcat/util/descriptor/web/MessageDestinationRef.java | 8 tomcat10-10.1.52/java/org/apache/tomcat/util/descriptor/web/MultipartDef.java | 14 tomcat10-10.1.52/java/org/apache/tomcat/util/descriptor/web/NamingResources.java | 9 tomcat10-10.1.52/java/org/apache/tomcat/util/descriptor/web/ResourceBase.java | 13 tomcat10-10.1.52/java/org/apache/tomcat/util/descriptor/web/SecurityCollection.java | 62 tomcat10-10.1.52/java/org/apache/tomcat/util/descriptor/web/SecurityConstraint.java | 185 tomcat10-10.1.52/java/org/apache/tomcat/util/descriptor/web/SecurityRoleRef.java | 8 tomcat10-10.1.52/java/org/apache/tomcat/util/descriptor/web/ServletDef.java | 29 tomcat10-10.1.52/java/org/apache/tomcat/util/descriptor/web/SessionConfig.java | 22 tomcat10-10.1.52/java/org/apache/tomcat/util/descriptor/web/TaglibDescriptorImpl.java | 3 tomcat10-10.1.52/java/org/apache/tomcat/util/descriptor/web/WebRuleSet.java | 944 tomcat10-10.1.52/java/org/apache/tomcat/util/descriptor/web/WebXml.java | 958 tomcat10-10.1.52/java/org/apache/tomcat/util/descriptor/web/WebXmlParser.java | 46 tomcat10-10.1.52/java/org/apache/tomcat/util/descriptor/web/XmlEncodingBase.java | 10 tomcat10-10.1.52/java/org/apache/tomcat/util/digester/AbstractObjectCreationFactory.java | 24 tomcat10-10.1.52/java/org/apache/tomcat/util/digester/ArrayStack.java | 70 tomcat10-10.1.52/java/org/apache/tomcat/util/digester/CallMethodRule.java | 198 tomcat10-10.1.52/java/org/apache/tomcat/util/digester/CallParamRule.java | 66 tomcat10-10.1.52/java/org/apache/tomcat/util/digester/Digester.java | 543 tomcat10-10.1.52/java/org/apache/tomcat/util/digester/DocumentProperties.java | 6 tomcat10-10.1.52/java/org/apache/tomcat/util/digester/EnvironmentPropertySource.java | 19 tomcat10-10.1.52/java/org/apache/tomcat/util/digester/FactoryCreateRule.java | 50 tomcat10-10.1.52/java/org/apache/tomcat/util/digester/ObjectCreateRule.java | 39 tomcat10-10.1.52/java/org/apache/tomcat/util/digester/ObjectCreationFactory.java | 25 tomcat10-10.1.52/java/org/apache/tomcat/util/digester/Rule.java | 66 tomcat10-10.1.52/java/org/apache/tomcat/util/digester/RuleSet.java | 31 tomcat10-10.1.52/java/org/apache/tomcat/util/digester/Rules.java | 36 tomcat10-10.1.52/java/org/apache/tomcat/util/digester/RulesBase.java | 80 tomcat10-10.1.52/java/org/apache/tomcat/util/digester/ServiceBindingPropertySource.java | 40 tomcat10-10.1.52/java/org/apache/tomcat/util/digester/SetNextRule.java | 88 tomcat10-10.1.52/java/org/apache/tomcat/util/digester/SetPropertiesRule.java | 25 tomcat10-10.1.52/java/org/apache/tomcat/util/digester/SystemPropertySource.java | 5 tomcat10-10.1.52/java/org/apache/tomcat/util/file/ConfigFileLoader.java | 14 tomcat10-10.1.52/java/org/apache/tomcat/util/file/ConfigurationSource.java | 53 tomcat10-10.1.52/java/org/apache/tomcat/util/file/Matcher.java | 75 tomcat10-10.1.52/java/org/apache/tomcat/util/http/CookiesWithoutEquals.java | 44 tomcat10-10.1.52/java/org/apache/tomcat/util/http/FastHttpDateFormat.java | 6 tomcat10-10.1.52/java/org/apache/tomcat/util/http/HeaderUtil.java | 2 tomcat10-10.1.52/java/org/apache/tomcat/util/http/Method.java | 164 tomcat10-10.1.52/java/org/apache/tomcat/util/http/MimeHeaders.java | 56 tomcat10-10.1.52/java/org/apache/tomcat/util/http/Parameters.java | 8 tomcat10-10.1.52/java/org/apache/tomcat/util/http/ResponseUtil.java | 4 tomcat10-10.1.52/java/org/apache/tomcat/util/http/Rfc6265CookieProcessor.java | 3 tomcat10-10.1.52/java/org/apache/tomcat/util/http/WebdavIfHeader.java | 383 tomcat10-10.1.52/java/org/apache/tomcat/util/http/fileupload/FileItem.java | 140 tomcat10-10.1.52/java/org/apache/tomcat/util/http/fileupload/FileItemHeaders.java | 22 tomcat10-10.1.52/java/org/apache/tomcat/util/http/fileupload/FileItemStream.java | 49 tomcat10-10.1.52/java/org/apache/tomcat/util/http/fileupload/FileUpload.java | 12 tomcat10-10.1.52/java/org/apache/tomcat/util/http/fileupload/FileUploadBase.java | 504 tomcat10-10.1.52/java/org/apache/tomcat/util/http/fileupload/FileUploadException.java | 12 tomcat10-10.1.52/java/org/apache/tomcat/util/http/fileupload/InvalidFileNameException.java | 10 tomcat10-10.1.52/java/org/apache/tomcat/util/http/fileupload/MultipartStream.java | 1045 - tomcat10-10.1.52/java/org/apache/tomcat/util/http/fileupload/ParameterParser.java | 292 tomcat10-10.1.52/java/org/apache/tomcat/util/http/fileupload/ProgressListener.java | 8 tomcat10-10.1.52/java/org/apache/tomcat/util/http/fileupload/RFC2231Utility.java | 158 tomcat10-10.1.52/java/org/apache/tomcat/util/http/fileupload/disk/DiskFileItem.java | 652 tomcat10-10.1.52/java/org/apache/tomcat/util/http/fileupload/disk/DiskFileItemFactory.java | 115 tomcat10-10.1.52/java/org/apache/tomcat/util/http/fileupload/impl/FileItemIteratorImpl.java | 1 tomcat10-10.1.52/java/org/apache/tomcat/util/http/fileupload/package-info.java | 4 tomcat10-10.1.52/java/org/apache/tomcat/util/http/fileupload/servlet/ServletRequestContext.java | 40 tomcat10-10.1.52/java/org/apache/tomcat/util/http/fileupload/util/FileItemHeadersImpl.java | 37 tomcat10-10.1.52/java/org/apache/tomcat/util/http/fileupload/util/LimitedInputStream.java | 81 tomcat10-10.1.52/java/org/apache/tomcat/util/http/fileupload/util/Streams.java | 74 tomcat10-10.1.52/java/org/apache/tomcat/util/http/fileupload/util/mime/MimeUtility.java | 18 tomcat10-10.1.52/java/org/apache/tomcat/util/http/fileupload/util/mime/ParseException.java | 2 tomcat10-10.1.52/java/org/apache/tomcat/util/http/fileupload/util/mime/QuotedPrintableDecoder.java | 53 tomcat10-10.1.52/java/org/apache/tomcat/util/http/fileupload/util/mime/RFC2231Utility.java | 154 tomcat10-10.1.52/java/org/apache/tomcat/util/http/parser/Cookie.java | 4 tomcat10-10.1.52/java/org/apache/tomcat/util/http/parser/HttpHeaderParser.java | 9 tomcat10-10.1.52/java/org/apache/tomcat/util/http/parser/LocalStrings_es.properties | 1 tomcat10-10.1.52/java/org/apache/tomcat/util/http/parser/MediaType.java | 8 tomcat10-10.1.52/java/org/apache/tomcat/util/http/parser/MediaTypeCache.java | 2 tomcat10-10.1.52/java/org/apache/tomcat/util/json/JSONFilter.java | 22 tomcat10-10.1.52/java/org/apache/tomcat/util/json/JSONParser.java | 1170 - tomcat10-10.1.52/java/org/apache/tomcat/util/json/JSONParserConstants.java | 165 tomcat10-10.1.52/java/org/apache/tomcat/util/json/JSONParserTokenManager.java | 1660 - tomcat10-10.1.52/java/org/apache/tomcat/util/json/JavaCharStream.java | 1149 - tomcat10-10.1.52/java/org/apache/tomcat/util/json/ParseException.java | 330 tomcat10-10.1.52/java/org/apache/tomcat/util/json/Token.java | 217 tomcat10-10.1.52/java/org/apache/tomcat/util/json/TokenMgrError.java | 264 tomcat10-10.1.52/java/org/apache/tomcat/util/log/CaptureLog.java | 2 tomcat10-10.1.52/java/org/apache/tomcat/util/log/SystemLogHandler.java | 15 tomcat10-10.1.52/java/org/apache/tomcat/util/log/UserDataHelper.java | 38 tomcat10-10.1.52/java/org/apache/tomcat/util/modeler/AttributeInfo.java | 35 tomcat10-10.1.52/java/org/apache/tomcat/util/modeler/BaseAttributeFilter.java | 47 tomcat10-10.1.52/java/org/apache/tomcat/util/modeler/BaseModelMBean.java | 457 tomcat10-10.1.52/java/org/apache/tomcat/util/modeler/BaseNotificationBroadcaster.java | 57 tomcat10-10.1.52/java/org/apache/tomcat/util/modeler/FeatureInfo.java | 12 tomcat10-10.1.52/java/org/apache/tomcat/util/modeler/LocalStrings_fr.properties | 1 tomcat10-10.1.52/java/org/apache/tomcat/util/modeler/LocalStrings_ja.properties | 1 tomcat10-10.1.52/java/org/apache/tomcat/util/modeler/ManagedBean.java | 113 tomcat10-10.1.52/java/org/apache/tomcat/util/modeler/NoDescriptorRegistry.java | 84 tomcat10-10.1.52/java/org/apache/tomcat/util/modeler/NotificationInfo.java | 25 tomcat10-10.1.52/java/org/apache/tomcat/util/modeler/OperationInfo.java | 35 tomcat10-10.1.52/java/org/apache/tomcat/util/modeler/ParameterInfo.java | 17 tomcat10-10.1.52/java/org/apache/tomcat/util/modeler/Registry.java | 195 tomcat10-10.1.52/java/org/apache/tomcat/util/modeler/RegistryMBean.java | 84 tomcat10-10.1.52/java/org/apache/tomcat/util/modeler/modules/MbeansDescriptorsDigesterSource.java | 137 tomcat10-10.1.52/java/org/apache/tomcat/util/modeler/modules/MbeansDescriptorsIntrospectionSource.java | 128 tomcat10-10.1.52/java/org/apache/tomcat/util/modeler/modules/ModelerSource.java | 9 tomcat10-10.1.52/java/org/apache/tomcat/util/net/AbstractEndpoint.java | 541 tomcat10-10.1.52/java/org/apache/tomcat/util/net/AbstractJsseEndpoint.java | 119 tomcat10-10.1.52/java/org/apache/tomcat/util/net/Acceptor.java | 43 tomcat10-10.1.52/java/org/apache/tomcat/util/net/ApplicationBufferHandler.java | 7 tomcat10-10.1.52/java/org/apache/tomcat/util/net/Constants.java | 21 tomcat10-10.1.52/java/org/apache/tomcat/util/net/DispatchType.java | 5 tomcat10-10.1.52/java/org/apache/tomcat/util/net/IPv6Utils.java | 65 tomcat10-10.1.52/java/org/apache/tomcat/util/net/LocalStrings.properties | 6 tomcat10-10.1.52/java/org/apache/tomcat/util/net/LocalStrings_fr.properties | 2 tomcat10-10.1.52/java/org/apache/tomcat/util/net/LocalStrings_ja.properties | 5 tomcat10-10.1.52/java/org/apache/tomcat/util/net/LocalStrings_ko.properties | 1 tomcat10-10.1.52/java/org/apache/tomcat/util/net/LocalStrings_zh_CN.properties | 1 tomcat10-10.1.52/java/org/apache/tomcat/util/net/Nio2Channel.java | 80 tomcat10-10.1.52/java/org/apache/tomcat/util/net/Nio2Endpoint.java | 233 tomcat10-10.1.52/java/org/apache/tomcat/util/net/NioChannel.java | 63 tomcat10-10.1.52/java/org/apache/tomcat/util/net/NioEndpoint.java | 370 tomcat10-10.1.52/java/org/apache/tomcat/util/net/SSLContext.java | 8 tomcat10-10.1.52/java/org/apache/tomcat/util/net/SSLHostConfig.java | 332 tomcat10-10.1.52/java/org/apache/tomcat/util/net/SSLHostConfigCertificate.java | 68 tomcat10-10.1.52/java/org/apache/tomcat/util/net/SSLImplementation.java | 26 tomcat10-10.1.52/java/org/apache/tomcat/util/net/SSLSessionManager.java | 3 tomcat10-10.1.52/java/org/apache/tomcat/util/net/SSLSupport.java | 86 tomcat10-10.1.52/java/org/apache/tomcat/util/net/SSLUtil.java | 40 tomcat10-10.1.52/java/org/apache/tomcat/util/net/SSLUtilBase.java | 154 tomcat10-10.1.52/java/org/apache/tomcat/util/net/SecureNio2Channel.java | 473 tomcat10-10.1.52/java/org/apache/tomcat/util/net/SecureNioChannel.java | 328 tomcat10-10.1.52/java/org/apache/tomcat/util/net/SendfileDataBase.java | 20 tomcat10-10.1.52/java/org/apache/tomcat/util/net/SendfileKeepAliveState.java | 12 tomcat10-10.1.52/java/org/apache/tomcat/util/net/SendfileState.java | 6 tomcat10-10.1.52/java/org/apache/tomcat/util/net/SocketBufferHandler.java | 14 tomcat10-10.1.52/java/org/apache/tomcat/util/net/SocketEvent.java | 24 tomcat10-10.1.52/java/org/apache/tomcat/util/net/SocketProperties.java | 125 tomcat10-10.1.52/java/org/apache/tomcat/util/net/SocketWrapperBase.java | 742 tomcat10-10.1.52/java/org/apache/tomcat/util/net/TLSClientHelloExtractor.java | 127 tomcat10-10.1.52/java/org/apache/tomcat/util/net/WriteBuffer.java | 22 tomcat10-10.1.52/java/org/apache/tomcat/util/net/jsse/JSSEImplementation.java | 9 tomcat10-10.1.52/java/org/apache/tomcat/util/net/jsse/JSSEKeyManager.java | 34 tomcat10-10.1.52/java/org/apache/tomcat/util/net/jsse/JSSESSLContext.java | 3 tomcat10-10.1.52/java/org/apache/tomcat/util/net/jsse/JSSESupport.java | 50 tomcat10-10.1.52/java/org/apache/tomcat/util/net/jsse/JSSEUtil.java | 20 tomcat10-10.1.52/java/org/apache/tomcat/util/net/jsse/LocalStrings.properties | 2 tomcat10-10.1.52/java/org/apache/tomcat/util/net/jsse/LocalStrings_fr.properties | 1 tomcat10-10.1.52/java/org/apache/tomcat/util/net/jsse/LocalStrings_ja.properties | 1 tomcat10-10.1.52/java/org/apache/tomcat/util/net/jsse/PEMFile.java | 15 tomcat10-10.1.52/java/org/apache/tomcat/util/net/mbeans-descriptors.xml | 3 tomcat10-10.1.52/java/org/apache/tomcat/util/net/openssl/OpenSSLCertificateVerifier.java | 60 tomcat10-10.1.52/java/org/apache/tomcat/util/net/openssl/OpenSSLConfCmd.java | 14 tomcat10-10.1.52/java/org/apache/tomcat/util/net/openssl/OpenSSLContext.java | 194 tomcat10-10.1.52/java/org/apache/tomcat/util/net/openssl/OpenSSLEngine.java | 221 tomcat10-10.1.52/java/org/apache/tomcat/util/net/openssl/OpenSSLImplementation.java | 2 tomcat10-10.1.52/java/org/apache/tomcat/util/net/openssl/OpenSSLSessionContext.java | 14 tomcat10-10.1.52/java/org/apache/tomcat/util/net/openssl/OpenSSLSessionStats.java | 24 tomcat10-10.1.52/java/org/apache/tomcat/util/net/openssl/OpenSSLStatus.java | 51 tomcat10-10.1.52/java/org/apache/tomcat/util/net/openssl/OpenSSLUtil.java | 11 tomcat10-10.1.52/java/org/apache/tomcat/util/net/openssl/OpenSSLX509Certificate.java | 14 tomcat10-10.1.52/java/org/apache/tomcat/util/net/openssl/ciphers/Authentication.java | 24 tomcat10-10.1.52/java/org/apache/tomcat/util/net/openssl/ciphers/Cipher.java | 37 tomcat10-10.1.52/java/org/apache/tomcat/util/net/openssl/ciphers/Group.java | 82 tomcat10-10.1.52/java/org/apache/tomcat/util/net/openssl/ciphers/KeyExchange.java | 20 tomcat10-10.1.52/java/org/apache/tomcat/util/net/openssl/ciphers/OpenSSLCipherConfigurationParser.java | 221 tomcat10-10.1.52/java/org/apache/tomcat/util/net/openssl/ciphers/Protocol.java | 5 tomcat10-10.1.52/java/org/apache/tomcat/util/net/openssl/ciphers/SignatureScheme.java | 100 tomcat10-10.1.52/java/org/apache/tomcat/util/net/openssl/panama/LocalStrings.properties | 1 tomcat10-10.1.52/java/org/apache/tomcat/util/net/openssl/panama/LocalStrings_fr.properties | 1 tomcat10-10.1.52/java/org/apache/tomcat/util/net/openssl/panama/LocalStrings_ja.properties | 1 tomcat10-10.1.52/java/org/apache/tomcat/util/net/openssl/panama/OpenSSLContext.java | 440 tomcat10-10.1.52/java/org/apache/tomcat/util/net/openssl/panama/OpenSSLEngine.java | 434 tomcat10-10.1.52/java/org/apache/tomcat/util/net/openssl/panama/OpenSSLImplementation.java | 2 tomcat10-10.1.52/java/org/apache/tomcat/util/net/openssl/panama/OpenSSLLibrary.java | 83 tomcat10-10.1.52/java/org/apache/tomcat/util/net/openssl/panama/OpenSSLSessionContext.java | 18 tomcat10-10.1.52/java/org/apache/tomcat/util/net/openssl/panama/OpenSSLSessionStats.java | 30 tomcat10-10.1.52/java/org/apache/tomcat/util/net/openssl/panama/OpenSSLUtil.java | 11 tomcat10-10.1.52/java/org/apache/tomcat/util/net/openssl/panama/OpenSSLX509Certificate.java | 14 tomcat10-10.1.52/java/org/apache/tomcat/util/openssl/SSL_CTX_set_alpn_select_cb$cb.java | 23 tomcat10-10.1.52/java/org/apache/tomcat/util/openssl/SSL_CTX_set_cert_verify_callback$cb.java | 15 tomcat10-10.1.52/java/org/apache/tomcat/util/openssl/SSL_CTX_set_tmp_dh_callback$dh.java | 16 tomcat10-10.1.52/java/org/apache/tomcat/util/openssl/SSL_CTX_set_verify$callback.java | 15 tomcat10-10.1.52/java/org/apache/tomcat/util/openssl/SSL_set_info_callback$cb.java | 17 tomcat10-10.1.52/java/org/apache/tomcat/util/openssl/SSL_set_verify$callback.java | 15 tomcat10-10.1.52/java/org/apache/tomcat/util/openssl/openssl_h.java |10176 ++++++---- tomcat10-10.1.52/java/org/apache/tomcat/util/openssl/openssl_h_Compatibility.java | 238 tomcat10-10.1.52/java/org/apache/tomcat/util/openssl/openssl_h_Macros.java | 78 tomcat10-10.1.52/java/org/apache/tomcat/util/openssl/pem_password_cb.java | 18 tomcat10-10.1.52/java/org/apache/tomcat/util/res/StringManager.java | 21 tomcat10-10.1.52/java/org/apache/tomcat/util/scan/AbstractInputStreamJar.java | 15 tomcat10-10.1.52/java/org/apache/tomcat/util/scan/Constants.java | 6 tomcat10-10.1.52/java/org/apache/tomcat/util/scan/JarFactory.java | 6 tomcat10-10.1.52/java/org/apache/tomcat/util/scan/JarFileUrlJar.java | 28 tomcat10-10.1.52/java/org/apache/tomcat/util/scan/JarFileUrlNestedJar.java | 7 tomcat10-10.1.52/java/org/apache/tomcat/util/scan/NonClosingJarInputStream.java | 10 tomcat10-10.1.52/java/org/apache/tomcat/util/scan/ReferenceCountedJar.java | 4 tomcat10-10.1.52/java/org/apache/tomcat/util/scan/StandardJarScanFilter.java | 39 tomcat10-10.1.52/java/org/apache/tomcat/util/scan/StandardJarScanner.java | 122 tomcat10-10.1.52/java/org/apache/tomcat/util/scan/UrlJar.java | 3 tomcat10-10.1.52/java/org/apache/tomcat/util/security/ConcurrentMessageDigest.java | 28 tomcat10-10.1.52/java/org/apache/tomcat/util/security/Escape.java | 52 tomcat10-10.1.52/java/org/apache/tomcat/util/security/KeyStoreUtil.java | 22 tomcat10-10.1.52/java/org/apache/tomcat/util/security/MD5Encoder.java | 17 tomcat10-10.1.52/java/org/apache/tomcat/util/security/PermissionCheck.java | 19 tomcat10-10.1.52/java/org/apache/tomcat/util/security/PrivilegedSetAccessControlContext.java | 2 tomcat10-10.1.52/java/org/apache/tomcat/util/threads/InlineExecutorService.java | 12 tomcat10-10.1.52/java/org/apache/tomcat/util/threads/LimitLatch.java | 43 tomcat10-10.1.52/java/org/apache/tomcat/util/threads/ResizableExecutor.java | 3 tomcat10-10.1.52/java/org/apache/tomcat/util/threads/RetryableQueue.java | 32 tomcat10-10.1.52/java/org/apache/tomcat/util/threads/ScheduledThreadPoolExecutor.java | 32 tomcat10-10.1.52/java/org/apache/tomcat/util/threads/StopPooledThreadException.java | 4 tomcat10-10.1.52/java/org/apache/tomcat/util/threads/TaskQueue.java | 39 tomcat10-10.1.52/java/org/apache/tomcat/util/threads/TaskThread.java | 19 tomcat10-10.1.52/java/org/apache/tomcat/util/threads/TaskThreadFactory.java | 6 tomcat10-10.1.52/java/org/apache/tomcat/util/threads/ThreadPoolExecutor.java | 1645 - tomcat10-10.1.52/java/org/apache/tomcat/util/xreflection/ObjectReflectionPropertyInspector.java | 181 tomcat10-10.1.52/java/org/apache/tomcat/util/xreflection/ReflectionLessCodeGenerator.java | 88 tomcat10-10.1.52/java/org/apache/tomcat/util/xreflection/ReflectionProperty.java | 4 tomcat10-10.1.52/java/org/apache/tomcat/util/xreflection/SetPropertyClass.java | 96 tomcat10-10.1.52/java/org/apache/tomcat/websocket/AsyncChannelGroupUtil.java | 6 tomcat10-10.1.52/java/org/apache/tomcat/websocket/AsyncChannelWrapper.java | 4 tomcat10-10.1.52/java/org/apache/tomcat/websocket/AsyncChannelWrapperNonSecure.java | 6 tomcat10-10.1.52/java/org/apache/tomcat/websocket/AsyncChannelWrapperSecure.java | 42 tomcat10-10.1.52/java/org/apache/tomcat/websocket/Authenticator.java | 4 tomcat10-10.1.52/java/org/apache/tomcat/websocket/BasicAuthenticator.java | 2 tomcat10-10.1.52/java/org/apache/tomcat/websocket/Constants.java | 27 tomcat10-10.1.52/java/org/apache/tomcat/websocket/DigestAuthenticator.java | 5 tomcat10-10.1.52/java/org/apache/tomcat/websocket/LocalStrings.properties | 3 tomcat10-10.1.52/java/org/apache/tomcat/websocket/LocalStrings_es.properties | 3 tomcat10-10.1.52/java/org/apache/tomcat/websocket/LocalStrings_fr.properties | 3 tomcat10-10.1.52/java/org/apache/tomcat/websocket/LocalStrings_ja.properties | 3 tomcat10-10.1.52/java/org/apache/tomcat/websocket/LocalStrings_ko.properties | 2 tomcat10-10.1.52/java/org/apache/tomcat/websocket/LocalStrings_zh_CN.properties | 2 tomcat10-10.1.52/java/org/apache/tomcat/websocket/PerMessageDeflate.java | 19 tomcat10-10.1.52/java/org/apache/tomcat/websocket/TransformationBuilder.java | 26 tomcat10-10.1.52/java/org/apache/tomcat/websocket/TransformationFactory.java | 37 tomcat10-10.1.52/java/org/apache/tomcat/websocket/Util.java | 33 tomcat10-10.1.52/java/org/apache/tomcat/websocket/WsFrameBase.java | 5 tomcat10-10.1.52/java/org/apache/tomcat/websocket/WsFrameClient.java | 16 tomcat10-10.1.52/java/org/apache/tomcat/websocket/WsHandshakeResponse.java | 8 tomcat10-10.1.52/java/org/apache/tomcat/websocket/WsRemoteEndpointImplBase.java | 55 tomcat10-10.1.52/java/org/apache/tomcat/websocket/WsSession.java | 33 tomcat10-10.1.52/java/org/apache/tomcat/websocket/WsWebSocketContainer.java | 68 tomcat10-10.1.52/java/org/apache/tomcat/websocket/pojo/PojoEndpointBase.java | 4 tomcat10-10.1.52/java/org/apache/tomcat/websocket/pojo/PojoEndpointServer.java | 6 tomcat10-10.1.52/java/org/apache/tomcat/websocket/pojo/PojoMethodMapping.java | 20 tomcat10-10.1.52/java/org/apache/tomcat/websocket/server/Constants.java | 6 tomcat10-10.1.52/java/org/apache/tomcat/websocket/server/UpgradeUtil.java | 19 tomcat10-10.1.52/java/org/apache/tomcat/websocket/server/UriTemplate.java | 8 tomcat10-10.1.52/java/org/apache/tomcat/websocket/server/WsFrameServer.java | 4 tomcat10-10.1.52/java/org/apache/tomcat/websocket/server/WsHandshakeRequest.java | 20 tomcat10-10.1.52/java/org/apache/tomcat/websocket/server/WsHttpUpgradeHandler.java | 12 tomcat10-10.1.52/java/org/apache/tomcat/websocket/server/WsMappingResult.java | 6 tomcat10-10.1.52/java/org/apache/tomcat/websocket/server/WsPerSessionServerEndpointConfig.java | 4 tomcat10-10.1.52/java/org/apache/tomcat/websocket/server/WsRemoteEndpointImplServer.java | 8 tomcat10-10.1.52/java/org/apache/tomcat/websocket/server/WsServerContainer.java | 17 tomcat10-10.1.52/java/org/apache/tomcat/websocket/server/WsWriteTimeout.java | 4 tomcat10-10.1.52/modules/cxf/.gitignore | 16 tomcat10-10.1.52/modules/cxf/pom.xml | 4 tomcat10-10.1.52/modules/jdbc-pool/NOTICE | 2 tomcat10-10.1.52/modules/jdbc-pool/doc/changelog.xml | 1 tomcat10-10.1.52/modules/jdbc-pool/doc/jdbc-pool.xml | 1 tomcat10-10.1.52/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/naming/GenericNamingResourcesFactory.java | 6 tomcat10-10.1.52/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/ConnectionPool.java | 30 tomcat10-10.1.52/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/DataSourceFactory.java | 8 tomcat10-10.1.52/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/PoolProperties.java | 10 tomcat10-10.1.52/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/PooledConnection.java | 6 tomcat10-10.1.52/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/Validator.java | 2 tomcat10-10.1.52/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/interceptor/StatementDecoratorInterceptor.java | 1 tomcat10-10.1.52/modules/jdbc-pool/src/test/java/org/apache/tomcat/jdbc/test/TestValidation.java | 25 tomcat10-10.1.52/modules/jdbc-pool/src/test/java/org/apache/tomcat/jdbc/test/driver/Connection.java | 4 tomcat10-10.1.52/modules/owb/.gitignore | 16 tomcat10-10.1.52/modules/stuffed/.gitignore | 16 tomcat10-10.1.52/modules/stuffed/conf/.gitignore | 16 tomcat10-10.1.52/modules/stuffed/webapps/.gitignore | 16 tomcat10-10.1.52/res/bnd/tomcat-embed-core.jar.tmp.bnd | 1 tomcat10-10.1.52/res/bnd/tomcat-util.jar.tmp.bnd | 1 tomcat10-10.1.52/res/checkstyle/header-al2.txt | 2 tomcat10-10.1.52/res/checkstyle/org-import-control.xml | 3 tomcat10-10.1.52/res/ide-support/eclipse/formatting-asf-tomcat.xml | 6 tomcat10-10.1.52/res/ide-support/idea/codeStyles/Project.xml | 97 tomcat10-10.1.52/res/ide-support/idea/inspectionProfiles/Project_Default.xml | 35 tomcat10-10.1.52/res/install-win/tomcat.nsi | 6 tomcat10-10.1.52/res/maven/mvn.properties.default | 4 tomcat10-10.1.52/res/maven/mvn.properties.release | 2 tomcat10-10.1.52/res/openssl/README.md | 14 tomcat10-10.1.52/res/openssl/openssl-tomcat.conf | 34 tomcat10-10.1.52/res/openssl/openssl.h | 1 tomcat10-10.1.52/res/rat/rat-excludes.txt | 11 tomcat10-10.1.52/res/scripts/check-mime.pl | 47 tomcat10-10.1.52/res/spotbugs/filter-false-positives.xml | 44 tomcat10-10.1.52/test-profiles.properties.default | 100 tomcat10-10.1.52/test/conf/TesterRewriteMapB.txt | 4 tomcat10-10.1.52/test/jakarta/el/TestBeanELResolver.java | 20 tomcat10-10.1.52/test/jakarta/el/TestBeanELResolverVarargsInvocation.java | 2 tomcat10-10.1.52/test/jakarta/el/TestELResolver.java | 4 tomcat10-10.1.52/test/jakarta/el/TestImportHandler.java | 17 tomcat10-10.1.52/test/jakarta/el/TestImportHandlerStandardPackages.java | 4 tomcat10-10.1.52/test/jakarta/el/TestMapELResolver.java | 10 tomcat10-10.1.52/test/jakarta/el/TestStaticFieldELResolver.java | 8 tomcat10-10.1.52/test/jakarta/el/TesterBeanNameResolver.java | 2 tomcat10-10.1.52/test/jakarta/servlet/ServletRequestParametersBaseTest.java | 90 tomcat10-10.1.52/test/jakarta/servlet/http/HttpServletDoHeadBaseTest.java | 3 tomcat10-10.1.52/test/jakarta/servlet/http/TestCookie.java | 8 tomcat10-10.1.52/test/jakarta/servlet/http/TestHttpServlet.java | 92 tomcat10-10.1.52/test/jakarta/servlet/http/TestHttpServletDoHeadInvalidWrite0ValidWrite0.java | 5 tomcat10-10.1.52/test/jakarta/servlet/http/TestHttpServletDoHeadInvalidWrite0ValidWrite1.java | 5 tomcat10-10.1.52/test/jakarta/servlet/http/TestHttpServletDoHeadInvalidWrite0ValidWrite1023.java | 5 tomcat10-10.1.52/test/jakarta/servlet/http/TestHttpServletDoHeadInvalidWrite0ValidWrite1024.java | 5 tomcat10-10.1.52/test/jakarta/servlet/http/TestHttpServletDoHeadInvalidWrite0ValidWrite1025.java | 5 tomcat10-10.1.52/test/jakarta/servlet/http/TestHttpServletDoHeadInvalidWrite0ValidWrite511.java | 5 tomcat10-10.1.52/test/jakarta/servlet/http/TestHttpServletDoHeadInvalidWrite0ValidWrite512.java | 5 tomcat10-10.1.52/test/jakarta/servlet/http/TestHttpServletDoHeadInvalidWrite0ValidWrite513.java | 5 tomcat10-10.1.52/test/jakarta/servlet/http/TestHttpServletDoHeadInvalidWrite1023ValidWrite0.java | 5 tomcat10-10.1.52/test/jakarta/servlet/http/TestHttpServletDoHeadInvalidWrite1023ValidWrite1.java | 5 tomcat10-10.1.52/test/jakarta/servlet/http/TestHttpServletDoHeadInvalidWrite1023ValidWrite1023.java | 5 tomcat10-10.1.52/test/jakarta/servlet/http/TestHttpServletDoHeadInvalidWrite1023ValidWrite1024.java | 5 tomcat10-10.1.52/test/jakarta/servlet/http/TestHttpServletDoHeadInvalidWrite1023ValidWrite1025.java | 5 tomcat10-10.1.52/test/jakarta/servlet/http/TestHttpServletDoHeadInvalidWrite1023ValidWrite511.java | 5 tomcat10-10.1.52/test/jakarta/servlet/http/TestHttpServletDoHeadInvalidWrite1023ValidWrite512.java | 5 tomcat10-10.1.52/test/jakarta/servlet/http/TestHttpServletDoHeadInvalidWrite1023ValidWrite513.java | 5 tomcat10-10.1.52/test/jakarta/servlet/http/TestHttpServletDoHeadInvalidWrite1024ValidWrite0.java | 5 tomcat10-10.1.52/test/jakarta/servlet/http/TestHttpServletDoHeadInvalidWrite1024ValidWrite1.java | 5 tomcat10-10.1.52/test/jakarta/servlet/http/TestHttpServletDoHeadInvalidWrite1024ValidWrite1023.java | 5 tomcat10-10.1.52/test/jakarta/servlet/http/TestHttpServletDoHeadInvalidWrite1024ValidWrite1024.java | 5 tomcat10-10.1.52/test/jakarta/servlet/http/TestHttpServletDoHeadInvalidWrite1024ValidWrite1025.java | 5 tomcat10-10.1.52/test/jakarta/servlet/http/TestHttpServletDoHeadInvalidWrite1024ValidWrite511.java | 5 tomcat10-10.1.52/test/jakarta/servlet/http/TestHttpServletDoHeadInvalidWrite1024ValidWrite512.java | 5 tomcat10-10.1.52/test/jakarta/servlet/http/TestHttpServletDoHeadInvalidWrite1024ValidWrite513.java | 5 tomcat10-10.1.52/test/jakarta/servlet/http/TestHttpServletDoHeadInvalidWrite1025ValidWrite0.java | 5 tomcat10-10.1.52/test/jakarta/servlet/http/TestHttpServletDoHeadInvalidWrite1025ValidWrite1.java | 5 tomcat10-10.1.52/test/jakarta/servlet/http/TestHttpServletDoHeadInvalidWrite1025ValidWrite1023.java | 5 tomcat10-10.1.52/test/jakarta/servlet/http/TestHttpServletDoHeadInvalidWrite1025ValidWrite1024.java | 5 tomcat10-10.1.52/test/jakarta/servlet/http/TestHttpServletDoHeadInvalidWrite1025ValidWrite1025.java | 5 tomcat10-10.1.52/test/jakarta/servlet/http/TestHttpServletDoHeadInvalidWrite1025ValidWrite511.java | 5 tomcat10-10.1.52/test/jakarta/servlet/http/TestHttpServletDoHeadInvalidWrite1025ValidWrite512.java | 5 tomcat10-10.1.52/test/jakarta/servlet/http/TestHttpServletDoHeadInvalidWrite1025ValidWrite513.java | 5 tomcat10-10.1.52/test/jakarta/servlet/http/TestHttpServletDoHeadInvalidWrite1ValidWrite0.java | 5 tomcat10-10.1.52/test/jakarta/servlet/http/TestHttpServletDoHeadInvalidWrite1ValidWrite1.java | 5 tomcat10-10.1.52/test/jakarta/servlet/http/TestHttpServletDoHeadInvalidWrite1ValidWrite1023.java | 5 tomcat10-10.1.52/test/jakarta/servlet/http/TestHttpServletDoHeadInvalidWrite1ValidWrite1024.java | 5 tomcat10-10.1.52/test/jakarta/servlet/http/TestHttpServletDoHeadInvalidWrite1ValidWrite1025.java | 5 tomcat10-10.1.52/test/jakarta/servlet/http/TestHttpServletDoHeadInvalidWrite1ValidWrite511.java | 5 tomcat10-10.1.52/test/jakarta/servlet/http/TestHttpServletDoHeadInvalidWrite1ValidWrite512.java | 5 tomcat10-10.1.52/test/jakarta/servlet/http/TestHttpServletDoHeadInvalidWrite1ValidWrite513.java | 5 tomcat10-10.1.52/test/jakarta/servlet/http/TestHttpServletDoHeadInvalidWrite511ValidWrite0.java | 5 tomcat10-10.1.52/test/jakarta/servlet/http/TestHttpServletDoHeadInvalidWrite511ValidWrite1.java | 5 tomcat10-10.1.52/test/jakarta/servlet/http/TestHttpServletDoHeadInvalidWrite511ValidWrite1023.java | 5 tomcat10-10.1.52/test/jakarta/servlet/http/TestHttpServletDoHeadInvalidWrite511ValidWrite1024.java | 5 tomcat10-10.1.52/test/jakarta/servlet/http/TestHttpServletDoHeadInvalidWrite511ValidWrite1025.java | 5 tomcat10-10.1.52/test/jakarta/servlet/http/TestHttpServletDoHeadInvalidWrite511ValidWrite511.java | 5 tomcat10-10.1.52/test/jakarta/servlet/http/TestHttpServletDoHeadInvalidWrite511ValidWrite512.java | 5 tomcat10-10.1.52/test/jakarta/servlet/http/TestHttpServletDoHeadInvalidWrite511ValidWrite513.java | 5 tomcat10-10.1.52/test/jakarta/servlet/http/TestHttpServletDoHeadInvalidWrite512ValidWrite0.java | 5 tomcat10-10.1.52/test/jakarta/servlet/http/TestHttpServletDoHeadInvalidWrite512ValidWrite1.java | 5 tomcat10-10.1.52/test/jakarta/servlet/http/TestHttpServletDoHeadInvalidWrite512ValidWrite1023.java | 5 tomcat10-10.1.52/test/jakarta/servlet/http/TestHttpServletDoHeadInvalidWrite512ValidWrite1024.java | 5 tomcat10-10.1.52/test/jakarta/servlet/http/TestHttpServletDoHeadInvalidWrite512ValidWrite1025.java | 5 tomcat10-10.1.52/test/jakarta/servlet/http/TestHttpServletDoHeadInvalidWrite512ValidWrite511.java | 5 tomcat10-10.1.52/test/jakarta/servlet/http/TestHttpServletDoHeadInvalidWrite512ValidWrite512.java | 5 tomcat10-10.1.52/test/jakarta/servlet/http/TestHttpServletDoHeadInvalidWrite512ValidWrite513.java | 5 tomcat10-10.1.52/test/jakarta/servlet/http/TestHttpServletDoHeadInvalidWrite513ValidWrite0.java | 5 tomcat10-10.1.52/test/jakarta/servlet/http/TestHttpServletDoHeadInvalidWrite513ValidWrite1.java | 5 tomcat10-10.1.52/test/jakarta/servlet/http/TestHttpServletDoHeadInvalidWrite513ValidWrite1023.java | 5 tomcat10-10.1.52/test/jakarta/servlet/http/TestHttpServletDoHeadInvalidWrite513ValidWrite1024.java | 5 tomcat10-10.1.52/test/jakarta/servlet/http/TestHttpServletDoHeadInvalidWrite513ValidWrite1025.java | 5 tomcat10-10.1.52/test/jakarta/servlet/http/TestHttpServletDoHeadInvalidWrite513ValidWrite511.java | 5 tomcat10-10.1.52/test/jakarta/servlet/http/TestHttpServletDoHeadInvalidWrite513ValidWrite512.java | 5 tomcat10-10.1.52/test/jakarta/servlet/http/TestHttpServletDoHeadInvalidWrite513ValidWrite513.java | 5 tomcat10-10.1.52/test/jakarta/servlet/http/TestHttpServletResponseSendError.java | 55 tomcat10-10.1.52/test/jakarta/servlet/http/TesterHttpServletPerformance.java | 2 tomcat10-10.1.52/test/jakarta/servlet/jsp/TestPageContext.java | 3 tomcat10-10.1.52/test/jakarta/servlet/jsp/TesterPageContext.java | 30 tomcat10-10.1.52/test/jakarta/servlet/jsp/TesterPageContextWithAttributes.java | 126 tomcat10-10.1.52/test/jakarta/servlet/jsp/el/TestScopedAttributeELResolver.java | 3 tomcat10-10.1.52/test/jakarta/servlet/jsp/el/TesterScopedAttributeELResolverPerformance.java | 3 tomcat10-10.1.52/test/jakarta/servlet/resources/TestSchemaValidation.java | 60 tomcat10-10.1.52/test/jakarta/websocket/TesterContainerProviderPerformance.java | 3 tomcat10-10.1.52/test/org/apache/catalina/ant/TestDeployTask.java | 10 tomcat10-10.1.52/test/org/apache/catalina/authenticator/ResponseDescriptor.java | 6 tomcat10-10.1.52/test/org/apache/catalina/authenticator/TestAuthInfoResponseHeaders.java | 22 tomcat10-10.1.52/test/org/apache/catalina/authenticator/TestAuthenticatorBaseCorsPreflight.java | 41 tomcat10-10.1.52/test/org/apache/catalina/authenticator/TestBasicAuthParser.java | 247 tomcat10-10.1.52/test/org/apache/catalina/authenticator/TestDigestAuthenticator.java | 124 tomcat10-10.1.52/test/org/apache/catalina/authenticator/TestDigestAuthenticatorAlgorithms.java | 7 tomcat10-10.1.52/test/org/apache/catalina/authenticator/TestFormAuthenticatorA.java | 252 tomcat10-10.1.52/test/org/apache/catalina/authenticator/TestFormAuthenticatorB.java | 186 tomcat10-10.1.52/test/org/apache/catalina/authenticator/TestFormAuthenticatorC.java | 185 tomcat10-10.1.52/test/org/apache/catalina/authenticator/TestJaspicCallbackHandlerInAuthenticator.java | 19 tomcat10-10.1.52/test/org/apache/catalina/authenticator/TestNonLoginAndBasicAuthenticator.java | 302 tomcat10-10.1.52/test/org/apache/catalina/authenticator/TestSSOChangeSessionId.java | 268 tomcat10-10.1.52/test/org/apache/catalina/authenticator/TestSSOnonLoginAndBasicAuthenticator.java | 273 tomcat10-10.1.52/test/org/apache/catalina/authenticator/TestSSOnonLoginAndDigestAuthenticator.java | 203 tomcat10-10.1.52/test/org/apache/catalina/authenticator/TesterDigestAuthenticatorPerformance.java | 42 tomcat10-10.1.52/test/org/apache/catalina/authenticator/jaspic/TestAuthConfigFactoryImpl.java | 64 tomcat10-10.1.52/test/org/apache/catalina/authenticator/jaspic/TestPersistentProviderRegistrations.java | 40 tomcat10-10.1.52/test/org/apache/catalina/authenticator/jaspic/TestSimpleServerAuthConfig.java | 15 tomcat10-10.1.52/test/org/apache/catalina/authenticator/jaspic/TesterServerAuthModuleA.java | 12 tomcat10-10.1.52/test/org/apache/catalina/connector/TestConnector.java | 16 tomcat10-10.1.52/test/org/apache/catalina/connector/TestCoyoteAdapter.java | 35 tomcat10-10.1.52/test/org/apache/catalina/connector/TestCoyoteAdapterCanonicalization.java | 7 tomcat10-10.1.52/test/org/apache/catalina/connector/TestCoyoteAdapterRequestFuzzing.java | 5 tomcat10-10.1.52/test/org/apache/catalina/connector/TestCoyoteInputStream.java | 6 tomcat10-10.1.52/test/org/apache/catalina/connector/TestCoyoteOutputStream.java | 35 tomcat10-10.1.52/test/org/apache/catalina/connector/TestInputBuffer.java | 15 tomcat10-10.1.52/test/org/apache/catalina/connector/TestKeepAliveCount.java | 22 tomcat10-10.1.52/test/org/apache/catalina/connector/TestMaxConnections.java | 20 tomcat10-10.1.52/test/org/apache/catalina/connector/TestOutputBuffer.java | 36 tomcat10-10.1.52/test/org/apache/catalina/connector/TestRequest.java | 202 tomcat10-10.1.52/test/org/apache/catalina/connector/TestResponse.java | 63 tomcat10-10.1.52/test/org/apache/catalina/connector/TestResponsePerformance.java | 5 tomcat10-10.1.52/test/org/apache/catalina/connector/TestSendFile.java | 40 tomcat10-10.1.52/test/org/apache/catalina/core/TestApplicationContext.java | 38 tomcat10-10.1.52/test/org/apache/catalina/core/TestApplicationContextFacadeSecurityManager.java | 48 tomcat10-10.1.52/test/org/apache/catalina/core/TestApplicationContextGetRequestDispatcher.java | 169 tomcat10-10.1.52/test/org/apache/catalina/core/TestApplicationContextGetRequestDispatcherB.java | 531 tomcat10-10.1.52/test/org/apache/catalina/core/TestApplicationContextGetRequestDispatcherC.java | 14 tomcat10-10.1.52/test/org/apache/catalina/core/TestApplicationContextStripPathParams.java | 44 tomcat10-10.1.52/test/org/apache/catalina/core/TestApplicationFilterConfig.java | 9 tomcat10-10.1.52/test/org/apache/catalina/core/TestApplicationMapping.java | 49 tomcat10-10.1.52/test/org/apache/catalina/core/TestApplicationSessionCookieConfig.java | 3 tomcat10-10.1.52/test/org/apache/catalina/core/TestAprLifecycleListener.java | 11 tomcat10-10.1.52/test/org/apache/catalina/core/TestAsyncContextImpl.java | 456 tomcat10-10.1.52/test/org/apache/catalina/core/TestAsyncContextImplDispatch.java | 22 tomcat10-10.1.52/test/org/apache/catalina/core/TestAsyncContextImplListenerOnComplete.java | 11 tomcat10-10.1.52/test/org/apache/catalina/core/TestAsyncContextIoError.java | 17 tomcat10-10.1.52/test/org/apache/catalina/core/TestAsyncContextStateChanges.java | 39 tomcat10-10.1.52/test/org/apache/catalina/core/TestContextNamingInfoListener.java | 34 tomcat10-10.1.52/test/org/apache/catalina/core/TestDefaultInstanceManager.java | 3 tomcat10-10.1.52/test/org/apache/catalina/core/TestNamingContextListener.java | 15 tomcat10-10.1.52/test/org/apache/catalina/core/TestPropertiesRoleMappingListener.java | 4 tomcat10-10.1.52/test/org/apache/catalina/core/TestStandardContext.java | 205 tomcat10-10.1.52/test/org/apache/catalina/core/TestStandardContextAliases.java | 6 tomcat10-10.1.52/test/org/apache/catalina/core/TestStandardContextResources.java | 106 tomcat10-10.1.52/test/org/apache/catalina/core/TestStandardContextValve.java | 23 tomcat10-10.1.52/test/org/apache/catalina/core/TestStandardHostValve.java | 18 tomcat10-10.1.52/test/org/apache/catalina/core/TestStandardWrapper.java | 79 tomcat10-10.1.52/test/org/apache/catalina/core/TestSwallowAbortedUploads.java | 118 tomcat10-10.1.52/test/org/apache/catalina/filters/TestAddCharSetFilter.java | 2 tomcat10-10.1.52/test/org/apache/catalina/filters/TestCorsFilter.java | 125 tomcat10-10.1.52/test/org/apache/catalina/filters/TestCsrfPreventionFilter.java | 127 tomcat10-10.1.52/test/org/apache/catalina/filters/TestRateLimitFilterWithExactRateLimiter.java | 2 tomcat10-10.1.52/test/org/apache/catalina/filters/TestRemoteCIDRFilter.java | 90 tomcat10-10.1.52/test/org/apache/catalina/filters/TestRemoteIpFilter.java | 13 tomcat10-10.1.52/test/org/apache/catalina/filters/TestRestCsrfPreventionFilter.java | 51 tomcat10-10.1.52/test/org/apache/catalina/filters/TestRestCsrfPreventionFilter2.java | 52 tomcat10-10.1.52/test/org/apache/catalina/filters/TesterHttpServletRequest.java | 13 tomcat10-10.1.52/test/org/apache/catalina/filters/TesterHttpServletResponse.java | 4 tomcat10-10.1.52/test/org/apache/catalina/ha/context/TestReplicatedContext.java | 3 tomcat10-10.1.52/test/org/apache/catalina/loader/EchoTag.java | 4 tomcat10-10.1.52/test/org/apache/catalina/loader/MyAnnotatedServlet.java | 3 tomcat10-10.1.52/test/org/apache/catalina/loader/TestVirtualContext.java | 271 tomcat10-10.1.52/test/org/apache/catalina/loader/TestVirtualWebappLoader.java | 13 tomcat10-10.1.52/test/org/apache/catalina/loader/TestWebappClassLoader.java | 88 tomcat10-10.1.52/test/org/apache/catalina/loader/TestWebappClassLoaderExecutorMemoryLeak.java | 12 tomcat10-10.1.52/test/org/apache/catalina/loader/TestWebappClassLoaderMemoryLeak.java | 13 tomcat10-10.1.52/test/org/apache/catalina/loader/TestWebappClassLoaderWeaving.java | 95 tomcat10-10.1.52/test/org/apache/catalina/loader/TesterWebappClassLoaderThreadLocalMemoryLeak.java | 75 tomcat10-10.1.52/test/org/apache/catalina/manager/TestHostManagerWebapp.java | 94 tomcat10-10.1.52/test/org/apache/catalina/manager/TestManagerWebapp.java | 310 tomcat10-10.1.52/test/org/apache/catalina/manager/TestManagerWebappSsl.java | 53 tomcat10-10.1.52/test/org/apache/catalina/manager/TestStatusTransformer.java | 25 tomcat10-10.1.52/test/org/apache/catalina/mapper/TestMapper.java | 22 tomcat10-10.1.52/test/org/apache/catalina/mapper/TestMapperWebapps.java | 4 tomcat10-10.1.52/test/org/apache/catalina/mbeans/TestRegistration.java | 101 tomcat10-10.1.52/test/org/apache/catalina/nonblocking/TestNonBlockingAPI.java | 571 tomcat10-10.1.52/test/org/apache/catalina/nonblocking/TesterAjpNonBlockingClient.java | 21 tomcat10-10.1.52/test/org/apache/catalina/realm/TestDataSourceRealm.java | 2 tomcat10-10.1.52/test/org/apache/catalina/realm/TestRealmBase.java | 13 tomcat10-10.1.52/test/org/apache/catalina/realm/TesterLoginModule.java | 4 tomcat10-10.1.52/test/org/apache/catalina/realm/TesterServletSecurity01.java | 7 tomcat10-10.1.52/test/org/apache/catalina/servlets/ServletOptionsBaseTest.java | 10 tomcat10-10.1.52/test/org/apache/catalina/servlets/TestDefaultServlet.java | 150 tomcat10-10.1.52/test/org/apache/catalina/servlets/TestDefaultServletIfMatchRequests.java | 4 tomcat10-10.1.52/test/org/apache/catalina/servlets/TestDefaultServletOptions.java | 4 tomcat10-10.1.52/test/org/apache/catalina/servlets/TestDefaultServletPut.java | 37 tomcat10-10.1.52/test/org/apache/catalina/servlets/TestDefaultServletRangeRequests.java | 4 tomcat10-10.1.52/test/org/apache/catalina/servlets/TestDefaultServletRfc9110Section14.java | 3 tomcat10-10.1.52/test/org/apache/catalina/servlets/TestWebdavServlet.java | 1155 - tomcat10-10.1.52/test/org/apache/catalina/servlets/TestWebdavServletOptionCollection.java | 6 tomcat10-10.1.52/test/org/apache/catalina/servlets/TestWebdavServletOptionsFile.java | 6 tomcat10-10.1.52/test/org/apache/catalina/servlets/TestWebdavServletOptionsUnknown.java | 6 tomcat10-10.1.52/test/org/apache/catalina/session/Benchmarks.java | 4 tomcat10-10.1.52/test/org/apache/catalina/session/FileStoreTest.java | 8 tomcat10-10.1.52/test/org/apache/catalina/session/TestFileStoreConcurrency.java | 188 tomcat10-10.1.52/test/org/apache/catalina/session/TestPersistentManager.java | 2 tomcat10-10.1.52/test/org/apache/catalina/session/TesterManager.java | 205 tomcat10-10.1.52/test/org/apache/catalina/startup/DuplicateMappingParamFilter.java | 3 tomcat10-10.1.52/test/org/apache/catalina/startup/DuplicateMappingParamServlet.java | 2 tomcat10-10.1.52/test/org/apache/catalina/startup/ParamFilter.java | 3 tomcat10-10.1.52/test/org/apache/catalina/startup/SimpleHttpClient.java | 18 tomcat10-10.1.52/test/org/apache/catalina/startup/TestContextConfigAnnotation.java | 2 tomcat10-10.1.52/test/org/apache/catalina/startup/TestStartupIPv6Connectors.java | 149 tomcat10-10.1.52/test/org/apache/catalina/startup/TestStrictServletComplianceAttributes.java | 77 tomcat10-10.1.52/test/org/apache/catalina/startup/TestTomcatNoServer.java | 43 tomcat10-10.1.52/test/org/apache/catalina/startup/TestTomcatStandalone.java | 222 tomcat10-10.1.52/test/org/apache/catalina/startup/TestWebappServiceLoader.java | 8 tomcat10-10.1.52/test/org/apache/catalina/startup/TestXmlValidationUsingContext.java | 83 tomcat10-10.1.52/test/org/apache/catalina/startup/TomcatBaseTest.java | 246 tomcat10-10.1.52/test/org/apache/catalina/util/TestFilterUtil.java | 120 tomcat10-10.1.52/test/org/apache/catalina/util/TestParameterMapPerformance.java | 103 tomcat10-10.1.52/test/org/apache/catalina/util/TestURLEncoder.java | 28 tomcat10-10.1.52/test/org/apache/catalina/valves/TestAccessLogValve.java | 11 tomcat10-10.1.52/test/org/apache/catalina/valves/TestCrawlerSessionManagerValve.java | 2 tomcat10-10.1.52/test/org/apache/catalina/valves/TestExtendedAccessLogValve.java | 7 tomcat10-10.1.52/test/org/apache/catalina/valves/TestParameterLimitValve.java | 694 tomcat10-10.1.52/test/org/apache/catalina/valves/TestParameterLimitValveConfig.java | 44 tomcat10-10.1.52/test/org/apache/catalina/valves/TestRequestFilterValve.java | 1 tomcat10-10.1.52/test/org/apache/catalina/valves/TestSSLValve.java | 68 tomcat10-10.1.52/test/org/apache/catalina/valves/TestStuckThreadDetectionValve.java | 8 tomcat10-10.1.52/test/org/apache/catalina/valves/rewrite/TestResolverSSL.java | 2 tomcat10-10.1.52/test/org/apache/catalina/valves/rewrite/TestRewriteValve.java | 118 tomcat10-10.1.52/test/org/apache/catalina/webresources/AbstractTestResourceSet.java | 69 tomcat10-10.1.52/test/org/apache/catalina/webresources/AbstractTestResourceSetMount.java | 5 tomcat10-10.1.52/test/org/apache/catalina/webresources/AbstractTestResourceSetMountTrailing.java | 80 tomcat10-10.1.52/test/org/apache/catalina/webresources/TestCachedResource.java | 35 tomcat10-10.1.52/test/org/apache/catalina/webresources/TestDirResourceSetMountTrailing.java | 85 tomcat10-10.1.52/test/org/apache/catalina/webresources/TestJarContents.java | 3 tomcat10-10.1.52/test/org/apache/catalina/webresources/TestJarResourceSetMountTrailing.java | 60 tomcat10-10.1.52/test/org/apache/catalina/webresources/TestWebResourceContentType.java | 88 tomcat10-10.1.52/test/org/apache/coyote/TestIoTimeouts.java | 12 tomcat10-10.1.52/test/org/apache/coyote/ajp/SimpleAjpClient.java | 58 tomcat10-10.1.52/test/org/apache/coyote/ajp/TestAbstractAjpProcessor.java | 21 tomcat10-10.1.52/test/org/apache/coyote/http11/TestHttp11InputBuffer.java | 62 tomcat10-10.1.52/test/org/apache/coyote/http11/TestHttp11Processor.java | 345 tomcat10-10.1.52/test/org/apache/coyote/http11/filters/TestChunkedInputFilter.java | 323 tomcat10-10.1.52/test/org/apache/coyote/http2/Http2TestBase.java | 36 tomcat10-10.1.52/test/org/apache/coyote/http2/TestAsync.java | 4 tomcat10-10.1.52/test/org/apache/coyote/http2/TestAsyncError.java | 19 tomcat10-10.1.52/test/org/apache/coyote/http2/TestFlowControl.java | 3 tomcat10-10.1.52/test/org/apache/coyote/http2/TestHpack.java | 64 tomcat10-10.1.52/test/org/apache/coyote/http2/TestHttp2AccessLogs.java | 4 tomcat10-10.1.52/test/org/apache/coyote/http2/TestHttp2Limits.java | 5 tomcat10-10.1.52/test/org/apache/coyote/http2/TestHttp2RequestParameters.java | 52 tomcat10-10.1.52/test/org/apache/coyote/http2/TestHttp2Section_3_5.java | 2 tomcat10-10.1.52/test/org/apache/coyote/http2/TestHttp2Section_6_1.java | 53 tomcat10-10.1.52/test/org/apache/coyote/http2/TestHttp2Section_8_1.java | 25 tomcat10-10.1.52/test/org/apache/coyote/http2/TestHttp2UpgradeHandler.java | 3 tomcat10-10.1.52/test/org/apache/coyote/http2/TestStandardSessionIntegrationHttp2.java | 174 tomcat10-10.1.52/test/org/apache/coyote/http2/TestStreamProcessor.java | 17 tomcat10-10.1.52/test/org/apache/el/TestELInJsp.java | 10 tomcat10-10.1.52/test/org/apache/el/parser/TesterGenerateIdentifierRanges.java | 4 tomcat10-10.1.52/test/org/apache/jasper/compiler/TestGenerator.java | 106 tomcat10-10.1.52/test/org/apache/jasper/compiler/TestNonstandardTagPerformance.java | 148 tomcat10-10.1.52/test/org/apache/jasper/compiler/TestValidator.java | 4 tomcat10-10.1.52/test/org/apache/jasper/runtime/TestJspRuntimeLibrary.java | 37 tomcat10-10.1.52/test/org/apache/jasper/servlet/TestJspServlet.java | 7 tomcat10-10.1.52/test/org/apache/juli/TestLogUtil.java | 93 tomcat10-10.1.52/test/org/apache/juli/TestPerWebappJuliIntegration.java | 164 tomcat10-10.1.52/test/org/apache/naming/TestNamingContext.java | 56 tomcat10-10.1.52/test/org/apache/tomcat/buildutil/translate/TestUtils.java | 44 tomcat10-10.1.52/test/org/apache/tomcat/security/TestSecurity2017Ocsp.java | 114 tomcat10-10.1.52/test/org/apache/tomcat/security/TestSecurity2023.java | 251 tomcat10-10.1.52/test/org/apache/tomcat/security/TestSecurity2025Http2.java | 62 tomcat10-10.1.52/test/org/apache/tomcat/util/concurrent/TestKeyedReentrantReadWriteLock.java | 31 tomcat10-10.1.52/test/org/apache/tomcat/util/descriptor/web/TestSecurityConstraint.java | 53 tomcat10-10.1.52/test/org/apache/tomcat/util/descriptor/web/TestWebXml.java | 3 tomcat10-10.1.52/test/org/apache/tomcat/util/http/TestCookieProcessorGeneration.java | 15 tomcat10-10.1.52/test/org/apache/tomcat/util/http/TestMethod.java | 43 tomcat10-10.1.52/test/org/apache/tomcat/util/http/TestMethodPerformance.java | 67 tomcat10-10.1.52/test/org/apache/tomcat/util/net/TestClientCertTls13.java | 2 tomcat10-10.1.52/test/org/apache/tomcat/util/net/TestKeyManagerWrappingFips.java | 227 tomcat10-10.1.52/test/org/apache/tomcat/util/net/TestSSLHostConfig.java | 70 tomcat10-10.1.52/test/org/apache/tomcat/util/net/TestSSLHostConfigCipher.java | 161 tomcat10-10.1.52/test/org/apache/tomcat/util/net/TestSSLHostConfigCompat.java | 22 tomcat10-10.1.52/test/org/apache/tomcat/util/net/TestSsl.java | 166 tomcat10-10.1.52/test/org/apache/tomcat/util/net/TesterSupport.java | 106 tomcat10-10.1.52/test/org/apache/tomcat/util/net/ca-cert.pem | 73 tomcat10-10.1.52/test/org/apache/tomcat/util/net/index.db | 7 tomcat10-10.1.52/test/org/apache/tomcat/util/net/index.db.attr | 1 tomcat10-10.1.52/test/org/apache/tomcat/util/net/localhost-crl-rsa-cert.pem | 108 tomcat10-10.1.52/test/org/apache/tomcat/util/net/localhost-crl-rsa-key.pem | 28 tomcat10-10.1.52/test/org/apache/tomcat/util/net/localhost-ec-cert.pem | 130 tomcat10-10.1.52/test/org/apache/tomcat/util/net/localhost-ec-key.pem | 13 tomcat10-10.1.52/test/org/apache/tomcat/util/net/localhost-rsa-cert.pem | 165 tomcat10-10.1.52/test/org/apache/tomcat/util/net/localhost-rsa-key.pem | 52 tomcat10-10.1.52/test/org/apache/tomcat/util/net/ocsp-responder-rsa-cert.pem | 105 tomcat10-10.1.52/test/org/apache/tomcat/util/net/ocsp-responder-rsa-key.pem | 28 tomcat10-10.1.52/test/org/apache/tomcat/util/net/ocsp/OcspBaseTest.java | 186 tomcat10-10.1.52/test/org/apache/tomcat/util/net/ocsp/TestOcspEnabled.java | 121 tomcat10-10.1.52/test/org/apache/tomcat/util/net/ocsp/TestOcspSoftFail.java | 59 tomcat10-10.1.52/test/org/apache/tomcat/util/net/ocsp/TestOcspTimeout.java | 73 tomcat10-10.1.52/test/org/apache/tomcat/util/net/ocsp/TesterOcspResponder.java | 125 tomcat10-10.1.52/test/org/apache/tomcat/util/net/ocsp/TesterOcspResponderNoResponse.java | 113 tomcat10-10.1.52/test/org/apache/tomcat/util/net/openssl/TestOpenSSLConf.java | 2 tomcat10-10.1.52/test/org/apache/tomcat/util/net/openssl/ciphers/TesterOpenSSL.java | 12 tomcat10-10.1.52/test/org/apache/tomcat/websocket/TestPerMessageDeflate.java | 12 tomcat10-10.1.52/test/org/apache/tomcat/websocket/TestWsSessionSuspendResume.java | 6 tomcat10-10.1.52/test/org/apache/tomcat/websocket/TesterEchoServer.java | 40 tomcat10-10.1.52/test/org/apache/tomcat/websocket/TesterWsClientAutobahn.java | 8 tomcat10-10.1.52/test/org/apache/tomcat/websocket/server/TestWsRemoteEndpointImplServerDeadlock.java | 2 tomcat10-10.1.52/test/webapp/WEB-INF/classes/bug69623-a.mdd | 1 tomcat10-10.1.52/test/webapp/WEB-INF/web.xml | 28 tomcat10-10.1.52/test/webapp/bug6nnnn/bug69635.jsp | 18 tomcat10-10.1.52/test/webapp/jsp/encoding/README.txt | 2 tomcat10-10.1.52/test/webapp/jsp/generator/lambda.jsp | 23 tomcat10-10.1.52/test/webapp/jsp/generator/nonstandard/remove-01.jsp | 26 tomcat10-10.1.52/test/webapp/jsp/generator/nonstandard/remove-02.jsp | 26 tomcat10-10.1.52/test/webapp/jsp/generator/nonstandard/remove-03.jsp | 26 tomcat10-10.1.52/test/webapp/jsp/generator/nonstandard/remove-04.jsp | 26 tomcat10-10.1.52/test/webapp/jsp/generator/nonstandard/remove-05.jsp | 26 tomcat10-10.1.52/test/webapp/jsp/generator/nonstandard/set-01.jsp | 22 tomcat10-10.1.52/test/webapp/jsp/generator/nonstandard/set-02.jsp | 22 tomcat10-10.1.52/test/webapp/jsp/generator/nonstandard/set-03.jsp | 22 tomcat10-10.1.52/test/webapp/jsp/generator/nonstandard/set-04.jsp | 22 tomcat10-10.1.52/test/webapp/jsp/generator/nonstandard/set-05.jsp | 22 tomcat10-10.1.52/test/webapp/jsp/pageContext1.jsp | 2 tomcat10-10.1.52/webapps/ROOT/asf-logo-wide.svg | 322 tomcat10-10.1.52/webapps/docs/META-INF/context.xml | 4 tomcat10-10.1.52/webapps/docs/aio.xml | 1 tomcat10-10.1.52/webapps/docs/appdev/deployment.xml | 1 tomcat10-10.1.52/webapps/docs/appdev/index.xml | 14 tomcat10-10.1.52/webapps/docs/appdev/installation.xml | 2 tomcat10-10.1.52/webapps/docs/appdev/introduction.xml | 1 tomcat10-10.1.52/webapps/docs/appdev/processes.xml | 1 tomcat10-10.1.52/webapps/docs/appdev/sample/index.html | 1 tomcat10-10.1.52/webapps/docs/appdev/sample/src/mypackage/Hello.java | 2 tomcat10-10.1.52/webapps/docs/appdev/source.xml | 1 tomcat10-10.1.52/webapps/docs/apr.xml | 1 tomcat10-10.1.52/webapps/docs/architecture/index.xml | 5 tomcat10-10.1.52/webapps/docs/architecture/overview.xml | 1 tomcat10-10.1.52/webapps/docs/architecture/requestProcess.xml | 81 tomcat10-10.1.52/webapps/docs/architecture/requestProcess/11_nio.plantuml | 97 tomcat10-10.1.52/webapps/docs/architecture/requestProcess/21_http11.plantuml | 38 tomcat10-10.1.52/webapps/docs/architecture/requestProcess/31_synchronous.plantuml | 109 tomcat10-10.1.52/webapps/docs/architecture/requestProcess/41_basic.plantuml | 78 tomcat10-10.1.52/webapps/docs/architecture/startup.xml | 1 tomcat10-10.1.52/webapps/docs/balancer-howto.xml | 3 tomcat10-10.1.52/webapps/docs/changelog.xml | 1066 + tomcat10-10.1.52/webapps/docs/class-loader-howto.xml | 2 tomcat10-10.1.52/webapps/docs/cluster-howto.xml | 14 tomcat10-10.1.52/webapps/docs/config/ajp.xml | 47 tomcat10-10.1.52/webapps/docs/config/cluster-channel.xml | 1 tomcat10-10.1.52/webapps/docs/config/cluster-deployer.xml | 1 tomcat10-10.1.52/webapps/docs/config/cluster-interceptor.xml | 1 tomcat10-10.1.52/webapps/docs/config/cluster-listener.xml | 1 tomcat10-10.1.52/webapps/docs/config/cluster-manager.xml | 52 tomcat10-10.1.52/webapps/docs/config/cluster-membership.xml | 1 tomcat10-10.1.52/webapps/docs/config/cluster-receiver.xml | 1 tomcat10-10.1.52/webapps/docs/config/cluster-sender.xml | 1 tomcat10-10.1.52/webapps/docs/config/cluster-valve.xml | 47 tomcat10-10.1.52/webapps/docs/config/cluster.xml | 98 tomcat10-10.1.52/webapps/docs/config/context.xml | 12 tomcat10-10.1.52/webapps/docs/config/credentialhandler.xml | 13 tomcat10-10.1.52/webapps/docs/config/engine.xml | 5 tomcat10-10.1.52/webapps/docs/config/executor.xml | 1 tomcat10-10.1.52/webapps/docs/config/filter.xml | 5 tomcat10-10.1.52/webapps/docs/config/globalresources.xml | 2 tomcat10-10.1.52/webapps/docs/config/host.xml | 11 tomcat10-10.1.52/webapps/docs/config/http.xml | 162 tomcat10-10.1.52/webapps/docs/config/http2.xml | 7 tomcat10-10.1.52/webapps/docs/config/index.xml | 1 tomcat10-10.1.52/webapps/docs/config/loader.xml | 1 tomcat10-10.1.52/webapps/docs/config/manager.xml | 2 tomcat10-10.1.52/webapps/docs/config/realm.xml | 1 tomcat10-10.1.52/webapps/docs/config/resources.xml | 13 tomcat10-10.1.52/webapps/docs/config/server.xml | 3 tomcat10-10.1.52/webapps/docs/config/service.xml | 1 tomcat10-10.1.52/webapps/docs/config/valve.xml | 189 tomcat10-10.1.52/webapps/docs/connectors.xml | 1 tomcat10-10.1.52/webapps/docs/default-servlet.xml | 26 tomcat10-10.1.52/webapps/docs/deployer-howto.xml | 1 tomcat10-10.1.52/webapps/docs/developers.xml | 2 tomcat10-10.1.52/webapps/docs/html-manager-howto.xml | 1 tomcat10-10.1.52/webapps/docs/images/asf-logo.svg | 253 tomcat10-10.1.52/webapps/docs/index.xml | 3 tomcat10-10.1.52/webapps/docs/introduction.xml | 6 tomcat10-10.1.52/webapps/docs/jasper-howto.xml | 2 tomcat10-10.1.52/webapps/docs/jndi-datasource-examples-howto.xml | 4 tomcat10-10.1.52/webapps/docs/jndi-resources-howto.xml | 19 tomcat10-10.1.52/webapps/docs/logging.xml | 6 tomcat10-10.1.52/webapps/docs/manager-howto.xml | 11 tomcat10-10.1.52/webapps/docs/maven-jars.xml | 1 tomcat10-10.1.52/webapps/docs/mbeans-descriptors-howto.xml | 1 tomcat10-10.1.52/webapps/docs/proxy-howto.xml | 1 tomcat10-10.1.52/webapps/docs/realm-howto.xml | 3 tomcat10-10.1.52/webapps/docs/rewrite.xml | 1 tomcat10-10.1.52/webapps/docs/security-howto.xml | 104 tomcat10-10.1.52/webapps/docs/security-manager-howto.xml | 2 tomcat10-10.1.52/webapps/docs/setup.xml | 1 tomcat10-10.1.52/webapps/docs/ssi-howto.xml | 1 tomcat10-10.1.52/webapps/docs/ssl-howto.xml | 31 tomcat10-10.1.52/webapps/docs/tomcat-docs.xsl | 1 tomcat10-10.1.52/webapps/docs/tribes/introduction.xml | 1 tomcat10-10.1.52/webapps/docs/windows-service-howto.xml | 1 tomcat10-10.1.52/webapps/examples/META-INF/context.xml | 4 tomcat10-10.1.52/webapps/examples/WEB-INF/classes/CookieExample.java | 2 tomcat10-10.1.52/webapps/examples/WEB-INF/classes/HelloWorldExample.java | 3 tomcat10-10.1.52/webapps/examples/WEB-INF/classes/LocalStrings_zh_CN.properties | 2 tomcat10-10.1.52/webapps/examples/WEB-INF/classes/RequestHeaderExample.java | 2 tomcat10-10.1.52/webapps/examples/WEB-INF/classes/RequestInfoExample.java | 4 tomcat10-10.1.52/webapps/examples/WEB-INF/classes/RequestParamExample.java | 3 tomcat10-10.1.52/webapps/examples/WEB-INF/classes/ServletToJsp.java | 1 tomcat10-10.1.52/webapps/examples/WEB-INF/classes/SessionExample.java | 3 tomcat10-10.1.52/webapps/examples/WEB-INF/classes/compressionFilters/CompressionFilter.java | 3 tomcat10-10.1.52/webapps/examples/WEB-INF/classes/compressionFilters/CompressionFilterTestServlet.java | 3 tomcat10-10.1.52/webapps/examples/WEB-INF/classes/compressionFilters/CompressionResponseStream.java | 3 tomcat10-10.1.52/webapps/examples/WEB-INF/classes/compressionFilters/CompressionServletResponseWrapper.java | 5 tomcat10-10.1.52/webapps/examples/WEB-INF/classes/examples/FooTag.java | 4 tomcat10-10.1.52/webapps/examples/WEB-INF/classes/examples/LogTag.java | 4 tomcat10-10.1.52/webapps/examples/WEB-INF/classes/examples/ValuesTag.java | 4 tomcat10-10.1.52/webapps/examples/WEB-INF/classes/filters/ExampleFilter.java | 2 tomcat10-10.1.52/webapps/examples/WEB-INF/classes/listeners/ContextListener.java | 2 tomcat10-10.1.52/webapps/examples/WEB-INF/classes/listeners/SessionListener.java | 2 tomcat10-10.1.52/webapps/examples/WEB-INF/classes/num/NumberGuessBean.java | 4 tomcat10-10.1.52/webapps/examples/WEB-INF/classes/util/HTMLFilter.java | 3 tomcat10-10.1.52/webapps/examples/WEB-INF/classes/validators/DebugValidator.java | 4 tomcat10-10.1.52/webapps/examples/WEB-INF/classes/websocket/chat/ChatAnnotation.java | 8 tomcat10-10.1.52/webapps/examples/WEB-INF/classes/websocket/drawboard/Client.java | 4 tomcat10-10.1.52/webapps/examples/WEB-INF/classes/websocket/drawboard/Room.java | 4 tomcat10-10.1.52/webapps/examples/WEB-INF/classes/websocket/echo/EchoAnnotation.java | 8 tomcat10-10.1.52/webapps/examples/WEB-INF/classes/websocket/echo/EchoEndpoint.java | 30 tomcat10-10.1.52/webapps/examples/jsp/index.html | 1 tomcat10-10.1.52/webapps/examples/jsp/jsp2/jspx/textRotate.jspx | 5 tomcat10-10.1.52/webapps/examples/jsp/num/numguess.html | 4 tomcat10-10.1.52/webapps/examples/jsp/num/numguess.jsp | 2 tomcat10-10.1.52/webapps/examples/servlets/index.html | 1 tomcat10-10.1.52/webapps/host-manager/META-INF/context.xml | 4 tomcat10-10.1.52/webapps/host-manager/WEB-INF/jsp/401.jsp | 1 tomcat10-10.1.52/webapps/host-manager/WEB-INF/jsp/403.jsp | 1 tomcat10-10.1.52/webapps/host-manager/WEB-INF/jsp/404.jsp | 1 tomcat10-10.1.52/webapps/host-manager/WEB-INF/manager.xml | 4 tomcat10-10.1.52/webapps/host-manager/images/asf-logo.svg | 253 tomcat10-10.1.52/webapps/manager/META-INF/context.xml | 4 tomcat10-10.1.52/webapps/manager/WEB-INF/jsp/401.jsp | 1 tomcat10-10.1.52/webapps/manager/WEB-INF/jsp/403.jsp | 1 tomcat10-10.1.52/webapps/manager/WEB-INF/jsp/404.jsp | 1 tomcat10-10.1.52/webapps/manager/WEB-INF/jsp/connectorCerts.jsp | 5 tomcat10-10.1.52/webapps/manager/WEB-INF/jsp/connectorCiphers.jsp | 5 tomcat10-10.1.52/webapps/manager/WEB-INF/jsp/connectorTrustedCerts.jsp | 5 tomcat10-10.1.52/webapps/manager/WEB-INF/jsp/sessionDetail.jsp | 10 tomcat10-10.1.52/webapps/manager/WEB-INF/jsp/sessionsList.jsp | 8 tomcat10-10.1.52/webapps/manager/images/asf-logo.svg | 253 1657 files changed, 43695 insertions(+), 30805 deletions(-) dpkg-source: warning: cannot verify inline signature for /srv/release.debian.org/tmp/tmpa90jq876/tomcat10_10.1.40-1.dsc: no acceptable signature found dpkg-source: warning: cannot verify inline signature for /srv/release.debian.org/tmp/tmpa90jq876/tomcat10_10.1.52-1~deb13u1.dsc: no acceptable signature found diff -Nru tomcat10-10.1.40/.github/workflows/ci.yml tomcat10-10.1.52/.github/workflows/ci.yml --- tomcat10-10.1.40/.github/workflows/ci.yml 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/.github/workflows/ci.yml 2026-01-23 19:33:36.000000000 +0000 @@ -30,7 +30,7 @@ matrix: isMain: - ${{ contains(github.ref, 'main') }} - java: [ 24 ] + java: [ 26-ea ] os: [ ubuntu-latest ] name: JDK${{ matrix.java }} ${{ matrix.os }} runs-on: ${{ matrix.os }} @@ -46,7 +46,7 @@ run: | ant -noinput echoproperties deploy embed test-nio test-status env: - ANT_OPTS: -Dtest.openssl.exists=false -Dtest.excludePerformance=true -Dtest.exclude=jakarta/servlet/http/TestHttpServletResponseSendError.java,org/apache/catalina/authenticator/TestFormAuthenticatorA.java,org/apache/catalina/authenticator/TestFormAuthenticatorB.java,org/apache/catalina/authenticator/TestFormAuthenticatorC.java,org/apache/catalina/authenticator/TestSSOnonLoginAndBasicAuthenticator.java,org/apache/catalina/authenticator/TestSSOnonLoginAndDigestAuthenticator.java,org/apache/catalina/core/TestAsyncContextImpl.java,org/apache/catalina/core/TestAsyncContextStateChanges.java,org/apache/catalina/core/TestStandardContextResources.java,org/apache/catalina/core/TestStandardWrapper.java,org/apache/catalina/loader/TestVirtualContext.java,org/apache/catalina/mapper/TestMapperWebapps.java,org/apache/catalina/nonblocking/TestNonBlockingAPI.java,org/apache/catalina/servlets/TestDefaultServletEncodingPassThroughBom.java,org/apache/catalina/servlets/TestDefaultServletEncodingWithBom.java,org/apache/catalina/servlets/TestDefaultServletEncodingWithoutBom.java,org/apache/catalina/servlets/TestDefaultServletIfMatchRequests.java,org/apache/catalina/servlets/TestDefaultServlet.java,org/apache/catalina/servlets/TestDefaultServletOptions.java,org/apache/catalina/servlets/TestWebdavServletOptionsFile.java,org/apache/catalina/startup/TestContextConfig.java,org/apache/catalina/startup/TestHostConfigAutomaticDeploymentA.java,org/apache/catalina/startup/TestHostConfigAutomaticDeploymentB.java,org/apache/catalina/startup/TestHostConfigAutomaticDeploymentC.java,org/apache/catalina/valves/rewrite/TestRewriteValve.java,org/apache/catalina/valves/TestStuckThreadDetectionValve.java,org/apache/coyote/ajp/TestAbstractAjpProcessor.java,org/apache/coyote/http11/filters/TestChunkedInputFilter.java,org/apache/coyote/http11/TestHttp11InputBufferCRLF.java,org/apache/coyote/http11/TestHttp11InputBuffer.java,org/apache/coyote/http11/TestHttp11Processor.java,org/apache/coyote/http2/TestAsync.java,org/apache/coyote/http2/TestHttp2ConnectionTimeouts.java,org/apache/coyote/http2/TestHttp2Limits.java,org/apache/coyote/http2/TestHttp2Section_6_8.java,org/apache/coyote/http2/TestHttp2Timeouts.java,org/apache/coyote/http2/TestStreamQueryString.java,org/apache/el/TestELInJsp.java,org/apache/jasper/compiler/TestCompiler.java,org/apache/jasper/compiler/TestEncodingDetector.java,org/apache/jasper/compiler/TestGenerator.java,org/apache/jasper/compiler/TestJspConfig.java,org/apache/jasper/compiler/TestJspDocumentParser.java,org/apache/jasper/compiler/TestValidator.java,org/apache/jasper/optimizations/TestELInterpreterTagSetters.java,org/apache/jasper/optimizations/TestStringInterpreterTagSetters.java,org/apache/jasper/runtime/TestCustomHttpJspPage.java,org/apache/jasper/runtime/TestJspContextWrapper.java,org/apache/jasper/runtime/TestJspRuntimeLibrary.java,org/apache/jasper/runtime/TestPageContextImpl.java,org/apache/jasper/servlet/TestTldScanner.java,org/apache/naming/resources/TestWarDirContext.java,org/apache/naming/TestEnvEntry.java,org/apache/tomcat/util/net/TestClientCert.java,org/apache/tomcat/util/net/TestCustomSslTrustManager.java,org/apache/tomcat/util/net/TestSSLHostConfigCompat.java,org/apache/tomcat/util/net/TestSsl.java,org/apache/tomcat/websocket/server/TestSlowClient.java,org/apache/tomcat/websocket/server/TestWsRemoteEndpointImplServerDeadlock.java,org/apache/tomcat/websocket/TestWebSocketFrameClientSSL.java,org/apache/tomcat/websocket/TestWsWebSocketContainer.java,org/apache/tomcat/websocket/TestWsWebSocketContainerTimeoutServer.java,org/apache/catalina/tribes/group/interceptors/TestTcpFailureDetector.java,org/apache/catalina/filters/TestRateLimitFilter.java,jakarta/servlet/http/TestHttpServletDoHeadInvalidWrite*.java,jakarta/servlet/http/TestHttpServletDoHeadValidWrite*.java + ANT_OPTS: -Dtest.openssl.exists=false -Dtest.excludePerformance=true -Dtest.profile=smoke - name: Upload logs if: ${{ !cancelled() }} diff -Nru tomcat10-10.1.40/.gitignore tomcat10-10.1.52/.gitignore --- tomcat10-10.1.40/.gitignore 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/.gitignore 2026-01-23 19:33:36.000000000 +0000 @@ -51,3 +51,4 @@ modules/jdbc-pool/bin modules/jdbc-pool/includes webapps/docs/jdbc-pool.xml +/test/org/apache/tomcat/util/net/ocsp/ocsp-work/ diff -Nru tomcat10-10.1.40/BUILDING.txt tomcat10-10.1.52/BUILDING.txt --- tomcat10-10.1.40/BUILDING.txt 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/BUILDING.txt 2026-01-23 19:33:36.000000000 +0000 @@ -293,14 +293,15 @@ # Location of GPG executable (used only for releases) gpg.exec=/path/to/gpg - You do not need it if you do not plan to sign the release. - - If "gpg.exec" property does not point to an existing file, it will be - ignored and this feature will be deactivated. - You will be prompted for the GPG passphrase when the release build starts, unless "gpg.passphrase" property is set. + The ant target "verify-release" also uses the property "gpg.exec" to + call the GPG executable. If you want to use "verify-release" but you + do not want to sign the release artefacts, set "gpg.exec" and also + "gpg.sign.files=false". + + 3. If building the Windows installer on Windows If running the build in a UAC enabled environment, building the Windows @@ -539,7 +540,16 @@ This is configured by setting "test.threads" property. The recommended value is one thread per core. - 6. Optional support is provided for the Cobertura code coverage tool. + 6. Test output can be suppressed for cleaner console output, especially useful + when running tests with multiple threads: + + ant test -Dtest.silent=true + + This suppresses JUnit console output while still saving all test results to + individual log files in output/build/logs. The test-status target will still + display a summary of any failures or skipped tests. + + 7. Optional support is provided for the Cobertura code coverage tool. NOTE: Cobertura is licensed under GPL v2 with parts of it being under Apache License v1.1. See https://cobertura.github.io/cobertura/ for details. diff -Nru tomcat10-10.1.40/CONTRIBUTING.md tomcat10-10.1.52/CONTRIBUTING.md --- tomcat10-10.1.40/CONTRIBUTING.md 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/CONTRIBUTING.md 2026-01-23 19:33:36.000000000 +0000 @@ -43,7 +43,7 @@ is pretty new to the project, so if there aren't any issues in the filter feel free to ask on the [dev list](https://tomcat.apache.org/lists.html#tomcat-dev). -* [Beginner issues](https://bz.apache.org/bugzilla/buglist.cgi?bug_status=NEW&bug_status=ASSIGNED&bug_status=REOPENED&bug_status=NEEDINFO&keywords=Beginner&keywords_type=allwords&list_id=160824&product=Tomcat%207&product=Tomcat%208.5&product=Tomcat%209&query_format=advanced) - +* [Beginner issues](https://bz.apache.org/bugzilla/buglist.cgi?bug_status=__open__&keywords=Beginner&keywords_type=allwords&product=Tomcat%209&product=Tomcat%2010&product=Tomcat%2011&query_format=advanced) - issues which should only require a few lines of code, and a test or two to resolve. diff -Nru tomcat10-10.1.40/MERGE.txt tomcat10-10.1.52/MERGE.txt --- tomcat10-10.1.40/MERGE.txt 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/MERGE.txt 2026-01-23 19:33:36.000000000 +0000 @@ -55,7 +55,7 @@ Sub-tree: src/main/java/org/apache/commons/fileupload The SHA1 ID / tag for the most recent commit to be merged to Tomcat is: -7a8c3241cfa8d036452cd4fc3f92d57cff189bca (2023-09-16) +rel/commons-fileupload-1.6.0 (2025-06-05) Note: Tomcat's copy of fileupload also includes classes copied manually from Commons IO. @@ -67,7 +67,7 @@ Sub-tree src/main/java/org/apache/commons/pool2 The SHA1 ID / tag for the most recent commit to be merged to Tomcat is: -rel/commons-pool-2.12.1 (2025-01-27) +rel/commons-pool-2.13.1 (2025-12-30) DBCP2 No unused code removed @@ -75,4 +75,4 @@ src/main/java/org/apache/commons/dbcp2 src/main/resources/org/apache/commons/dbcp2 The SHA1 ID / tag for the most recent commit to be merged to Tomcat is: -rel/commons-dbcp-2.13.0 (2024-12-02) +rel/commons-dbcp-2.14.0 (2025-12-16) diff -Nru tomcat10-10.1.40/NOTICE tomcat10-10.1.52/NOTICE --- tomcat10-10.1.40/NOTICE 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/NOTICE 2026-01-23 19:33:36.000000000 +0000 @@ -1,5 +1,5 @@ Apache Tomcat -Copyright 1999-2025 The Apache Software Foundation +Copyright 1999-2026 The Apache Software Foundation This product includes software developed at The Apache Software Foundation (https://www.apache.org/). diff -Nru tomcat10-10.1.40/README.md tomcat10-10.1.52/README.md --- tomcat10-10.1.40/README.md 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/README.md 2026-01-23 19:33:36.000000000 +0000 @@ -57,9 +57,7 @@ ### Support and Mailing List Information * Free community support is available through the -[tomcat-users](https://tomcat.apache.org/lists.html#tomcat-users) email list and -a dedicated [IRC channel](https://tomcat.apache.org/irc.html) (#tomcat on -Freenode). +[tomcat-users](https://tomcat.apache.org/lists.html#tomcat-users) email list. * If you want freely available support for running Apache Tomcat, please see the resources page [here](https://tomcat.apache.org/findhelp.html). diff -Nru tomcat10-10.1.40/RUNNING.txt tomcat10-10.1.52/RUNNING.txt --- tomcat10-10.1.40/RUNNING.txt 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/RUNNING.txt 2026-01-23 19:33:36.000000000 +0000 @@ -305,8 +305,8 @@ - + diff -Nru tomcat10-10.1.40/bin/catalina.bat tomcat10-10.1.52/bin/catalina.bat --- tomcat10-10.1.40/bin/catalina.bat 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/bin/catalina.bat 2026-01-23 19:33:36.000000000 +0000 @@ -224,7 +224,7 @@ set LOGGING_MANAGER=-Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager :noJuliManager -rem Configure module start-up parameters +rem Configure module start-up parameters - ensure to keep it in line with service.bat set "JAVA_OPTS=%JAVA_OPTS% --add-opens=java.base/java.lang=ALL-UNNAMED" set "JAVA_OPTS=%JAVA_OPTS% --add-opens=java.base/java.lang.reflect=ALL-UNNAMED" set "JAVA_OPTS=%JAVA_OPTS% --add-opens=java.base/java.io=ALL-UNNAMED" diff -Nru tomcat10-10.1.40/bin/service.bat tomcat10-10.1.52/bin/service.bat --- tomcat10-10.1.40/bin/service.bat 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/bin/service.bat 2026-01-23 19:33:36.000000000 +0000 @@ -200,6 +200,14 @@ ) ) +rem Configure JAVA 9 specific start-up parameters - ensure to keep it in line with catalina.bat +set "JVM9_OPTIONS=--add-opens=java.base/java.lang=ALL-UNNAMED" +set "JVM9_OPTIONS=%JVM9_OPTIONS%;--add-opens=java.base/java.lang.reflect=ALL-UNNAMED" +set "JVM9_OPTIONS=%JVM9_OPTIONS%;--add-opens=java.base/java.io=ALL-UNNAMED" +set "JVM9_OPTIONS=%JVM9_OPTIONS%;--add-opens=java.base/java.util=ALL-UNNAMED" +set "JVM9_OPTIONS=%JVM9_OPTIONS%;--add-opens=java.base/java.util.concurrent=ALL-UNNAMED" +set "JVM9_OPTIONS=%JVM9_OPTIONS%;--add-opens=java.rmi/sun.rmi.transport=ALL-UNNAMED" + "%EXECUTABLE%" //IS//%SERVICE_NAME% ^ --Description "Apache Tomcat @VERSION@ Server - https://tomcat.apache.org/" ^ --DisplayName "Apache Tomcat @VERSION_MAJOR_MINOR@ %SERVICE_NAME%" ^ @@ -217,8 +225,8 @@ --StopClass org.apache.catalina.startup.Bootstrap ^ --StartParams start ^ --StopParams stop ^ - --JvmOptions "-Dcatalina.home=%CATALINA_HOME%;-Dcatalina.base=%CATALINA_BASE%;-Djava.io.tmpdir=%CATALINA_BASE%\temp;-Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager;-Djava.util.logging.config.file=%CATALINA_BASE%\conf\logging.properties;%JvmArgs%" ^ - --JvmOptions9 "--add-opens=java.base/java.lang=ALL-UNNAMED#--add-opens=java.base/java.io=ALL-UNNAMED#--add-opens=java.base/java.util=ALL-UNNAMED#--add-opens=java.base/java.util.concurrent=ALL-UNNAMED#--add-opens=java.rmi/sun.rmi.transport=ALL-UNNAMED" ^ + --JvmOptions "-Dcatalina.home=%CATALINA_HOME%;-Dcatalina.base=%CATALINA_BASE%;-Djava.io.tmpdir=%CATALINA_BASE%\temp;-Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager;-Djava.util.logging.config.file=%CATALINA_BASE%\conf\logging.properties;-Dsun.io.useCanonCaches=false;%JvmArgs%" ^ + --JvmOptions9 "%JVM9_OPTIONS%" ^ --Startup "%SERVICE_STARTUP_MODE%" ^ --JvmMs "%JvmMs%" ^ --JvmMx "%JvmMx%" diff -Nru tomcat10-10.1.40/build.properties.default tomcat10-10.1.52/build.properties.default --- tomcat10-10.1.40/build.properties.default 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/build.properties.default 2026-01-23 19:33:36.000000000 +0000 @@ -7,7 +7,9 @@ # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 -## distributed under the License is distributed on an "AS IS" BASIS, +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. @@ -29,7 +31,7 @@ # ----- Version Control Flags ----- version.major=10 version.minor=1 -version.build=40 +version.build=52 version.patch=0 version.suffix= version.dev=-dev @@ -63,6 +65,7 @@ # works better for Tomcat. javadoc.failonerror=true javadoc.failonwarning=false +javadoc.locale=en # ----- Test configuration ----- execute.test.nio=true @@ -73,6 +76,8 @@ test.accesslog=false # Display the tests output on the console test.verbose=true +# Suppress JUnit console output (useful for parallel testing) +test.silent=false # Number of parallel threads to use for testing. The recommended value is one # thread per core. @@ -97,6 +102,8 @@ # ----- Release build settings ----- # Location of GPG executable gpg.exec=/path/to/gpg +# Release artefact signing with gpg +gpg.sign.files=true # Code signing of Windows installer # See https://infra.apache.org/digicert-use.html for setup instructions @@ -175,14 +182,14 @@ jdt.loc.2=https://download.eclipse.org/eclipse/downloads/drops4/${jdt.release}/ecj-${jdt.version}.jar # ----- Tomcat native library ----- -tomcat-native.version=2.0.8 -tomcat-native-openssl.version=3.0.14 +tomcat-native.version=2.0.12 +tomcat-native-openssl.version=3.5.4 tomcat-native.src.checksum.enabled=true tomcat-native.src.checksum.algorithm=SHA-512 -tomcat-native.src.checksum.value=fd45533b9c34b008717d18ed49334c7286b93c849c487c1c42746f2998cc4a6ff0362e536a8b5124c6539847a92a9f7631c7638a21cd5d22134fe1a9bb0f0702 +tomcat-native.src.checksum.value=d937e04f7c9f0fa6ef82b32928fa2d59dbdac45cb58c7ba8eff4338fbd942297b1c9512a0a8ff80cf758d9b6ca5cc5cba8cefdc91507318b72afc56888aa1f3c tomcat-native.win.checksum.enabled=true tomcat-native.win.checksum.algorithm=SHA-512 -tomcat-native.win.checksum.value=a4a8816668f14a7461711e25cb9277534981936c9e6f8b00ae55084cb265dc1d89ad07fa508ae2e1f7832236dafafbdd9d76a313c87f34e00ecfdfe75776638a +tomcat-native.win.checksum.value=f743c151a1d48a1967c08f01986b1a30176cc8a388ad760cb8aac19e6956e5630d7ddff54782c2e136e8f247809d573fd48a31ed1a756923a3ad0954e2d4a3fe tomcat-native.home=${base.path}/tomcat-native-${tomcat-native.version} tomcat-native.tar.gz=${tomcat-native.home}/tomcat-native.tar.gz tomcat-native.loc.1=${base-tomcat.loc.1}/tomcat-connectors/native/${tomcat-native.version}/source/tomcat-native-${tomcat-native.version}-src.tar.gz @@ -204,20 +211,20 @@ nsis.src.loc=${base-sf.loc}/nsis/nsis-${nsis.version}-src.tar.bz2 # ----- Commons Daemon, version 1.2.0 or later ----- -commons-daemon.version=1.4.1 +commons-daemon.version=1.5.1 -# checksum for commons-daemon-1.4.1-bin.tar.gz +# checksum for commons-daemon-1.5.1-bin.tar.gz commons-daemon.bin.checksum.enabled=true commons-daemon.bin.checksum.algorithm=SHA-512 -commons-daemon.bin.checksum.value=6e1e590d1b25b1c543b7e149748b25b7a200a20a70d490b1f2628ce808dd9da170d33c62b57421bdf7db0a9e0ac1df7f67de5e9ea4e70d500ec97ff7e6662e6a +commons-daemon.bin.checksum.value=740b832b8a7b5df8f2aa8029cf6ee88b8be6f4f5e42e34587a70bbf2cbe5b7e7dd75da375d2f3f1f7f2e6a5d89b5ceba5433499773852df67e8bbeb88b466786 -# checksums for commons-daemon-1.4.1-native-src.tar.gz, commons-daemon-1.4.1-bin-windows.zip +# checksums for commons-daemon-1.5.1-native-src.tar.gz, commons-daemon-1.5.1-bin-windows.zip commons-daemon.native.src.checksum.enabled=true commons-daemon.native.src.checksum.algorithm=SHA-512 -commons-daemon.native.src.checksum.value=578002ddd6d1a63488b9920b848d839cab39fca58c1e208b929b5c327590ca63c5878cd5280d2a2006191a8e81d93e5ca07414f6f6f4a72669352df72a5977b1 +commons-daemon.native.src.checksum.value=ced2238b4fb47a208e7c9aa435e7981b5d42fd9e07d11d7f72da2b7239c388a3b7d6b7ce3424624aecfbe7a8471ee316cdd46a040fadb129096705fa3325129b commons-daemon.native.win.checksum.enabled=true commons-daemon.native.win.checksum.algorithm=SHA-512 -commons-daemon.native.win.checksum.value=b8eeea01dbca495780e61db26776eab1561990d54499202bcb5d97c9f49e194ebc40002fabbaf74b5334481a2f42f80df5132efd0671632074df83759e04484a +commons-daemon.native.win.checksum.value=26cef55a0237aab449d2133e56815393729c3965c6fd063326bccdb569be91ddfe500b247ba3df3e9baac511452825d3d0333d165abd24932717a372a294a463 commons-daemon.home=${base.path}/commons-daemon-${commons-daemon.version} commons-daemon.jar=${commons-daemon.home}/commons-daemon-${commons-daemon.version}.jar @@ -251,10 +258,10 @@ hamcrest.loc=${base-maven.loc}/org/hamcrest/hamcrest/${hamcrest.version}/hamcrest-${hamcrest.version}.jar # ----- EasyMock, version 5.0.0 or later ----- -easymock.version=5.5.0 +easymock.version=5.6.0 easymock.checksum.enabled=true easymock.checksum.algorithm=MD5|SHA-1 -easymock.checksum.value=f1f7e94f70903b0c37a65dd2a011e31a|b07e2bcbc7b6bcae190a18b9ced742b6fd9ceec3 +easymock.checksum.value=2be7351f227b2022faf4230ceb576e0a|f8e15a47aac9838ee36be6c3eddc50bb78a06191 easymock.home=${base.path}/easymock-${easymock.version} easymock.jar=${easymock.home}/easymock-${easymock.version}.jar easymock.loc=${base-maven.loc}/org/easymock/easymock/${easymock.version}/easymock-${easymock.version}.jar @@ -269,66 +276,66 @@ objenesis.loc=${base-maven.loc}/org/objenesis/objenesis/${objenesis.version}/objenesis-${objenesis.version}.jar # ----- byte-buddy, used by EasyMock, version 1.12.18 or later ----- -bytebuddy.version=1.17.4 +bytebuddy.version=1.18.3 bytebuddy.checksum.enabled=true -bytebuddy.checksum.algorithm=MD5|SHA-1 -bytebuddy.checksum.value=7ba5cdb49a0e311e730b9a6dde61f95a|ffb8488d93290eff074fb542a596e4c5a26d0315 +bytebuddy.checksum.algorithm=SHA-512 +bytebuddy.checksum.value=8f35c806a25d9089a08d12a7aaf22c5bea2f356c432a21655f30a7935918b6385e1e080180b6ef5ad3638796fc3a7243220dfec08c31c1195416e6790fd797af bytebuddy.home=${base.path}/byte-buddy-${bytebuddy.version} bytebuddy.jar=${bytebuddy.home}/byte-buddy-${bytebuddy.version}.jar bytebuddy.loc=${base-maven.loc}/net/bytebuddy/byte-buddy/${bytebuddy.version}/byte-buddy-${bytebuddy.version}.jar # ----- UnboundID, used by unit tests, version 5.1.4 or later ----- -unboundid.version=7.0.2 +unboundid.version=7.0.4 unboundid.checksum.enabled=true -unboundid.checksum.algorithm=SHA-512 -unboundid.checksum.value=425a003273c8fb3ddcefae8273b322dae2186ccb48344c55e8a4a8251915ef0c595cd69566c3ef33476c3151bcd5b20a3492b2917c4959a83e30ca363cbce88e +unboundid.checksum.algorithm=MD5|SHA-1 +unboundid.checksum.value=7006a217741934517b1cdd6aa12c6d9f|2fe2d5461a87a58aee97f836e3af63ef8ce7b29e unboundid.home=${base.path}/unboundid-${unboundid.version} unboundid.jar=${unboundid.home}/unboundid-ldapsdk-${unboundid.version}.jar unboundid.loc=${base-maven.loc}/com/unboundid/unboundid-ldapsdk/${unboundid.version}/unboundid-ldapsdk-${unboundid.version}.jar # ----- Checkstyle, version 6.16 or later ----- -checkstyle.version=10.21.4 +checkstyle.version=12.3.1 checkstyle.checksum.enabled=true checkstyle.checksum.algorithm=SHA-512 -checkstyle.checksum.value=56f13d6dc4614ce3d41363d0b52f2ab3ebb75579823e066ac49ac13d00856fd11e3e8c5094b4b392a80afee8f652350d4aff2fd1675806ff375752a14a529abc +checkstyle.checksum.value=8406977982d6e5eb9dba561ccb319daa9d98fc7172217f0c36644d5830121124181752c425dcf34fb7579232983d923e430a5d6b119272ab8615e7b1e4f10bf1 checkstyle.home=${base.path}/checkstyle-${checkstyle.version} checkstyle.jar=${checkstyle.home}/checkstyle-${checkstyle.version}-all.jar checkstyle.loc=${base-gh.loc}/checkstyle/checkstyle/releases/download/checkstyle-${checkstyle.version}/checkstyle-${checkstyle.version}-all.jar # ----- JaCoCo code coverage tool ----- -jacoco.version=0.8.12 +jacoco.version=0.8.14 jacoco.checksum.enabled=true jacoco.checksum.algorithm=MD5|SHA-1 -jacoco.checksum.value=a85698213c36c6c964b1d4011a5f8770|c77282468d7e311b7e3e4b03dc9a8c7837902b4b +jacoco.checksum.value=1da00355854e56fe99b6c5b31224ea79|93f2e83229e20e02c556e412b041eff31132e60b jacoco.home=${base.path}/jacoco-${jacoco.version} jacoco.jar=${jacoco.home}/lib/jacocoant.jar jacoco.loc=${base-maven.loc}/org/jacoco/jacoco/${jacoco.version}/jacoco-${jacoco.version}.zip # ----- SpotBugs (originally FindBugs) ----- -spotbugs.version=4.9.3 +spotbugs.version=4.9.8 spotbugs.checksum.enabled=true spotbugs.checksum.algorithm=SHA-512 -spotbugs.checksum.value=e0c672d8db33f428726fc0832c6f5b46dbdeaf7631b9e64938b12416535e06758fc574eaaf6a98bd3de65d9b3275f94665fcc63bb1a309fa4f0195a86d4b0481 +spotbugs.checksum.value=9d0dde900b3e1330ca23b81ad9aaf292d2d9d144ff1db9d397bcbe58c5ebd86dcb36e3d83ba7c3043039d2557a9bd3af35f9dd14297fc5e908745924b9c51678 spotbugs.home=${base.path}/spotbugs-${spotbugs.version} spotbugs.jar=${spotbugs.home}/lib/spotbugs-ant.jar spotbugs.loc=${base-maven.loc}/com/github/spotbugs/spotbugs/${spotbugs.version}/spotbugs-${spotbugs.version}.tgz # ----- bnd, version 6.3.0 or later ----- # ----- provides OSGI metadata for JARs ----- -bnd.version=7.1.0 +bnd.version=7.2.0 bnd.checksum.enabled=true bnd.checksum.algorithm=MD5|SHA-1 -bnd.checksum.value=9cee533d5f3973d6135e557934160180|49e4ebe633c608c498cbfc7d7a4e9dda5fefa2fc +bnd.checksum.value=dea22b7afa9de21e1adb27d2e835a94c|af26ddc466eb178963d4eb800d2824f488037aec bnd.home=${base.path}/bnd-${bnd.version} bnd.jar=${bnd.home}/biz.aQute.bnd-${bnd.version}.jar bnd.loc=${base-maven.loc}/biz/aQute/bnd/biz.aQute.bnd/${bnd.version}/biz.aQute.bnd-${bnd.version}.jar # ----- Tomcat Migration Tool for Jakarta EE ----- -migration-lib.version=1.0.9 +migration-lib.version=1.0.10 migration-lib.checksum.enabled=true migration-lib.checksum.algorithm=MD5|SHA-1 -migration-lib.checksum.value=0c41a2032c09d943211be5d41aed3f8f|fe5473b73441e664842086b8496b940cd2c3c054 +migration-lib.checksum.value=264a836032d45f600e01a95b3d5925e3|c86a0981ae313658222fb576595c0546542c4911 migration-lib.home=${base.path}/migration-${migration-lib.version} migration-lib.jar=${migration-lib.home}/jakartaee-migration-${migration-lib.version}-shaded.jar @@ -336,10 +343,10 @@ # ----- JSign, version 4.1 or later ----- # Note: There are known issues with Tomcat and Jsign 7.0 and 7.1 -jsign.version=6.0 +jsign.version=7.4 jsign.checksum.enabled=true jsign.checksum.algorithm=MD5|SHA-1 -jsign.checksum.value=c14fe256b5bc42dc6934d3ce7b659cdf|d2f1a60711c3b51123f84cd9e04dd9d482d95f5e +jsign.checksum.value=18b96a09ba9e1f0bdba58775810550f5|09705503ca76807141398ded4b35ce3f987a6903 jsign.home=${base.path}/jsign-${jsign.version} jsign.jar=${jsign.home}/jsign-${jsign.version}.jar diff -Nru tomcat10-10.1.40/build.properties.release tomcat10-10.1.52/build.properties.release --- tomcat10-10.1.40/build.properties.release 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/build.properties.release 2026-01-23 19:33:36.000000000 +0000 @@ -24,7 +24,7 @@ version.dev= # Ensure consistent timestamps for reproducible builds. -ant.tstamp.now.iso=2025-04-01T17:20:53Z +ant.tstamp.now.iso=2026-01-23T19:29:07Z # Enable insertion of detached signatures into the Windows installer. do.codesigning=true @@ -41,14 +41,14 @@ # # Java Name: OpenJDK 64-Bit Server VM # Java Vendor: Eclipse Adoptium -# Java Version: 23.0.2+7 +# Java Version: 25.0.1+8-LTS # The following is provided for information only. Builds will be repeatable # whether or not the build environment is consistent with this information. # -# OS: aarch64 Mac OS X 15.1.1 +# OS: aarch64 Mac OS X 15.7.3 # File encoding: UTF-8 # # Release Manager: schultz -release-java-version=23.0.2+7 +release-java-version=25.0.1+8-LTS release-ant-version=1.10.15 diff -Nru tomcat10-10.1.40/build.xml tomcat10-10.1.52/build.xml --- tomcat10-10.1.40/build.xml 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/build.xml 2026-01-23 19:33:36.000000000 +0000 @@ -198,7 +198,7 @@ - + @@ -312,11 +312,14 @@ + + + @@ -453,12 +456,16 @@ + + - + + + @@ -468,6 +475,7 @@ + @@ -545,6 +553,7 @@ + @@ -560,6 +569,7 @@ + @@ -633,7 +643,6 @@ - @@ -919,6 +928,8 @@ + + @@ -926,6 +937,8 @@ + + @@ -954,6 +967,8 @@ + + @@ -1924,7 +1939,7 @@ - + @@ -1941,14 +1956,112 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + depends="-test-name-default,test-nio,test-nio2,coverage-report,test-status" /> + depends="clean-classes,-test-name-default,test-nio,test-nio2,coverage-report,test-status" /> + depends="-test-name-default,test-only-nio,test-only-nio2,test-status" /> @@ -1986,13 +2099,13 @@ + depends="-test-name-default,setup-jacoco,test-compile,deploy,test-openssl-exists" if="${execute.test.nio}"> + depends="-test-name-default,setup-jacoco,test-openssl-exists" if="${execute.test.nio}"> @@ -2051,7 +2164,7 @@ enabled="${test.coverage}" destfile="${coverage.datafile}" > - - - + + - - + + - + - + - -gpg.exec.available=${gpg.exec.available} -gpg.exec=${gpg.exec} - Enter GPG passphrase - + + + + + + + + gpg.exec.available=${gpg.exec.available} + gpg.exec=${gpg.exec} + Enter GPG passphrase: - + + + @@ -4432,6 +4563,86 @@ + + + + + + + + + + + + + + + + + + + + + + + +Valid signature for @{src-or-bin}/@{basefile} + + + + + +********************************************** +********************************************** +Invalid signature for @{src-or-bin}/@{basefile} +********************************************** +********************************************** + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +Unable to locate release signature for @{basefile} + + + + @@ -4446,6 +4657,16 @@ + + + + + + + + + + @@ -4457,6 +4678,17 @@ + + + + + + + + + + + @@ -4468,6 +4700,23 @@ + +Don't worry if there are a bunch of "WARNING: untrusted key" warnings below. +It's just because the KEYS -> apache-keys import doesn't contain any ownertrust +information. + + + + + + + + + + + + + diff -Nru tomcat10-10.1.40/debian/patches/0013-dont-look-for-build-properties-in-user-home.patch tomcat10-10.1.52/debian/patches/0013-dont-look-for-build-properties-in-user-home.patch --- tomcat10-10.1.40/debian/patches/0013-dont-look-for-build-properties-in-user-home.patch 2025-04-03 13:25:52.000000000 +0000 +++ tomcat10-10.1.52/debian/patches/0013-dont-look-for-build-properties-in-user-home.patch 2026-02-03 12:29:34.000000000 +0000 @@ -10,9 +10,11 @@ build.xml | 1 - 1 file changed, 1 deletion(-) +diff --git a/build.xml b/build.xml +index 31c9129..404ba8c 100644 --- a/build.xml +++ b/build.xml -@@ -858,7 +858,6 @@ +@@ -867,7 +867,6 @@ diff -Nru tomcat10-10.1.40/debian/patches/0018-fix-manager-webapp.patch tomcat10-10.1.52/debian/patches/0018-fix-manager-webapp.patch --- tomcat10-10.1.40/debian/patches/0018-fix-manager-webapp.patch 2025-04-03 13:25:26.000000000 +0000 +++ tomcat10-10.1.52/debian/patches/0018-fix-manager-webapp.patch 2026-02-03 12:29:34.000000000 +0000 @@ -13,6 +13,8 @@ webapps/host-manager/WEB-INF/manager.xml | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) +diff --git a/conf/catalina.policy b/conf/catalina.policy +index 6a82bcb..9ca7802 100644 --- a/conf/catalina.policy +++ b/conf/catalina.policy @@ -188,7 +188,7 @@ grant { @@ -24,7 +26,7 @@ permission java.lang.RuntimePermission "accessClassInPackage.org.apache.catalina"; permission java.lang.RuntimePermission "accessClassInPackage.org.apache.catalina.ha.session"; permission java.lang.RuntimePermission "accessClassInPackage.org.apache.catalina.manager"; -@@ -196,7 +196,7 @@ grant codeBase "file:${catalina.base}/we +@@ -196,7 +196,7 @@ grant codeBase "file:${catalina.base}/webapps/manager/-" { permission java.lang.RuntimePermission "accessClassInPackage.org.apache.catalina.util"; permission org.apache.catalina.security.DeployXmlPermission "manager"; }; @@ -33,7 +35,7 @@ permission java.lang.RuntimePermission "accessClassInPackage.org.apache.catalina"; permission java.lang.RuntimePermission "accessClassInPackage.org.apache.catalina.ha.session"; permission java.lang.RuntimePermission "accessClassInPackage.org.apache.catalina.manager"; -@@ -211,10 +211,10 @@ grant codeBase "file:${catalina.home}/we +@@ -211,10 +211,10 @@ grant codeBase "file:${catalina.home}/webapps/manager/-" { // - default CATALINA_HOME == CATALINA_BASE // - CATALINA_HOME != CATALINA_BASE, per instance Host Manager in CATALINA_BASE // - CATALINA_HOME != CATALINA_BASE, shared Host Manager in CATALINA_HOME @@ -46,16 +48,18 @@ permission org.apache.catalina.security.DeployXmlPermission "host-manager"; }; -@@ -260,4 +260,4 @@ grant codeBase "file:${catalina.home}/we +@@ -260,4 +260,4 @@ grant codeBase "file:${catalina.home}/webapps/host-manager/-" { // // The permissions granted to a specific JAR // grant codeBase "war:file:${catalina.base}/webapps/examples.war*/WEB-INF/lib/foo.jar" { -// }; \ No newline at end of file +// }; +diff --git a/webapps/docs/manager-howto.xml b/webapps/docs/manager-howto.xml +index 3bd65b9..07512b0 100644 --- a/webapps/docs/manager-howto.xml +++ b/webapps/docs/manager-howto.xml -@@ -74,7 +74,7 @@ configuration file in the +@@ -73,7 +73,7 @@ configuration file in the $CATALINA_BASE/conf/[enginename]/[hostname] folder. Here is an example:

- +diff --git a/java/org/apache/catalina/util/ServerInfo.properties b/java/org/apache/catalina/util/ServerInfo.properties +index 3aa34f4..c8dff06 100644 --- a/java/org/apache/catalina/util/ServerInfo.properties +++ b/java/org/apache/catalina/util/ServerInfo.properties @@ -13,7 +13,7 @@ diff -Nru tomcat10-10.1.40/debian/patches/0021-dont-test-unsupported-ciphers.patch tomcat10-10.1.52/debian/patches/0021-dont-test-unsupported-ciphers.patch --- tomcat10-10.1.40/debian/patches/0021-dont-test-unsupported-ciphers.patch 2025-04-03 13:28:21.000000000 +0000 +++ tomcat10-10.1.52/debian/patches/0021-dont-test-unsupported-ciphers.patch 2026-02-03 12:29:34.000000000 +0000 @@ -12,9 +12,11 @@ .../tomcat/util/net/openssl/ciphers/TesterOpenSSL.java | 18 ++++++++++++++++++ 3 files changed, 20 insertions(+), 2 deletions(-) +diff --git a/test/org/apache/tomcat/util/net/openssl/ciphers/TestCipher.java b/test/org/apache/tomcat/util/net/openssl/ciphers/TestCipher.java +index 9b9eb5e..9d81307 100644 --- a/test/org/apache/tomcat/util/net/openssl/ciphers/TestCipher.java +++ b/test/org/apache/tomcat/util/net/openssl/ciphers/TestCipher.java -@@ -76,7 +76,7 @@ +@@ -76,7 +76,7 @@ public class TestCipher { // OpenSSL does not include ECDH/ECDHE ciphers in all and there is no // EC alias. Use aRSA. // OpenSSL 1.0.0 onwards does not include eNULL in all. @@ -23,9 +25,11 @@ Set expectedCipherSuites = new HashSet<>(); for (Cipher cipher : Cipher.values()) { +diff --git a/test/org/apache/tomcat/util/net/openssl/ciphers/TestOpenSSLCipherConfigurationParser.java b/test/org/apache/tomcat/util/net/openssl/ciphers/TestOpenSSLCipherConfigurationParser.java +index 1c2b946..8bb4315 100644 --- a/test/org/apache/tomcat/util/net/openssl/ciphers/TestOpenSSLCipherConfigurationParser.java +++ b/test/org/apache/tomcat/util/net/openssl/ciphers/TestOpenSSLCipherConfigurationParser.java -@@ -573,7 +573,7 @@ +@@ -573,7 +573,7 @@ public class TestOpenSSLCipherConfigurationParser { private void testSpecification(String specification) throws Exception { // Filter out cipher suites that OpenSSL does not implement @@ -34,9 +38,11 @@ List jsseCipherListFromOpenSSL = OpenSSLCipherConfigurationParser.parseExpression(openSSLCipherList); List jsseCipherListFromParser = +diff --git a/test/org/apache/tomcat/util/net/openssl/ciphers/TesterOpenSSL.java b/test/org/apache/tomcat/util/net/openssl/ciphers/TesterOpenSSL.java +index 1c1cf5a..0dc9db8 100644 --- a/test/org/apache/tomcat/util/net/openssl/ciphers/TesterOpenSSL.java +++ b/test/org/apache/tomcat/util/net/openssl/ciphers/TesterOpenSSL.java -@@ -105,6 +105,24 @@ +@@ -105,6 +105,24 @@ public class TesterOpenSSL { unimplemented.add(Cipher.SSL2_RC4_128_EXPORT40_WITH_MD5); unimplemented.add(Cipher.SSL2_IDEA_128_CBC_WITH_MD5); unimplemented.add(Cipher.SSL2_DES_192_EDE3_CBC_WITH_MD5); diff -Nru tomcat10-10.1.40/debian/patches/0023-disable-shutdown-by-socket.patch tomcat10-10.1.52/debian/patches/0023-disable-shutdown-by-socket.patch --- tomcat10-10.1.40/debian/patches/0023-disable-shutdown-by-socket.patch 2025-04-03 13:25:26.000000000 +0000 +++ tomcat10-10.1.52/debian/patches/0023-disable-shutdown-by-socket.patch 2026-02-03 12:29:34.000000000 +0000 @@ -7,6 +7,8 @@ conf/server.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) +diff --git a/conf/server.xml b/conf/server.xml +index 0ab6264..cf8f617 100644 --- a/conf/server.xml +++ b/conf/server.xml @@ -19,7 +19,7 @@ diff -Nru tomcat10-10.1.40/debian/patches/0024-systemd-log-formatter.patch tomcat10-10.1.52/debian/patches/0024-systemd-log-formatter.patch --- tomcat10-10.1.40/debian/patches/0024-systemd-log-formatter.patch 2025-04-03 13:25:26.000000000 +0000 +++ tomcat10-10.1.52/debian/patches/0024-systemd-log-formatter.patch 2026-02-03 12:29:34.000000000 +0000 @@ -8,6 +8,9 @@ 1 file changed, 109 insertions(+) create mode 100644 java/org/apache/juli/SystemdFormatter.java +diff --git a/java/org/apache/juli/SystemdFormatter.java b/java/org/apache/juli/SystemdFormatter.java +new file mode 100644 +index 0000000..014a193 --- /dev/null +++ b/java/org/apache/juli/SystemdFormatter.java @@ -0,0 +1,109 @@ diff -Nru tomcat10-10.1.40/debian/patches/0025-invalid-configuration-exit-status.patch tomcat10-10.1.52/debian/patches/0025-invalid-configuration-exit-status.patch --- tomcat10-10.1.40/debian/patches/0025-invalid-configuration-exit-status.patch 2025-04-03 13:28:17.000000000 +0000 +++ tomcat10-10.1.52/debian/patches/0025-invalid-configuration-exit-status.patch 2026-02-03 12:29:34.000000000 +0000 @@ -8,9 +8,11 @@ java/org/apache/catalina/startup/Bootstrap.java | 4 ++++ 1 file changed, 4 insertions(+) +diff --git a/java/org/apache/catalina/startup/Bootstrap.java b/java/org/apache/catalina/startup/Bootstrap.java +index 8dfc1fb..7250ff7 100644 --- a/java/org/apache/catalina/startup/Bootstrap.java +++ b/java/org/apache/catalina/startup/Bootstrap.java -@@ -473,6 +473,10 @@ +@@ -470,6 +470,10 @@ public final class Bootstrap { case "start": daemon.setAwait(true); daemon.load(args); diff -Nru tomcat10-10.1.40/debian/patches/0026-easymock4-compatibility.patch tomcat10-10.1.52/debian/patches/0026-easymock4-compatibility.patch --- tomcat10-10.1.40/debian/patches/0026-easymock4-compatibility.patch 2025-04-03 13:25:26.000000000 +0000 +++ tomcat10-10.1.52/debian/patches/0026-easymock4-compatibility.patch 2026-02-03 12:29:34.000000000 +0000 @@ -5,12 +5,13 @@ Forwarded: no --- .../valves/TestCrawlerSessionManagerValve.java | 28 +++++++++++----------- - test/org/apache/catalina/valves/TestSSLValve.java | 4 ++-- - 2 files changed, 16 insertions(+), 16 deletions(-) + 1 file changed, 14 insertions(+), 14 deletions(-) +diff --git a/test/org/apache/catalina/valves/TestCrawlerSessionManagerValve.java b/test/org/apache/catalina/valves/TestCrawlerSessionManagerValve.java +index c813156..484ebf8 100644 --- a/test/org/apache/catalina/valves/TestCrawlerSessionManagerValve.java +++ b/test/org/apache/catalina/valves/TestCrawlerSessionManagerValve.java -@@ -57,13 +57,13 @@ public class TestCrawlerSessionManagerVa +@@ -57,13 +57,13 @@ public class TestCrawlerSessionManagerValve { CrawlerSessionManagerValve valve = new CrawlerSessionManagerValve(); valve.setCrawlerIps("216\\.58\\.206\\.174"); valve.setCrawlerUserAgents(valve.getCrawlerUserAgents()); @@ -26,7 +27,7 @@ EasyMock.verify(request, session); } -@@ -73,13 +73,13 @@ public class TestCrawlerSessionManagerVa +@@ -73,13 +73,13 @@ public class TestCrawlerSessionManagerValve { CrawlerSessionManagerValve valve = new CrawlerSessionManagerValve(); valve.setCrawlerIps("216\\.58\\.206\\.174"); valve.setCrawlerUserAgents(valve.getCrawlerUserAgents()); @@ -42,7 +43,7 @@ EasyMock.verify(request, session); } -@@ -90,7 +90,7 @@ public class TestCrawlerSessionManagerVa +@@ -90,7 +90,7 @@ public class TestCrawlerSessionManagerValve { valve.setCrawlerUserAgents(valve.getCrawlerUserAgents()); valve.setHostAware(true); valve.setContextAware(true); @@ -51,7 +52,7 @@ verifyCrawlingLocalhost(valve, "localhost"); verifyCrawlingLocalhost(valve, "example.invalid"); -@@ -102,7 +102,7 @@ public class TestCrawlerSessionManagerVa +@@ -102,7 +102,7 @@ public class TestCrawlerSessionManagerValve { valve.setCrawlerUserAgents(valve.getCrawlerUserAgents()); valve.setHostAware(true); valve.setContextAware(true); @@ -60,7 +61,7 @@ verifyCrawlingContext(valve, "/examples"); verifyCrawlingContext(valve, null); -@@ -113,7 +113,7 @@ public class TestCrawlerSessionManagerVa +@@ -113,7 +113,7 @@ public class TestCrawlerSessionManagerValve { CrawlerSessionManagerValve valve = new CrawlerSessionManagerValve(); valve.setCrawlerIps("216\\.58\\.206\\.174"); valve.setCrawlerUserAgents(valve.getCrawlerUserAgents()); @@ -69,7 +70,7 @@ valve.setSessionInactiveInterval(0); StandardSession session = new StandardSession(TEST_MANAGER); session.setId("id"); -@@ -123,7 +123,7 @@ public class TestCrawlerSessionManagerVa +@@ -123,7 +123,7 @@ public class TestCrawlerSessionManagerValve { EasyMock.replay(request); @@ -78,7 +79,7 @@ EasyMock.verify(request); -@@ -142,7 +142,7 @@ public class TestCrawlerSessionManagerVa +@@ -142,7 +142,7 @@ public class TestCrawlerSessionManagerValve { EasyMock.replay(request, session); @@ -87,7 +88,7 @@ EasyMock.verify(request, session); } -@@ -156,14 +156,14 @@ public class TestCrawlerSessionManagerVa +@@ -156,14 +156,14 @@ public class TestCrawlerSessionManagerValve { EasyMock.replay(request, session); @@ -104,16 +105,16 @@ if (isBot) { EasyMock.expect(session.getId()).andReturn("id").times(1); session.setAttribute(EasyMock.eq(valve.getClass().getName()), -@@ -182,7 +182,7 @@ public class TestCrawlerSessionManagerVa +@@ -182,7 +182,7 @@ public class TestCrawlerSessionManagerValve { private Request createRequestExpectations(String ip, HttpSession session, boolean isBot, String hostname, String contextPath, String userAgent) { - Request request = EasyMock.createMock(Request.class); + Request request = (Request) EasyMock.createMock(Request.class); EasyMock.expect(request.getRemoteAddr()).andReturn(ip); + EasyMock.expect(request.getRemoteAddr()).andReturn(ip); EasyMock.expect(request.getHost()).andReturn(simpleHostWithName(hostname)); - EasyMock.expect(request.getContext()).andReturn(simpleContextWithName(contextPath)); -@@ -196,7 +196,7 @@ public class TestCrawlerSessionManagerVa +@@ -198,7 +198,7 @@ public class TestCrawlerSessionManagerValve { } private Host simpleHostWithName(String hostname) { @@ -122,7 +123,7 @@ EasyMock.expect(host.getName()).andReturn(hostname); EasyMock.replay(host); return host; -@@ -206,7 +206,7 @@ public class TestCrawlerSessionManagerVa +@@ -208,7 +208,7 @@ public class TestCrawlerSessionManagerValve { if (contextPath == null) { return null; } @@ -131,23 +132,3 @@ EasyMock.expect(context.getName()).andReturn(contextPath); EasyMock.replay(context); return context; ---- a/test/org/apache/catalina/valves/TestSSLValve.java -+++ b/test/org/apache/catalina/valves/TestSSLValve.java -@@ -37,7 +37,7 @@ public class TestSSLValve { - public static class MockRequest extends Request { - - public MockRequest() { -- super(EasyMock.createMock(Connector.class)); -+ super((Connector) EasyMock.createMock(Connector.class)); - setCoyoteRequest(new org.apache.coyote.Request()); - } - -@@ -94,7 +94,7 @@ public class TestSSLValve { - private SSLValve valve = new SSLValve(); - - private MockRequest mockRequest = new MockRequest(); -- private Valve mockNext = EasyMock.createMock(Valve.class); -+ private Valve mockNext = (Valve) EasyMock.createMock(Valve.class); - - - @Before diff -Nru tomcat10-10.1.40/debian/patches/0030-eclipse-jdt-classpath.patch tomcat10-10.1.52/debian/patches/0030-eclipse-jdt-classpath.patch --- tomcat10-10.1.40/debian/patches/0030-eclipse-jdt-classpath.patch 2025-04-03 13:25:26.000000000 +0000 +++ tomcat10-10.1.52/debian/patches/0030-eclipse-jdt-classpath.patch 2026-02-03 12:29:34.000000000 +0000 @@ -1,6 +1,14 @@ -Description: Updates the Eclipse Compiler classpath -Author: Emmanuel Bourg +From: Emmanuel Bourg +Date: Wed, 28 Jan 2026 04:57:59 +0100 +Subject: Updates the Eclipse Compiler classpath + Forwarded: no +--- + build.xml | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/build.xml b/build.xml +index 5f30263..7d05c45 100644 --- a/build.xml +++ b/build.xml @@ -233,6 +233,7 @@ diff -Nru tomcat10-10.1.40/debian/patches/disable-jacoco.patch tomcat10-10.1.52/debian/patches/disable-jacoco.patch --- tomcat10-10.1.40/debian/patches/disable-jacoco.patch 2025-04-03 13:28:24.000000000 +0000 +++ tomcat10-10.1.52/debian/patches/disable-jacoco.patch 2026-02-03 12:29:34.000000000 +0000 @@ -1,15 +1,17 @@ From: Markus Koschany -Date: Wed, 1 Feb 2023 00:11:33 +0100 -Subject: disable-jacoco +Date: Wed, 28 Jan 2026 04:59:30 +0100 +Subject: disable jacoco Forwarded: not-needed --- build.xml | 12 ------------ 1 file changed, 12 deletions(-) +diff --git a/build.xml b/build.xml +index 7d05c45..969b037 100644 --- a/build.xml +++ b/build.xml -@@ -2054,10 +2054,6 @@ +@@ -2167,10 +2167,6 @@ @@ -17,10 +19,10 @@ - enabled="${test.coverage}" - destfile="${coverage.datafile}" - > - @@ -28,7 +30,7 @@ -@@ -3723,15 +3718,8 @@ +@@ -3853,15 +3848,8 @@ Configured for ${release.asfusername} to release Tomcat ${version.major}.${versi diff -Nru tomcat10-10.1.40/debian/patches/exclude-TestJNDIRealmIntegration.patch tomcat10-10.1.52/debian/patches/exclude-TestJNDIRealmIntegration.patch --- tomcat10-10.1.40/debian/patches/exclude-TestJNDIRealmIntegration.patch 2025-04-03 13:28:22.000000000 +0000 +++ tomcat10-10.1.52/debian/patches/exclude-TestJNDIRealmIntegration.patch 2026-02-03 12:29:34.000000000 +0000 @@ -1,5 +1,5 @@ From: Markus Koschany -Date: Fri, 24 Sep 2021 16:29:54 +0200 +Date: Wed, 28 Jan 2026 05:12:44 +0100 Subject: exclude TestJNDIRealmIntegration Exclude TestJNDIRealmIntegration.java because it FTBFS due to missing @@ -7,20 +7,22 @@ Forwarded: not-needed --- - build.xml | 1 + - 1 file changed, 1 insertion(+) + build.xml | 2 ++ + 1 file changed, 2 insertions(+) +diff --git a/build.xml b/build.xml +index 969b037..5c56c29 100644 --- a/build.xml +++ b/build.xml -@@ -1929,6 +1929,7 @@ +@@ -1945,6 +1945,7 @@ - + +
-@@ -2125,6 +2126,7 @@ +@@ -2235,6 +2236,7 @@ tests. See below for more details. --> diff -Nru tomcat10-10.1.40/debian/patches/series tomcat10-10.1.52/debian/patches/series --- tomcat10-10.1.40/debian/patches/series 2025-04-03 13:25:26.000000000 +0000 +++ tomcat10-10.1.52/debian/patches/series 2026-02-03 12:29:34.000000000 +0000 @@ -10,6 +10,6 @@ 0025-invalid-configuration-exit-status.patch 0026-easymock4-compatibility.patch 0021-dont-test-unsupported-ciphers.patch -exclude-TestJNDIRealmIntegration.patch -disable-jacoco.patch 0030-eclipse-jdt-classpath.patch +disable-jacoco.patch +exclude-TestJNDIRealmIntegration.patch diff -Nru tomcat10-10.1.40/java/jakarta/el/ELContextListener.java tomcat10-10.1.52/java/jakarta/el/ELContextListener.java --- tomcat10-10.1.40/java/jakarta/el/ELContextListener.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/jakarta/el/ELContextListener.java 2026-01-23 19:33:36.000000000 +0000 @@ -16,9 +16,6 @@ */ package jakarta.el; -/** - * @author Jacob Hookom [jacob/hookom.net] - */ public interface ELContextListener extends java.util.EventListener { void contextCreated(ELContextEvent event); diff -Nru tomcat10-10.1.40/java/jakarta/el/ELResolver.java tomcat10-10.1.52/java/jakarta/el/ELResolver.java --- tomcat10-10.1.40/java/jakarta/el/ELResolver.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/jakarta/el/ELResolver.java 2026-01-23 19:33:36.000000000 +0000 @@ -18,9 +18,6 @@ import java.util.Iterator; -/** - * @author Jacob Hookom [jacob/hookom.net] - */ public abstract class ELResolver { public static final String TYPE = "type"; diff -Nru tomcat10-10.1.40/java/jakarta/el/ExpressionFactory.java tomcat10-10.1.52/java/jakarta/el/ExpressionFactory.java --- tomcat10-10.1.40/java/jakarta/el/ExpressionFactory.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/jakarta/el/ExpressionFactory.java 2026-01-23 19:33:36.000000000 +0000 @@ -360,8 +360,8 @@ } } catch (FileNotFoundException e) { // Should not happen - ignore it if it does - } catch (IOException e) { - throw new ELException(Util.message(null, "expressionFactory.readFailed", PROPERTY_FILE), e); + } catch (IOException ioe) { + throw new ELException(Util.message(null, "expressionFactory.readFailed", PROPERTY_FILE), ioe); } } return null; @@ -375,4 +375,4 @@ return null; } -} +} \ No newline at end of file diff -Nru tomcat10-10.1.40/java/jakarta/el/ImportHandler.java tomcat10-10.1.52/java/jakarta/el/ImportHandler.java --- tomcat10-10.1.40/java/jakarta/el/ImportHandler.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/jakarta/el/ImportHandler.java 2026-01-23 19:33:36.000000000 +0000 @@ -136,7 +136,7 @@ standardPackages.put("jakarta.servlet.jsp", servletJspClassNames); Set javaLangClassNames = new HashSet<>(); - // Based on Java 21 EA29 + // Based on Java 26 EA26 // Interfaces javaLangClassNames.add("Appendable"); javaLangClassNames.add("AutoCloseable"); @@ -144,6 +144,7 @@ javaLangClassNames.add("Cloneable"); javaLangClassNames.add("Comparable"); javaLangClassNames.add("Iterable"); + javaLangClassNames.add("LazyConstant"); javaLangClassNames.add("ProcessHandle"); javaLangClassNames.add("ProcessHandle.Info"); javaLangClassNames.add("Readable"); @@ -168,6 +169,7 @@ javaLangClassNames.add("Enum"); javaLangClassNames.add("Enum.EnumDesc"); javaLangClassNames.add("Float"); + javaLangClassNames.add("IO"); javaLangClassNames.add("InheritableThreadLocal"); javaLangClassNames.add("Integer"); javaLangClassNames.add("Long"); @@ -190,6 +192,7 @@ javaLangClassNames.add("ScopedValue.Carrier"); javaLangClassNames.add("SecurityManager"); javaLangClassNames.add("Short"); + javaLangClassNames.add("StableValue"); javaLangClassNames.add("StackTraceElement"); javaLangClassNames.add("StackWalker"); javaLangClassNames.add("StrictMath"); @@ -400,6 +403,18 @@ clazzes.put(name, clazz); return clazz; } + // Might be an inner class + StringBuilder sb = new StringBuilder(className); + int replacementPosition = sb.lastIndexOf("."); + while (replacementPosition > -1) { + sb.setCharAt(replacementPosition, '$'); + clazz = findClass(sb.toString(), true); + if (clazz != null) { + clazzes.put(name, clazz); + return clazz; + } + replacementPosition = sb.lastIndexOf(".", replacementPosition); + } } // Search the package imports - note there may be multiple matches diff -Nru tomcat10-10.1.40/java/jakarta/el/Util.java tomcat10-10.1.52/java/jakarta/el/Util.java --- tomcat10-10.1.40/java/jakarta/el/Util.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/jakarta/el/Util.java 2026-01-23 19:33:36.000000000 +0000 @@ -130,7 +130,7 @@ try { Method method = clazz.getMethod(methodName, paramTypes); return getMethod(clazz, base, method); - } catch (NoSuchMethodException | SecurityException e) { + } catch (NoSuchMethodException | SecurityException ignore) { // Fall through to broader, slower logic } } diff -Nru tomcat10-10.1.40/java/jakarta/servlet/LocalStrings_ru.properties tomcat10-10.1.52/java/jakarta/servlet/LocalStrings_ru.properties --- tomcat10-10.1.40/java/jakarta/servlet/LocalStrings_ru.properties 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/jakarta/servlet/LocalStrings_ru.properties 2026-01-23 19:33:36.000000000 +0000 @@ -17,3 +17,9 @@ # To edit translations see: https://tomcat.apache.org/getinvolved.html#Translations httpMethodConstraintElement.invalidMethod=Ошибочный HTTP метод + +value.false=ложный +value.true=истина + +wrapper.nullRequest=запрос не может быть null +wrapper.nullResponse=Ответ не может быть null diff -Nru tomcat10-10.1.40/java/jakarta/servlet/http/HttpServlet.java tomcat10-10.1.52/java/jakarta/servlet/http/HttpServlet.java --- tomcat10-10.1.40/java/jakarta/servlet/http/HttpServlet.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/jakarta/servlet/http/HttpServlet.java 2026-01-23 19:33:36.000000000 +0000 @@ -683,9 +683,8 @@ if (REQUEST_FACADE_CLAZZ.isAssignableFrom(req.getClass())) { try { return ((Boolean) GET_ALLOW_TRACE.invoke(req, (Object[]) null)).booleanValue(); - } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) { + } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException ignore) { // Should never happen given the checks in place. - // Ignore } } } @@ -892,11 +891,11 @@ Writer osw = null; try { osw = new OutputStreamWriter(out, encoding); - } catch (UnsupportedEncodingException e) { - // Impossible. - // The same values were used in the constructor. If this method - // gets called then the constructor must have succeeded so the - // above call must also succeed. + } catch (UnsupportedEncodingException ignore) { + /* + * Impossible. The same values were used in the constructor. If this method gets called then the + * constructor must have succeeded so the above call must also succeed. + */ } pw = new PrintWriter(osw); } diff -Nru tomcat10-10.1.40/java/jakarta/servlet/http/HttpServletRequest.java tomcat10-10.1.52/java/jakarta/servlet/http/HttpServletRequest.java --- tomcat10-10.1.40/java/jakarta/servlet/http/HttpServletRequest.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/jakarta/servlet/http/HttpServletRequest.java 2026-01-23 19:33:36.000000000 +0000 @@ -294,8 +294,8 @@ String getRequestedSessionId(); /** - * Returns the part of this request's URL from the protocol name up to the query string in the first line of the - * HTTP request. The web container does not decode this String. For example: + * Returns the URI path part of this request's URL which starts after the authority (if any) and ends before the + * query string delimiter ({@code ?}), if any. The web container does not decode this String. For example: * * * @@ -317,7 +317,8 @@ *

* To reconstruct a URL with a scheme and host, use {@link #getRequestURL}. * - * @return a String containing the part of the URL from the protocol name up to the query string + * @return a String containing the path part of the URL from after the authority to before the query + * string * * @see #getRequestURL */ diff -Nru tomcat10-10.1.40/java/jakarta/servlet/http/LocalStrings_ja.properties tomcat10-10.1.52/java/jakarta/servlet/http/LocalStrings_ja.properties --- tomcat10-10.1.40/java/jakarta/servlet/http/LocalStrings_ja.properties 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/jakarta/servlet/http/LocalStrings_ja.properties 2026-01-23 19:33:36.000000000 +0000 @@ -28,7 +28,7 @@ http.method_delete_not_supported=HTTPのDELETEメソッドは、このURLではサポートされていません。 http.method_get_not_supported=HTTPのGETメソッドは、このURLではサポートされていません。 -http.method_not_implemented=メソッド [{0}] は RFC 2068 には定義されておらず、サーブレット API ではサポートされません +http.method_not_implemented=メソッド [{0}] はこの URI のこのサーブレットでは実装されていません http.method_post_not_supported=HTTPのPOSTメソッドは、このURLではサポートされていません。 http.method_put_not_supported=HTTPのPUTメソッドは、このURLではサポートされていません。 http.non_http=リクエストが HTTP リクエストではない、あるいはレスポンスが HTTP レスポンスではありません。 diff -Nru tomcat10-10.1.40/java/jakarta/servlet/http/LocalStrings_ru.properties tomcat10-10.1.52/java/jakarta/servlet/http/LocalStrings_ru.properties --- tomcat10-10.1.40/java/jakarta/servlet/http/LocalStrings_ru.properties 1970-01-01 00:00:00.000000000 +0000 +++ tomcat10-10.1.52/java/jakarta/servlet/http/LocalStrings_ru.properties 2026-01-23 19:33:36.000000000 +0000 @@ -0,0 +1,21 @@ +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# Do not edit this file directly. +# To edit translations see: https://tomcat.apache.org/getinvolved.html#Translations + +http.method_get_not_supported=HTTP метод GET не поддерживается этим URL +http.method_post_not_supported=HTTP метод POST не поддерживается этим URL +http.method_put_not_supported=HTTP метод PUT не поддерживается этим URL diff -Nru tomcat10-10.1.40/java/jakarta/servlet/jsp/LocalStrings_ru.properties tomcat10-10.1.52/java/jakarta/servlet/jsp/LocalStrings_ru.properties --- tomcat10-10.1.40/java/jakarta/servlet/jsp/LocalStrings_ru.properties 1970-01-01 00:00:00.000000000 +0000 +++ tomcat10-10.1.52/java/jakarta/servlet/jsp/LocalStrings_ru.properties 2026-01-23 19:33:36.000000000 +0000 @@ -0,0 +1,19 @@ +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# Do not edit this file directly. +# To edit translations see: https://tomcat.apache.org/getinvolved.html#Translations + +el.unknown.identifier=Неизвестный идентификатор diff -Nru tomcat10-10.1.40/java/jakarta/servlet/jsp/tagext/BodyContent.java tomcat10-10.1.52/java/jakarta/servlet/jsp/tagext/BodyContent.java --- tomcat10-10.1.40/java/jakarta/servlet/jsp/tagext/BodyContent.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/jakarta/servlet/jsp/tagext/BodyContent.java 2026-01-23 19:33:36.000000000 +0000 @@ -71,7 +71,7 @@ public void clearBody() { try { this.clear(); - } catch (IOException ex) { + } catch (IOException ioe) { // TODO -- clean this one up. throw new Error("internal error!;"); } diff -Nru tomcat10-10.1.40/java/jakarta/websocket/ContainerProvider.java tomcat10-10.1.52/java/jakarta/websocket/ContainerProvider.java --- tomcat10-10.1.40/java/jakarta/websocket/ContainerProvider.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/jakarta/websocket/ContainerProvider.java 2026-01-23 19:33:36.000000000 +0000 @@ -47,7 +47,7 @@ Class clazz = (Class) Class.forName(DEFAULT_PROVIDER_CLASS_NAME); result = clazz.getConstructor().newInstance(); - } catch (ReflectiveOperationException | IllegalArgumentException | SecurityException e) { + } catch (ReflectiveOperationException | IllegalArgumentException | SecurityException ignore) { // No options left. Just return null. } } diff -Nru tomcat10-10.1.40/java/jakarta/websocket/server/ServerEndpointConfig.java tomcat10-10.1.52/java/jakarta/websocket/server/ServerEndpointConfig.java --- tomcat10-10.1.40/java/jakarta/websocket/server/ServerEndpointConfig.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/jakarta/websocket/server/ServerEndpointConfig.java 2026-01-23 19:33:36.000000000 +0000 @@ -182,7 +182,7 @@ @SuppressWarnings("unchecked") Class clazz = (Class) Class.forName(DEFAULT_IMPL_CLASSNAME); result = clazz.getConstructor().newInstance(); - } catch (ReflectiveOperationException | IllegalArgumentException | SecurityException e) { + } catch (ReflectiveOperationException | IllegalArgumentException | SecurityException ignore) { // No options left. Just return null. } } diff -Nru tomcat10-10.1.40/java/org/apache/catalina/Authenticator.java tomcat10-10.1.52/java/org/apache/catalina/Authenticator.java --- tomcat10-10.1.40/java/org/apache/catalina/Authenticator.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/Authenticator.java 2026-01-23 19:33:36.000000000 +0000 @@ -27,8 +27,6 @@ /** * An Authenticator is a component (usually a Valve or Container) that provides some sort of authentication * service. - * - * @author Craig R. McClanahan */ public interface Authenticator { diff -Nru tomcat10-10.1.40/java/org/apache/catalina/Cluster.java tomcat10-10.1.52/java/org/apache/catalina/Cluster.java --- tomcat10-10.1.40/java/org/apache/catalina/Cluster.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/Cluster.java 2026-01-23 19:33:36.000000000 +0000 @@ -21,9 +21,6 @@ * support different ways to communicate within the Cluster. A Cluster implementation is responsible for setting up a * way to communicate within the Cluster and also supply "ClientApplications" with ClusterSender used when * sending information in the Cluster and ClusterInfo used for receiving information in the Cluster. - * - * @author Bip Thelin - * @author Remy Maucherat */ public interface Cluster extends Contained { diff -Nru tomcat10-10.1.40/java/org/apache/catalina/Contained.java tomcat10-10.1.52/java/org/apache/catalina/Contained.java --- tomcat10-10.1.40/java/org/apache/catalina/Contained.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/Contained.java 2026-01-23 19:33:36.000000000 +0000 @@ -17,13 +17,8 @@ package org.apache.catalina; /** - *

* Decoupling interface which specifies that an implementing class is associated with at most one * Container instance. - *

- * - * @author Craig R. McClanahan - * @author Peter Donald */ public interface Contained { diff -Nru tomcat10-10.1.40/java/org/apache/catalina/Container.java tomcat10-10.1.52/java/org/apache/catalina/Container.java --- tomcat10-10.1.40/java/org/apache/catalina/Container.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/Container.java 2026-01-23 19:33:36.000000000 +0000 @@ -60,9 +60,6 @@ *
  • Resources - JNDI directory context enabling access to static resources, enabling custom linkages to * existing server components when Catalina is embedded in a larger server. * - * - * @author Craig R. McClanahan - * @author Remy Maucherat */ public interface Container extends Lifecycle { @@ -429,7 +426,7 @@ * * @param request Request (associated with the response) to log * @param response Response (associated with the request) to log - * @param time Time taken to process the request/response in milliseconds (use 0 if not known) + * @param time Time taken to process the request/response in nanoseconds (use 0 if not known) * @param useDefault Flag that indicates that the request/response should be logged in the engine's default access * log */ diff -Nru tomcat10-10.1.40/java/org/apache/catalina/ContainerEvent.java tomcat10-10.1.52/java/org/apache/catalina/ContainerEvent.java --- tomcat10-10.1.40/java/org/apache/catalina/ContainerEvent.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/ContainerEvent.java 2026-01-23 19:33:36.000000000 +0000 @@ -20,8 +20,6 @@ /** * General event for notifying listeners of significant changes on a Container. - * - * @author Craig R. McClanahan */ public final class ContainerEvent extends EventObject { diff -Nru tomcat10-10.1.40/java/org/apache/catalina/ContainerListener.java tomcat10-10.1.52/java/org/apache/catalina/ContainerListener.java --- tomcat10-10.1.40/java/org/apache/catalina/ContainerListener.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/ContainerListener.java 2026-01-23 19:33:36.000000000 +0000 @@ -20,8 +20,6 @@ /** * Interface defining a listener for significant Container generated events. Note that "container start" and "container * stop" events are normally LifecycleEvents, not ContainerEvents. - * - * @author Craig R. McClanahan */ public interface ContainerListener { diff -Nru tomcat10-10.1.40/java/org/apache/catalina/ContainerServlet.java tomcat10-10.1.52/java/org/apache/catalina/ContainerServlet.java --- tomcat10-10.1.40/java/org/apache/catalina/ContainerServlet.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/ContainerServlet.java 2026-01-23 19:33:36.000000000 +0000 @@ -20,8 +20,6 @@ * A ContainerServlet is a servlet that has access to Catalina internal functionality, and is loaded from the * Catalina class loader instead of the web application class loader. The property setter methods must be called by the * container whenever a new instance of this servlet is put into service. - * - * @author Craig R. McClanahan */ public interface ContainerServlet { diff -Nru tomcat10-10.1.40/java/org/apache/catalina/Context.java tomcat10-10.1.52/java/org/apache/catalina/Context.java --- tomcat10-10.1.40/java/org/apache/catalina/Context.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/Context.java 2026-01-23 19:33:36.000000000 +0000 @@ -61,8 +61,6 @@ * The child containers attached to a Context are generally implementations of Wrapper (representing individual servlet * definitions). *

    - * - * @author Craig R. McClanahan */ public interface Context extends Container, ContextBind { @@ -1100,7 +1098,7 @@ /** * @return the array of watched resources for this Context. If none are defined, a zero length array will be - * returned. + * returned. */ String[] findWatchedResources(); @@ -1116,7 +1114,7 @@ /** * @return the array of welcome files defined for this Context. If none are defined, a zero-length array is - * returned. + * returned. */ String[] findWelcomeFiles(); diff -Nru tomcat10-10.1.40/java/org/apache/catalina/Engine.java tomcat10-10.1.52/java/org/apache/catalina/Engine.java --- tomcat10-10.1.40/java/org/apache/catalina/Engine.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/Engine.java 2026-01-23 19:33:36.000000000 +0000 @@ -32,8 +32,6 @@ *

    * If used, an Engine is always the top level Container in a Catalina hierarchy. Therefore, the implementation's * setParent() method should throw IllegalArgumentException. - * - * @author Craig R. McClanahan */ public interface Engine extends Container { diff -Nru tomcat10-10.1.40/java/org/apache/catalina/Globals.java tomcat10-10.1.52/java/org/apache/catalina/Globals.java --- tomcat10-10.1.40/java/org/apache/catalina/Globals.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/Globals.java 2026-01-23 19:33:36.000000000 +0000 @@ -18,8 +18,6 @@ /** * Global constants that are applicable to multiple packages within Catalina. - * - * @author Craig R. McClanahan */ public final class Globals { diff -Nru tomcat10-10.1.40/java/org/apache/catalina/Group.java tomcat10-10.1.52/java/org/apache/catalina/Group.java --- tomcat10-10.1.40/java/org/apache/catalina/Group.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/Group.java 2026-01-23 19:33:36.000000000 +0000 @@ -25,8 +25,6 @@ * group inherits the {@link Role}s assigned to the group. *

    * - * @author Craig R. McClanahan - * * @since 4.1 */ public interface Group extends Principal { diff -Nru tomcat10-10.1.40/java/org/apache/catalina/Host.java tomcat10-10.1.52/java/org/apache/catalina/Host.java --- tomcat10-10.1.40/java/org/apache/catalina/Host.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/Host.java 2026-01-23 19:33:36.000000000 +0000 @@ -37,8 +37,6 @@ *

    * The child containers attached to a Host are generally implementations of Context (representing an individual servlet * context). - * - * @author Craig R. McClanahan */ public interface Host extends Container { diff -Nru tomcat10-10.1.40/java/org/apache/catalina/Lifecycle.java tomcat10-10.1.52/java/org/apache/catalina/Lifecycle.java --- tomcat10-10.1.40/java/org/apache/catalina/Lifecycle.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/Lifecycle.java 2026-01-23 19:33:36.000000000 +0000 @@ -75,8 +75,6 @@ * * The {@link LifecycleEvent}s fired during state changes are defined in the methods that trigger the changed. No * {@link LifecycleEvent}s are fired if the attempted transition is not valid. - * - * @author Craig R. McClanahan */ public interface Lifecycle { diff -Nru tomcat10-10.1.40/java/org/apache/catalina/LifecycleEvent.java tomcat10-10.1.52/java/org/apache/catalina/LifecycleEvent.java --- tomcat10-10.1.40/java/org/apache/catalina/LifecycleEvent.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/LifecycleEvent.java 2026-01-23 19:33:36.000000000 +0000 @@ -20,8 +20,6 @@ /** * General event for notifying listeners of significant changes on a component that implements the Lifecycle interface. - * - * @author Craig R. McClanahan */ public final class LifecycleEvent extends EventObject { diff -Nru tomcat10-10.1.40/java/org/apache/catalina/LifecycleException.java tomcat10-10.1.52/java/org/apache/catalina/LifecycleException.java --- tomcat10-10.1.40/java/org/apache/catalina/LifecycleException.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/LifecycleException.java 2026-01-23 19:33:36.000000000 +0000 @@ -20,8 +20,6 @@ /** * General purpose exception that is thrown to indicate a lifecycle related problem. Such exceptions should generally be * considered fatal to the operation of the application containing this component. - * - * @author Craig R. McClanahan */ public final class LifecycleException extends Exception { diff -Nru tomcat10-10.1.40/java/org/apache/catalina/LifecycleListener.java tomcat10-10.1.52/java/org/apache/catalina/LifecycleListener.java --- tomcat10-10.1.40/java/org/apache/catalina/LifecycleListener.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/LifecycleListener.java 2026-01-23 19:33:36.000000000 +0000 @@ -18,11 +18,9 @@ /** - * Interface defining a listener for significant events (including "component start" and "component stop") generated by a - * component that implements the Lifecycle interface. The listener will be fired after the associated state change has + * Interface defining a listener for significant events (including "component start" and "component stop") generated by + * a component that implements the Lifecycle interface. The listener will be fired after the associated state change has * taken place. - * - * @author Craig R. McClanahan */ public interface LifecycleListener { diff -Nru tomcat10-10.1.40/java/org/apache/catalina/Loader.java tomcat10-10.1.52/java/org/apache/catalina/Loader.java --- tomcat10-10.1.40/java/org/apache/catalina/Loader.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/Loader.java 2026-01-23 19:33:36.000000000 +0000 @@ -35,8 +35,6 @@ *

  • Based on a policy chosen by the implementation, must call the Context.reload() method on the owning * Context when a change to one or more of the class files loaded by this class loader is detected. * - * - * @author Craig R. McClanahan */ public interface Loader { diff -Nru tomcat10-10.1.40/java/org/apache/catalina/Manager.java tomcat10-10.1.52/java/org/apache/catalina/Manager.java --- tomcat10-10.1.40/java/org/apache/catalina/Manager.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/Manager.java 2026-01-23 19:33:36.000000000 +0000 @@ -31,8 +31,6 @@ *
  • Must allow a call to stop() to be followed by a call to start() on the same * Manager instance. * - * - * @author Craig R. McClanahan */ public interface Manager { diff -Nru tomcat10-10.1.40/java/org/apache/catalina/Pipeline.java tomcat10-10.1.52/java/org/apache/catalina/Pipeline.java --- tomcat10-10.1.40/java/org/apache/catalina/Pipeline.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/Pipeline.java 2026-01-23 19:33:36.000000000 +0000 @@ -19,21 +19,15 @@ import java.util.Set; /** - *

    * Interface describing a collection of Valves that should be executed in sequence when the invoke() method * is invoked. It is required that a Valve somewhere in the pipeline (usually the last one) must process the request and * create the corresponding response, rather than trying to pass the request on. - *

    *

    * There is generally a single Pipeline instance associated with each Container. The container's normal request * processing functionality is generally encapsulated in a container-specific Valve, which should always be executed at * the end of a pipeline. To facilitate this, the setBasic() method is provided to set the Valve instance * that will always be executed last. Other Valves will be executed in the order that they were added, before the basic * Valve is executed. - *

    - * - * @author Craig R. McClanahan - * @author Peter Donald */ public interface Pipeline extends Contained { @@ -81,7 +75,7 @@ /** * @return the array of Valves in the pipeline associated with this Container, including the basic Valve (if any). - * If there are no such Valves, a zero-length array is returned. + * If there are no such Valves, a zero-length array is returned. */ Valve[] getValves(); diff -Nru tomcat10-10.1.40/java/org/apache/catalina/Realm.java tomcat10-10.1.52/java/org/apache/catalina/Realm.java --- tomcat10-10.1.40/java/org/apache/catalina/Realm.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/Realm.java 2026-01-23 19:33:36.000000000 +0000 @@ -32,8 +32,6 @@ * A Realm is a read-only facade for an underlying security realm used to authenticate individual users, and * identify the security roles associated with those users. Realms can be attached at any Container level, but will * typically only be attached to a Context, or higher level, Container. - * - * @author Craig R. McClanahan */ public interface Realm extends Contained { diff -Nru tomcat10-10.1.40/java/org/apache/catalina/Role.java tomcat10-10.1.52/java/org/apache/catalina/Role.java --- tomcat10-10.1.40/java/org/apache/catalina/Role.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/Role.java 2026-01-23 19:33:36.000000000 +0000 @@ -26,8 +26,6 @@ * Principals. *

    * - * @author Craig R. McClanahan - * * @since 4.1 */ public interface Role extends Principal { diff -Nru tomcat10-10.1.40/java/org/apache/catalina/Server.java tomcat10-10.1.52/java/org/apache/catalina/Server.java --- tomcat10-10.1.40/java/org/apache/catalina/Server.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/Server.java 2026-01-23 19:33:36.000000000 +0000 @@ -34,8 +34,6 @@ * In between, the implementation must open a server socket on the port number specified by the port * property. When a connection is accepted, the first line is read and compared with the specified shutdown command. If * the command matches, shutdown of the server is initiated. - * - * @author Craig R. McClanahan */ public interface Server extends Lifecycle { diff -Nru tomcat10-10.1.40/java/org/apache/catalina/Service.java tomcat10-10.1.52/java/org/apache/catalina/Service.java --- tomcat10-10.1.40/java/org/apache/catalina/Service.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/Service.java 2026-01-23 19:33:36.000000000 +0000 @@ -26,8 +26,6 @@ *

    * A given JVM can contain any number of Service instances; however, they are completely independent of each other and * share only the basic JVM facilities and classes on the system class path. - * - * @author Craig R. McClanahan */ public interface Service extends Lifecycle { diff -Nru tomcat10-10.1.40/java/org/apache/catalina/Session.java tomcat10-10.1.52/java/org/apache/catalina/Session.java --- tomcat10-10.1.40/java/org/apache/catalina/Session.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/Session.java 2026-01-23 19:33:36.000000000 +0000 @@ -26,8 +26,6 @@ /** * A Session is the Catalina-internal facade for an HttpSession that is used to maintain state * information between requests for a particular user of a web application. - * - * @author Craig R. McClanahan */ public interface Session { @@ -58,6 +56,10 @@ */ String SESSION_PASSIVATED_EVENT = "passivateSession"; + /** + * The SessionEvent event type when a session changes its sessionId. + */ + String SESSION_CHANGED_ID_EVENT = "changeSessionId"; // ------------------------------------------------------------- Properties diff -Nru tomcat10-10.1.40/java/org/apache/catalina/SessionEvent.java tomcat10-10.1.52/java/org/apache/catalina/SessionEvent.java --- tomcat10-10.1.40/java/org/apache/catalina/SessionEvent.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/SessionEvent.java 2026-01-23 19:33:36.000000000 +0000 @@ -22,8 +22,6 @@ /** * General event for notifying listeners of significant changes on a Session. - * - * @author Craig R. McClanahan */ public final class SessionEvent extends EventObject { diff -Nru tomcat10-10.1.40/java/org/apache/catalina/SessionListener.java tomcat10-10.1.52/java/org/apache/catalina/SessionListener.java --- tomcat10-10.1.40/java/org/apache/catalina/SessionListener.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/SessionListener.java 2026-01-23 19:33:36.000000000 +0000 @@ -21,8 +21,6 @@ /** * Interface defining a listener for significant Session generated events. - * - * @author Craig R. McClanahan */ public interface SessionListener extends EventListener { diff -Nru tomcat10-10.1.40/java/org/apache/catalina/Store.java tomcat10-10.1.52/java/org/apache/catalina/Store.java --- tomcat10-10.1.40/java/org/apache/catalina/Store.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/Store.java 2026-01-23 19:33:36.000000000 +0000 @@ -25,13 +25,9 @@ * A Store is the abstraction of a Catalina component that provides persistent storage and loading of Sessions * and their associated user data. Implementations are free to save and load the Sessions to any media they wish, but it * is assumed that saved Sessions are persistent across server or context restarts. - * - * @author Craig R. McClanahan */ public interface Store { - // ------------------------------------------------------------- Properties - /** * @return the Manager instance associated with this Store. */ @@ -54,9 +50,6 @@ int getSize() throws IOException; - // --------------------------------------------------------- Public Methods - - /** * Add a property change listener to this component. * @@ -77,6 +70,11 @@ /** * Load and return the Session associated with the specified session identifier from this Store, without removing * it. If there is no such stored Session, return null. + *

    + * Implementations should expect, and correctly handle, concurrent calls to any method but in particular calls to + * {@code #load(String)}, {@code #save(Session)} and {@code #remove(String)} for the same session. + *

    + * The session ID is user provided so stores must treat it as untrusted data. * * @param id Session identifier of the session to load * @@ -91,6 +89,11 @@ /** * Remove the Session with the specified session identifier from this Store, if present. If no such Session is * present, this method takes no action. + *

    + * Implementations should expect, and correctly handle, concurrent calls to any method but in particular calls to + * {@code #load(String)}, {@code #save(Session)} and {@code #remove(String)} for the same session. + *

    + * The session ID is user provided so stores must treat it as untrusted data. * * @param id Session identifier of the Session to be removed * @@ -118,12 +121,13 @@ /** * Save the specified Session into this Store. Any previously saved information for the associated session * identifier is replaced. + *

    + * Implementations should expect, and correctly handle, concurrent calls to any method but in particular calls to + * {@code #load(String)}, {@code #save(Session)} and {@code #remove(String)} for the same session. * * @param session Session to be saved * * @exception IOException if an input/output error occurs */ void save(Session session) throws IOException; - - } diff -Nru tomcat10-10.1.40/java/org/apache/catalina/User.java tomcat10-10.1.52/java/org/apache/catalina/User.java --- tomcat10-10.1.40/java/org/apache/catalina/User.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/User.java 2026-01-23 19:33:36.000000000 +0000 @@ -26,8 +26,6 @@ * {@link Group}s through which they inherit additional security roles, and is optionally assigned a set of specific * {@link Role}s. * - * @author Craig R. McClanahan - * * @since 4.1 */ public interface User extends Principal { diff -Nru tomcat10-10.1.40/java/org/apache/catalina/UserDatabase.java tomcat10-10.1.52/java/org/apache/catalina/UserDatabase.java --- tomcat10-10.1.40/java/org/apache/catalina/UserDatabase.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/UserDatabase.java 2026-01-23 19:33:36.000000000 +0000 @@ -23,8 +23,6 @@ * along with definitions of corresponding {@link Role}s, and referenced by a {@link Realm} for authentication and * access control. * - * @author Craig R. McClanahan - * * @since 4.1 */ public interface UserDatabase { diff -Nru tomcat10-10.1.40/java/org/apache/catalina/Valve.java tomcat10-10.1.52/java/org/apache/catalina/Valve.java --- tomcat10-10.1.40/java/org/apache/catalina/Valve.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/Valve.java 2026-01-23 19:33:36.000000000 +0000 @@ -24,17 +24,12 @@ import org.apache.catalina.connector.Response; /** - *

    * A Valve is a request processing component associated with a particular Container. A series of Valves are * generally associated with each other into a Pipeline. The detailed contract for a Valve is included in the * description of the invoke() method below. - *

    + *

    * HISTORICAL NOTE: The "Valve" name was assigned to this concept because a valve is what you use in a real world * pipeline to control and/or modify flows through it. - * - * @author Craig R. McClanahan - * @author Gunnar Rjnning - * @author Peter Donald */ public interface Valve { diff -Nru tomcat10-10.1.40/java/org/apache/catalina/WebResourceRoot.java tomcat10-10.1.52/java/org/apache/catalina/WebResourceRoot.java --- tomcat10-10.1.40/java/org/apache/catalina/WebResourceRoot.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/WebResourceRoot.java 2026-01-23 19:33:36.000000000 +0000 @@ -21,6 +21,8 @@ import java.util.List; import java.util.Set; +import org.apache.catalina.util.ResourceSet; + /** * Represents the complete set of resources for a web application. The resources for a web application consist of * multiple ResourceSets and when looking for a Resource, the ResourceSets are processed in the following order: @@ -95,8 +97,8 @@ * calls to this method until the web application is reloaded. No guarantee is made as to what the search order for * JAR files may be. * - * @param path The path of the class loader resource of interest relative to the root of class loader resources - * for this web application. + * @param path The path of the class loader resource of interest relative to the root of class loader resources for + * this web application. * * @return The object that represents the class loader resource at the given path */ @@ -246,14 +248,16 @@ void setContext(Context context); /** - * Configure if this resources allow the use of symbolic links. + * Configure if this web application allows the use of symbolic links by default. Individual {@link ResourceSet}s + * may override this setting. * * @param allowLinking true if symbolic links are allowed. */ void setAllowLinking(boolean allowLinking); /** - * Determine if this resources allow the use of symbolic links. + * Determine if this web application allows the use of symbolic links by default. Individual {@link ResourceSet}s + * may override this setting. * * @return true if symbolic links are allowed */ diff -Nru tomcat10-10.1.40/java/org/apache/catalina/WebResourceSet.java tomcat10-10.1.52/java/org/apache/catalina/WebResourceSet.java --- tomcat10-10.1.40/java/org/apache/catalina/WebResourceSet.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/WebResourceSet.java 2026-01-23 19:33:36.000000000 +0000 @@ -135,4 +135,19 @@ * resources. */ void gc(); + + /** + * Configure if this {@code ResourceSet} allows the use of symbolic links. + * + * @param allowLinking true if symbolic links are allowed. + */ + void setAllowLinking(boolean allowLinking); + + /** + * Determine if this {@code ResourceSet} allows the use of symbolic links. If {@link #setAllowLinking(boolean)} has + * not been called for this instance, the value of {@link WebResourceRoot#getAllowLinking()} is returned. + * + * @return true if symbolic links are allowed + */ + boolean getAllowLinking(); } diff -Nru tomcat10-10.1.40/java/org/apache/catalina/Wrapper.java tomcat10-10.1.52/java/org/apache/catalina/Wrapper.java --- tomcat10-10.1.40/java/org/apache/catalina/Wrapper.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/Wrapper.java 2026-01-23 19:33:36.000000000 +0000 @@ -36,8 +36,6 @@ *

    * Child Containers are not allowed on Wrapper implementations, so the addChild() method should throw an * IllegalArgumentException. - * - * @author Craig R. McClanahan */ public interface Wrapper extends Container { diff -Nru tomcat10-10.1.40/java/org/apache/catalina/ant/AbstractCatalinaTask.java tomcat10-10.1.52/java/org/apache/catalina/ant/AbstractCatalinaTask.java --- tomcat10-10.1.40/java/org/apache/catalina/ant/AbstractCatalinaTask.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/ant/AbstractCatalinaTask.java 2026-01-23 19:33:36.000000000 +0000 @@ -28,6 +28,7 @@ import java.net.URLConnection; import org.apache.catalina.util.IOTools; +import org.apache.tomcat.util.http.Method; import org.apache.tools.ant.BuildException; import org.apache.tools.ant.Project; @@ -35,8 +36,6 @@ * Abstract base class for Ant tasks that interact with the Manager web application for dynamically deploying * and undeploying applications. These tasks require Ant 1.4 or later. * - * @author Craig R. McClanahan - * * @since 4.1 */ public abstract class AbstractCatalinaTask extends BaseRedirectorHelperTask { @@ -187,7 +186,7 @@ preAuthenticate(); hconn.setDoOutput(true); - hconn.setRequestMethod("PUT"); + hconn.setRequestMethod(Method.PUT); if (contentType != null) { hconn.setRequestProperty("Content-Type", contentType); } @@ -198,7 +197,7 @@ } } else { hconn.setDoOutput(false); - hconn.setRequestMethod("GET"); + hconn.setRequestMethod(Method.GET); } hconn.setRequestProperty("User-Agent", "Catalina-Ant-Task/1.0"); @@ -297,7 +296,7 @@ hconn.setDoInput(true); hconn.setUseCaches(false); hconn.setDoOutput(false); - hconn.setRequestMethod("OPTIONS"); + hconn.setRequestMethod(Method.OPTIONS); hconn.setRequestProperty("User-Agent", "Catalina-Ant-Task/1.0"); // Establish the connection with the server diff -Nru tomcat10-10.1.40/java/org/apache/catalina/ant/BaseRedirectorHelperTask.java tomcat10-10.1.52/java/org/apache/catalina/ant/BaseRedirectorHelperTask.java --- tomcat10-10.1.40/java/org/apache/catalina/ant/BaseRedirectorHelperTask.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/ant/BaseRedirectorHelperTask.java 2026-01-23 19:33:36.000000000 +0000 @@ -30,14 +30,12 @@ /** * Abstract base class to add output redirection support for Catalina Ant tasks. These tasks require Ant 1.5 or later. *
    - * WARNING: due to dependency chain, Ant could call a Task more than once and this can affect the output - * redirection when configured. If you are collecting the output in a property, it will collect the output of only the - * first run, since Ant properties are immutable and once created they cannot be changed.
    + * WARNING: due to dependency chain, Ant could call a Task more than once and this can affect the + * output redirection when configured. If you are collecting the output in a property, it will collect the output of + * only the first run, since Ant properties are immutable and once created they cannot be changed.
    * If you are collecting output in a file the file will be overwritten with the output of the last run, unless you set * append="true", in which case each run will append it's output to the file. * - * @author Gabriele Garuglieri - * * @since 5.5 */ public abstract class BaseRedirectorHelperTask extends Task { @@ -218,8 +216,8 @@ redirectOutput = true; } /* - * Due to dependency chain, Ant could call the Task more than once, this is to prevent that we attempt to configure - * uselessly more than once the Redirector. + * Due to dependency chain, Ant could call the Task more than once, this is to prevent that we attempt to + * configure uselessly more than once the Redirector. */ redirectorConfigured = true; } @@ -256,8 +254,8 @@ log("Error closing redirector: " + ioe.getMessage(), Project.MSG_ERR); } /* - * Due to dependency chain, Ant could call the Task more than once, this is to prevent that we attempt to reuse the - * previously closed Streams. + * Due to dependency chain, Ant could call the Task more than once, this is to prevent that we attempt to reuse + * the previously closed Streams. */ redirectOutStream = null; redirectOutPrintStream = null; diff -Nru tomcat10-10.1.40/java/org/apache/catalina/ant/DeployTask.java tomcat10-10.1.52/java/org/apache/catalina/ant/DeployTask.java --- tomcat10-10.1.40/java/org/apache/catalina/ant/DeployTask.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/ant/DeployTask.java 2026-01-23 19:33:36.000000000 +0000 @@ -32,8 +32,6 @@ /** * Ant task that implements the /deploy command, supported by the Tomcat manager application. * - * @author Craig R. McClanahan - * * @since 4.1 */ public class DeployTask extends AbstractCatalinaCommandTask { @@ -145,15 +143,15 @@ FileChannel fsChannel = fsInput.getChannel(); contentLength = fsChannel.size(); stream = new BufferedInputStream(fsInput, 1024); - } catch (IOException e) { + } catch (IOException ioe) { if (fsInput != null) { try { fsInput.close(); - } catch (IOException ioe) { + } catch (IOException ignore) { // Ignore } } - throw new BuildException(e); + throw new BuildException(ioe); } } contentType = "application/octet-stream"; diff -Nru tomcat10-10.1.40/java/org/apache/catalina/ant/JKStatusUpdateTask.java tomcat10-10.1.52/java/org/apache/catalina/ant/JKStatusUpdateTask.java --- tomcat10-10.1.40/java/org/apache/catalina/ant/JKStatusUpdateTask.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/ant/JKStatusUpdateTask.java 2026-01-23 19:33:36.000000000 +0000 @@ -24,8 +24,6 @@ /** * Ant task that implements the /status command, supported by the mod_jk status (1.2.9) application. * - * @author Peter Rossbach - * * @since 5.5.9 */ public class JKStatusUpdateTask extends AbstractCatalinaTask { diff -Nru tomcat10-10.1.40/java/org/apache/catalina/ant/JMXGetTask.java tomcat10-10.1.52/java/org/apache/catalina/ant/JMXGetTask.java --- tomcat10-10.1.40/java/org/apache/catalina/ant/JMXGetTask.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/ant/JMXGetTask.java 2026-01-23 19:33:36.000000000 +0000 @@ -26,8 +26,6 @@ /** * Ant task that implements the JMX Get command (/jmxproxy/?get) supported by the Tomcat manager * application. - * - * @author Peter Rossbach */ public class JMXGetTask extends AbstractCatalinaTask { diff -Nru tomcat10-10.1.40/java/org/apache/catalina/ant/JMXQueryTask.java tomcat10-10.1.52/java/org/apache/catalina/ant/JMXQueryTask.java --- tomcat10-10.1.40/java/org/apache/catalina/ant/JMXQueryTask.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/ant/JMXQueryTask.java 2026-01-23 19:33:36.000000000 +0000 @@ -26,8 +26,6 @@ /** * Ant task that implements the JMX Query command (/jmxproxy/?qry) supported by the Tomcat manager * application. - * - * @author Vivek Chopra */ public class JMXQueryTask extends AbstractCatalinaTask { diff -Nru tomcat10-10.1.40/java/org/apache/catalina/ant/JMXSetTask.java tomcat10-10.1.52/java/org/apache/catalina/ant/JMXSetTask.java --- tomcat10-10.1.40/java/org/apache/catalina/ant/JMXSetTask.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/ant/JMXSetTask.java 2026-01-23 19:33:36.000000000 +0000 @@ -26,8 +26,6 @@ /** * Ant task that implements the JMX Set command (/jmxproxy/?set) supported by the Tomcat manager * application. - * - * @author Vivek Chopra */ public class JMXSetTask extends AbstractCatalinaTask { diff -Nru tomcat10-10.1.40/java/org/apache/catalina/ant/ListTask.java tomcat10-10.1.52/java/org/apache/catalina/ant/ListTask.java --- tomcat10-10.1.40/java/org/apache/catalina/ant/ListTask.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/ant/ListTask.java 2026-01-23 19:33:36.000000000 +0000 @@ -23,8 +23,6 @@ /** * Ant task that implements the /list command, supported by the Tomcat manager application. * - * @author Craig R. McClanahan - * * @since 4.1 */ public class ListTask extends AbstractCatalinaTask { diff -Nru tomcat10-10.1.40/java/org/apache/catalina/ant/ReloadTask.java tomcat10-10.1.52/java/org/apache/catalina/ant/ReloadTask.java --- tomcat10-10.1.40/java/org/apache/catalina/ant/ReloadTask.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/ant/ReloadTask.java 2026-01-23 19:33:36.000000000 +0000 @@ -23,8 +23,6 @@ /** * Ant task that implements the /reload command, supported by the Tomcat manager application. * - * @author Craig R. McClanahan - * * @since 4.1 */ public class ReloadTask extends AbstractCatalinaCommandTask { diff -Nru tomcat10-10.1.40/java/org/apache/catalina/ant/ResourcesTask.java tomcat10-10.1.52/java/org/apache/catalina/ant/ResourcesTask.java --- tomcat10-10.1.40/java/org/apache/catalina/ant/ResourcesTask.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/ant/ResourcesTask.java 2026-01-23 19:33:36.000000000 +0000 @@ -26,8 +26,6 @@ /** * Ant task that implements the /resources command, supported by the Tomcat manager application. * - * @author Craig R. McClanahan - * * @since 4.1 */ public class ResourcesTask extends AbstractCatalinaTask { diff -Nru tomcat10-10.1.40/java/org/apache/catalina/ant/ServerinfoTask.java tomcat10-10.1.52/java/org/apache/catalina/ant/ServerinfoTask.java --- tomcat10-10.1.40/java/org/apache/catalina/ant/ServerinfoTask.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/ant/ServerinfoTask.java 2026-01-23 19:33:36.000000000 +0000 @@ -16,19 +16,13 @@ */ package org.apache.catalina.ant; - import org.apache.tools.ant.BuildException; - /** * Ant task that implements the /serverinfo command supported by the Tomcat manager application. - * - * @author Vivek Chopra */ public class ServerinfoTask extends AbstractCatalinaTask { - // Public Methods - /** * Execute the requested operation. * @@ -36,9 +30,7 @@ */ @Override public void execute() throws BuildException { - super.execute(); execute("/serverinfo"); - } } diff -Nru tomcat10-10.1.40/java/org/apache/catalina/ant/SessionsTask.java tomcat10-10.1.52/java/org/apache/catalina/ant/SessionsTask.java --- tomcat10-10.1.40/java/org/apache/catalina/ant/SessionsTask.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/ant/SessionsTask.java 2026-01-23 19:33:36.000000000 +0000 @@ -16,18 +16,13 @@ */ package org.apache.catalina.ant; - import org.apache.tools.ant.BuildException; - /** * Ant task that implements the /sessions command supported by the Tomcat manager application. - * - * @author Vivek Chopra */ public class SessionsTask extends AbstractCatalinaCommandTask { - protected String idle = null; public String getIdle() { diff -Nru tomcat10-10.1.40/java/org/apache/catalina/ant/StartTask.java tomcat10-10.1.52/java/org/apache/catalina/ant/StartTask.java --- tomcat10-10.1.40/java/org/apache/catalina/ant/StartTask.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/ant/StartTask.java 2026-01-23 19:33:36.000000000 +0000 @@ -23,8 +23,6 @@ /** * Ant task that implements the /start command, supported by the Tomcat manager application. * - * @author Craig R. McClanahan - * * @since 4.1 */ public class StartTask extends AbstractCatalinaCommandTask { diff -Nru tomcat10-10.1.40/java/org/apache/catalina/ant/StopTask.java tomcat10-10.1.52/java/org/apache/catalina/ant/StopTask.java --- tomcat10-10.1.40/java/org/apache/catalina/ant/StopTask.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/ant/StopTask.java 2026-01-23 19:33:36.000000000 +0000 @@ -23,8 +23,6 @@ /** * Ant task that implements the /stop command, supported by the Tomcat manager application. * - * @author Craig R. McClanahan - * * @since 4.1 */ public class StopTask extends AbstractCatalinaCommandTask { diff -Nru tomcat10-10.1.40/java/org/apache/catalina/ant/UndeployTask.java tomcat10-10.1.52/java/org/apache/catalina/ant/UndeployTask.java --- tomcat10-10.1.40/java/org/apache/catalina/ant/UndeployTask.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/ant/UndeployTask.java 2026-01-23 19:33:36.000000000 +0000 @@ -23,8 +23,6 @@ /** * Ant task that implements the /undeploy command, supported by the Tomcat manager application. * - * @author Craig R. McClanahan - * * @since 4.1 */ public class UndeployTask extends AbstractCatalinaCommandTask { diff -Nru tomcat10-10.1.40/java/org/apache/catalina/ant/ValidatorTask.java tomcat10-10.1.52/java/org/apache/catalina/ant/ValidatorTask.java --- tomcat10-10.1.40/java/org/apache/catalina/ant/ValidatorTask.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/ant/ValidatorTask.java 2026-01-23 19:33:36.000000000 +0000 @@ -32,8 +32,6 @@ /** * Task for validating a web application deployment descriptor, using XML schema validation. * - * @author Remy Maucherat - * * @since 5.0 */ public class ValidatorTask extends BaseRedirectorHelperTask { diff -Nru tomcat10-10.1.40/java/org/apache/catalina/ant/jmx/JMXAccessorCondition.java tomcat10-10.1.52/java/org/apache/catalina/ant/jmx/JMXAccessorCondition.java --- tomcat10-10.1.40/java/org/apache/catalina/ant/jmx/JMXAccessorCondition.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/ant/jmx/JMXAccessorCondition.java 2026-01-23 19:33:36.000000000 +0000 @@ -77,8 +77,6 @@ * NOTE: For numeric expressions the type must be set and use xml entities as operations.
    * As type we currently support long and double. * - * @author Peter Rossbach - * * @since 5.5.10 */ public class JMXAccessorCondition extends JMXAccessorConditionBase { diff -Nru tomcat10-10.1.40/java/org/apache/catalina/ant/jmx/JMXAccessorCreateTask.java tomcat10-10.1.52/java/org/apache/catalina/ant/jmx/JMXAccessorCreateTask.java --- tomcat10-10.1.40/java/org/apache/catalina/ant/jmx/JMXAccessorCreateTask.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/ant/jmx/JMXAccessorCreateTask.java 2026-01-23 19:33:36.000000000 +0000 @@ -46,16 +46,14 @@ * </jmxCreate/> * *

    - * WARNINGNot all Tomcat MBeans can create remotely and auto register by its parents! Please, use the MBeanFactory - * operation to generate valves and realms. + * WARNINGNot all Tomcat MBeans can create remotely and auto register by its parents! Please, use the + * MBeanFactory operation to generate valves and realms. *

    *

    * First call to a remote MBean server save the JMXConnection a reference jmx.server *

    * These tasks require Ant 1.6 or later interface. * - * @author Peter Rossbach - * * @since 5.5.12 */ public class JMXAccessorCreateTask extends JMXAccessorTask { diff -Nru tomcat10-10.1.40/java/org/apache/catalina/ant/jmx/JMXAccessorEqualsCondition.java tomcat10-10.1.52/java/org/apache/catalina/ant/jmx/JMXAccessorEqualsCondition.java --- tomcat10-10.1.40/java/org/apache/catalina/ant/jmx/JMXAccessorEqualsCondition.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/ant/jmx/JMXAccessorEqualsCondition.java 2026-01-23 19:33:36.000000000 +0000 @@ -54,8 +54,6 @@ * </target> * * - * @author Peter Rossbach - * * @since 5.5.10 */ public class JMXAccessorEqualsCondition extends JMXAccessorConditionBase { diff -Nru tomcat10-10.1.40/java/org/apache/catalina/ant/jmx/JMXAccessorGetTask.java tomcat10-10.1.52/java/org/apache/catalina/ant/jmx/JMXAccessorGetTask.java --- tomcat10-10.1.40/java/org/apache/catalina/ant/jmx/JMXAccessorGetTask.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/ant/jmx/JMXAccessorGetTask.java 2026-01-23 19:33:36.000000000 +0000 @@ -49,8 +49,6 @@ *

    * These tasks require Ant 1.6 or later interface. * - * @author Peter Rossbach - * * @since 5.5.10 */ public class JMXAccessorGetTask extends JMXAccessorTask { diff -Nru tomcat10-10.1.40/java/org/apache/catalina/ant/jmx/JMXAccessorInvokeTask.java tomcat10-10.1.52/java/org/apache/catalina/ant/jmx/JMXAccessorInvokeTask.java --- tomcat10-10.1.40/java/org/apache/catalina/ant/jmx/JMXAccessorInvokeTask.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/ant/jmx/JMXAccessorInvokeTask.java 2026-01-23 19:33:36.000000000 +0000 @@ -54,6 +54,7 @@ * *
  • *
  • Create new AccessLogger at localhost + * *
      *   <jmx:invoke
      *           name="Catalina:type=MBeanFactory"
    @@ -61,23 +62,26 @@
      *           resultproperty="accessLoggerObjectName">
      *         <arg value="Catalina:type=Host,host=localhost"/>
      *   </jmx:invoke>
    - * 
  • + * + * + * *
  • Remove existing AccessLogger at localhost + * *
      *   <jmx:invoke
      *           name="Catalina:type=MBeanFactory"
      *           operation="removeValve">
      *         <arg value="Catalina:type=Valve,name=AccessLogValve,host=localhost"/>
      *   </jmx:invoke>
    - * 
  • + * + * + * * *

    * First call to a remote MBeanserver save the JMXConnection a referenz jmx.server *

    * These tasks require Ant 1.6 or later interface. * - * @author Peter Rossbach - * * @since 5.5.10 */ public class JMXAccessorInvokeTask extends JMXAccessorTask { diff -Nru tomcat10-10.1.40/java/org/apache/catalina/ant/jmx/JMXAccessorQueryTask.java tomcat10-10.1.52/java/org/apache/catalina/ant/jmx/JMXAccessorQueryTask.java --- tomcat10-10.1.40/java/org/apache/catalina/ant/jmx/JMXAccessorQueryTask.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/ant/jmx/JMXAccessorQueryTask.java 2026-01-23 19:33:36.000000000 +0000 @@ -51,8 +51,6 @@ * The property manager.length show the size of the result and with manager.[0..length].name the resulted ObjectNames * are saved. These tasks require Ant 1.6 or later interface. * - * @author Peter Rossbach - * * @since 5.5.10 */ public class JMXAccessorQueryTask extends JMXAccessorTask { diff -Nru tomcat10-10.1.40/java/org/apache/catalina/ant/jmx/JMXAccessorSetTask.java tomcat10-10.1.52/java/org/apache/catalina/ant/jmx/JMXAccessorSetTask.java --- tomcat10-10.1.40/java/org/apache/catalina/ant/jmx/JMXAccessorSetTask.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/ant/jmx/JMXAccessorSetTask.java 2026-01-23 19:33:36.000000000 +0000 @@ -55,8 +55,6 @@ *

    * These tasks require Ant 1.6 or later interface. * - * @author Peter Rossbach - * * @since 5.5.10 */ public class JMXAccessorSetTask extends JMXAccessorTask { diff -Nru tomcat10-10.1.40/java/org/apache/catalina/ant/jmx/JMXAccessorTask.java tomcat10-10.1.52/java/org/apache/catalina/ant/jmx/JMXAccessorTask.java --- tomcat10-10.1.40/java/org/apache/catalina/ant/jmx/JMXAccessorTask.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/ant/jmx/JMXAccessorTask.java 2026-01-23 19:33:36.000000000 +0000 @@ -77,8 +77,6 @@ * execute when property exist and with unless when property not exists.
    * NOTE : These tasks require Ant 1.6 or later interface. * - * @author Peter Rossbach - * * @since 5.5.10 */ public class JMXAccessorTask extends BaseRedirectorHelperTask { diff -Nru tomcat10-10.1.40/java/org/apache/catalina/ant/jmx/JMXAccessorUnregisterTask.java tomcat10-10.1.52/java/org/apache/catalina/ant/jmx/JMXAccessorUnregisterTask.java --- tomcat10-10.1.40/java/org/apache/catalina/ant/jmx/JMXAccessorUnregisterTask.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/ant/jmx/JMXAccessorUnregisterTask.java 2026-01-23 19:33:36.000000000 +0000 @@ -45,8 +45,6 @@ *

    * These tasks require Ant 1.6 or later interface. * - * @author Peter Rossbach - * * @since 5.5.12 */ public class JMXAccessorUnregisterTask extends JMXAccessorTask { diff -Nru tomcat10-10.1.40/java/org/apache/catalina/authenticator/AuthenticatorBase.java tomcat10-10.1.52/java/org/apache/catalina/authenticator/AuthenticatorBase.java --- tomcat10-10.1.40/java/org/apache/catalina/authenticator/AuthenticatorBase.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/authenticator/AuthenticatorBase.java 2026-01-23 19:33:36.000000000 +0000 @@ -70,6 +70,7 @@ import org.apache.tomcat.util.descriptor.web.LoginConfig; import org.apache.tomcat.util.descriptor.web.SecurityConstraint; import org.apache.tomcat.util.http.FastHttpDateFormat; +import org.apache.tomcat.util.http.Method; import org.apache.tomcat.util.http.RequestUtil; import org.apache.tomcat.util.res.StringManager; @@ -85,8 +86,6 @@ *

    * USAGE CONSTRAINT: This Valve is only useful when processing HTTP requests. Requests of any other type will * simply be passed through. - * - * @author Craig R. McClanahan */ public abstract class AuthenticatorBase extends ValveBase implements Authenticator, RegistrationListener { @@ -211,7 +210,6 @@ * {@code remote-user} and {@code auth-type} to a reverse proxy. This is useful, e.g., for access log consistency or * other decisions to make. */ - protected boolean sendAuthInfoResponseHeaders = false; protected SessionIdGeneratorBase sessionIdGenerator = null; @@ -221,6 +219,8 @@ */ protected SingleSignOn sso = null; + private SsoReauthenticationMode ssoReauthenticationMode = SsoReauthenticationMode.DEFAULT; + private AllowCorsPreflight allowCorsPreflight = AllowCorsPreflight.NEVER; private volatile String jaspicAppContextID = null; @@ -230,6 +230,15 @@ // ------------------------------------------------------------- Properties + public String getSsoReauthenticationMode() { + return ssoReauthenticationMode.name().toLowerCase(Locale.ENGLISH); + } + + public void setSsoReauthenticationMode(String ssoReauthenticationMode) { + this.ssoReauthenticationMode = + SsoReauthenticationMode.valueOf(ssoReauthenticationMode.trim().toUpperCase(Locale.ENGLISH)); + } + public String getAllowCorsPreflight() { return allowCorsPreflight.name().toLowerCase(Locale.ENGLISH); } @@ -486,7 +495,7 @@ // Make sure that constrained resources are not cached by web proxies // or browsers as caching can provide a security hole - if (constraints != null && disableProxyCaching && !"POST".equalsIgnoreCase(request.getMethod())) { + if (constraints != null && disableProxyCaching && !Method.POST.equals(request.getMethod())) { if (securePagesWithPragma) { // Note: These can cause problems with downloading files with IE response.setHeader("Pragma", "No-cache"); @@ -609,7 +618,7 @@ if (allowCorsPreflight != AllowCorsPreflight.NEVER) { // First check to see if this is a CORS Preflight request // This is a subset of the tests in CorsFilter.checkRequestType - if ("OPTIONS".equals(request.getMethod())) { + if (Method.OPTIONS.equals(request.getMethod())) { String originHeader = request.getHeader(CorsFilter.REQUEST_HEADER_ORIGIN); if (originHeader != null && !originHeader.isEmpty() && RequestUtil.isValidOrigin(originHeader) && !RequestUtil.isSameOrigin(request, originHeader)) { @@ -726,12 +735,13 @@ Class clazz = null; try { clazz = Class.forName(jaspicCallbackHandlerClass, true, Thread.currentThread().getContextClassLoader()); - } catch (ClassNotFoundException e) { - // Proceed with the retry below + } catch (ClassNotFoundException ignore) { + // Not found in the context class loader (web application class loader). Re-try below. } try { if (clazz == null) { + // Look in the same class loader that loaded this class - usually Tomcat's common loader. clazz = Class.forName(jaspicCallbackHandlerClass); } callbackHandler = (CallbackHandler) clazz.getConstructor().newInstance(); @@ -878,40 +888,87 @@ * Check to see if the user has already been authenticated earlier in the processing chain or if there is enough * information available to authenticate the user without requiring further user interaction. * - * @param request The current request - * @param response The current response - * @param useSSO Should information available from SSO be used to attempt to authenticate the current user? + * @param request The current request + * @param response The current response + * @param useSsoCachedUserAndPassword Should the user and password available from SSO be used to attempt to + * authenticate the current user? * * @return true if the user was authenticated via the cache, otherwise false */ - protected boolean checkForCachedAuthentication(Request request, HttpServletResponse response, boolean useSSO) { + protected boolean checkForCachedAuthentication(Request request, HttpServletResponse response, + boolean useSsoCachedUserAndPassword) { + + /* + * There are two methods for authentication caching implemented by the SSO Valve. The first caches the + * authenticated Principal returned by the Realm. The second caches the user name and password passed to the + * Realm that were used for authentication. + * + * If cached authentication is not available or fails for any reason, the Authenticator will attempt the normal + * authentication process for the Authenticator. + * + * Which cached authentication methods are used depends on the configuration of the SSO Valve and/or the + * Authenticator. + * + * If the SSO Valve is configured to require re-authentication, any cached Principal will not be used unless the + * Authenticator is explicitly configured (via ssoReauthenticationMode) to use it. + * + * If the SSO Valve is configured to require re-authentication, whether the cached user name and password can be + * used will be determined by the calling Authenticator type unless the Authenticator's ssoReauthenticationMode + * is explicitly configured. + */ + + // Determine which - if any - checks for cached authentication will be made. + boolean checkPrincipal = false; + boolean checkPassword = false; - // Has the user already been authenticated? - Principal principal = request.getUserPrincipal(); + // Will be null if SSO is not configured or there is no current SSO session String ssoId = (String) request.getNote(Constants.REQ_SSOID_NOTE); - if (principal != null) { - if (log.isDebugEnabled()) { - log.debug(sm.getString("authenticator.check.found", principal.getName())); - } - // Associate the session with any existing SSO session. Even if - // useSSO is false, this will ensure coordinated session - // invalidation at log out. + + if (sso == null) { + // There is no SSO - check in case some other component has set the Principal + checkPrincipal = true; + } else if (ssoReauthenticationMode == SsoReauthenticationMode.DEFAULT && !sso.getRequireReauthentication() || + ssoReauthenticationMode == SsoReauthenticationMode.PRINCIPAL) { + checkPrincipal = true; + // If checkPrincipal is enabled then checkPassword is enabled if there is an SSO session if (ssoId != null) { - associate(ssoId, request.getSessionInternal(true)); + checkPassword = true; } - return true; + } else if (ssoId != null && (ssoReauthenticationMode == SsoReauthenticationMode.PASSWORD || + sso.getRequireReauthentication() && useSsoCachedUserAndPassword)) { + checkPassword = true; } - // Is there an SSO session against which we can try to reauthenticate? - if (useSSO && ssoId != null) { + // Check for a cached Principal. Most likely from SSO but could be another component. + if (checkPrincipal) { + if (ssoId != null && sso != null && sso.getRequireReauthentication()) { + // There is a valid SSO session but SSO Valve won't have cached the Principal. + sso.populateRequestFromSsoEntry(request, ssoId); + } + + // Has the user already been authenticated? + Principal principal = request.getUserPrincipal(); + if (principal != null) { + if (log.isDebugEnabled()) { + log.debug(sm.getString("authenticator.check.found", principal.getName())); + } + // Associate the session with any existing SSO session. Even if + // useSSO is false, this will ensure coordinated session + // invalidation at log out. + if (ssoId != null) { + associate(ssoId, request.getSessionInternal(true)); + } + return true; + } + } + + // Check for a user and password cached by SSO + if (checkPassword) { if (log.isDebugEnabled()) { log.debug(sm.getString("authenticator.check.sso", ssoId)); } /* - * Try to reauthenticate using data cached by SSO. If this fails, either the original SSO logon was of - * DIGEST or SSL (which we can't reauthenticate ourselves because there is no cached username and password), - * or the realm denied the user's reauthentication for some reason. In either case we have to prompt the - * user for a logon + * Try to reauthenticate using data cached by SSO. If this fails we have to prompt the user for credentials. */ if (reauthenticateFromSSO(ssoId, request)) { return true; @@ -1294,4 +1351,12 @@ FILTER, ALWAYS } + + + protected enum SsoReauthenticationMode { + DEFAULT, + PRINCIPAL, + PASSWORD, + FULL + } } diff -Nru tomcat10-10.1.40/java/org/apache/catalina/authenticator/BasicAuthenticator.java tomcat10-10.1.52/java/org/apache/catalina/authenticator/BasicAuthenticator.java --- tomcat10-10.1.40/java/org/apache/catalina/authenticator/BasicAuthenticator.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/authenticator/BasicAuthenticator.java 2026-01-23 19:33:36.000000000 +0000 @@ -34,8 +34,6 @@ /** * An Authenticator and Valve implementation of HTTP BASIC Authentication, as outlined in RFC 7617: "The * 'Basic' HTTP Authentication Scheme" - * - * @author Craig R. McClanahan */ public class BasicAuthenticator extends AuthenticatorBase { @@ -116,7 +114,7 @@ } } catch (IllegalArgumentException iae) { if (log.isDebugEnabled()) { - log.debug(sm.getString("basicAuthenticator.invalidAuthorization", iae.getMessage())); + log.debug(sm.getString("basicAuthenticator.invalidAuthorization"), iae); } } } diff -Nru tomcat10-10.1.40/java/org/apache/catalina/authenticator/DigestAuthenticator.java tomcat10-10.1.52/java/org/apache/catalina/authenticator/DigestAuthenticator.java --- tomcat10-10.1.40/java/org/apache/catalina/authenticator/DigestAuthenticator.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/authenticator/DigestAuthenticator.java 2026-01-23 19:33:36.000000000 +0000 @@ -47,9 +47,6 @@ /** * An Authenticator and Valve implementation of HTTP DIGEST Authentication, as outlined in RFC 7616: "HTTP * Digest Authentication" - * - * @author Craig R. McClanahan - * @author Remy Maucherat */ public class DigestAuthenticator extends AuthenticatorBase { @@ -266,14 +263,16 @@ @Override protected boolean doAuthenticate(Request request, HttpServletResponse response) throws IOException { - // NOTE: We don't try to reauthenticate using any existing SSO session, - // because that will only work if the original authentication was - // BASIC or FORM, which are less secure than the DIGEST auth-type - // specified for this webapp - // - // Change to true below to allow previous FORM or BASIC authentications - // to authenticate users for this webapp - // TODO make this a configurable attribute (in SingleSignOn??) + /* + * Reauthentication using the cached user name and password (if any) is not enabled for DIGEST authentication. + * This was an historical design decision made because DIGEST authentication is viewed as more secure than + * BASIC/FORM. + * + * However, reauthentication was introduced to handle the case where the Realm took additional actions on + * authentication. Reauthenticating with the cached user name and password should be sufficient for DIGEST in + * that scenario. However, the original behaviour to reauthenticate has been retained in case of any (very + * unlikely) backwards compatibility issues. + */ if (checkForCachedAuthentication(request, response, false)) { return true; } @@ -539,7 +538,7 @@ Map directives; try { directives = Authorization.parseAuthorizationDigest(new StringReader(authorization)); - } catch (IOException e) { + } catch (IOException ioe) { return false; } diff -Nru tomcat10-10.1.40/java/org/apache/catalina/authenticator/FormAuthenticator.java tomcat10-10.1.52/java/org/apache/catalina/authenticator/FormAuthenticator.java --- tomcat10-10.1.40/java/org/apache/catalina/authenticator/FormAuthenticator.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/authenticator/FormAuthenticator.java 2026-01-23 19:33:36.000000000 +0000 @@ -42,14 +42,12 @@ import org.apache.tomcat.util.buf.ByteChunk; import org.apache.tomcat.util.buf.MessageBytes; import org.apache.tomcat.util.descriptor.web.LoginConfig; +import org.apache.tomcat.util.http.Method; import org.apache.tomcat.util.http.MimeHeaders; /** * An Authenticator and Valve implementation of FORM BASED Authentication, as described in the Servlet API * Specification. - * - * @author Craig R. McClanahan - * @author Remy Maucherat */ public class FormAuthenticator extends AuthenticatorBase { @@ -247,7 +245,7 @@ try { saveRequest(request, session); } catch (IOException ioe) { - log.debug(sm.getString("authenticator.requestBodyTooBig")); + log.debug(sm.getString("authenticator.requestBodyTooBig"), ioe); response.sendError(HttpServletResponse.SC_FORBIDDEN, sm.getString("authenticator.requestBodyTooBig")); return false; } @@ -303,7 +301,7 @@ // the landing page String uri = request.getContextPath() + landingPage; SavedRequest saved = new SavedRequest(); - saved.setMethod("GET"); + saved.setMethod(Method.GET); saved.setRequestURI(uri); saved.setDecodedRequestURI(uri); request.getSessionInternal(true).setNote(Constants.FORM_REQUEST_NOTE, saved); @@ -328,7 +326,7 @@ // the landing page String uri = request.getContextPath() + landingPage; SavedRequest saved = new SavedRequest(); - saved.setMethod("GET"); + saved.setMethod(Method.GET); saved.setRequestURI(uri); saved.setDecodedRequestURI(uri); session.setNote(Constants.FORM_REQUEST_NOTE, saved); @@ -364,15 +362,7 @@ // a resource is protected for some HTTP methods but not protected for // GET which is used after authentication when redirecting to the // protected resource. - // TODO: This is similar to the FormAuthenticator.matchRequest() logic - // Is there a way to remove the duplication? - Session session = request.getSessionInternal(false); - if (session != null) { - SavedRequest savedRequest = (SavedRequest) session.getNote(Constants.FORM_REQUEST_NOTE); - return savedRequest != null && decodedRequestURI.equals(savedRequest.getDecodedRequestURI()); - } - - return false; + return matchRequest(request, false); } @@ -448,7 +438,7 @@ // Always use GET for the login page, regardless of the method used String oldMethod = request.getMethod(); - request.getCoyoteRequest().method().setString("GET"); + request.getCoyoteRequest().setMethod(Method.GET); RequestDispatcher disp = context.getServletContext().getRequestDispatcher(loginPage); try { @@ -464,7 +454,7 @@ response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, msg); } finally { // Restore original method so that it is written into access log - request.getCoyoteRequest().method().setString(oldMethod); + request.getCoyoteRequest().setMethod(oldMethod); } } @@ -506,15 +496,21 @@ } + protected boolean matchRequest(Request request) { + return matchRequest(request, true); + } + /** * Does this request match the saved one (so that it must be the redirect we signaled after successful * authentication?) * * @param request The request to be verified + * @param strict true to check for a valid Principal and valid Session ID, false to only + * check for a valid saved request and matching URI * * @return true if the requests matched the saved one */ - protected boolean matchRequest(Request request) { + protected boolean matchRequest(Request request, boolean strict) { // Has a session been created? Session session = request.getSessionInternal(false); if (session == null) { @@ -527,17 +523,19 @@ return false; } - // Is there a saved principal? - if (cache && session.getPrincipal() == null || !cache && request.getPrincipal() == null) { - return false; - } - - // Does session id match? - if (getChangeSessionIdOnAuthentication()) { - String expectedSessionId = (String) session.getNote(Constants.SESSION_ID_NOTE); - if (expectedSessionId == null || !expectedSessionId.equals(request.getRequestedSessionId())) { + if (strict) { + // Is there a saved principal? + if (cache && session.getPrincipal() == null || !cache && request.getPrincipal() == null) { return false; } + + // Does session id match? + if (getChangeSessionIdOnAuthentication()) { + String expectedSessionId = (String) session.getNote(Constants.SESSION_ID_NOTE); + if (expectedSessionId == null || !expectedSessionId.equals(request.getRequestedSessionId())) { + return false; + } + } } // Does the request URI match? @@ -590,7 +588,7 @@ String method = saved.getMethod(); MimeHeaders rmh = request.getCoyoteRequest().getMimeHeaders(); rmh.recycle(); - boolean cacheable = "GET".equalsIgnoreCase(method) || "HEAD".equalsIgnoreCase(method); + boolean cacheable = Method.GET.equals(method) || Method.HEAD.equals(method); Iterator names = saved.getHeaderNames(); while (names.hasNext()) { String name = names.next(); @@ -624,7 +622,7 @@ // If no content type specified, use default for POST String savedContentType = saved.getContentType(); - if (savedContentType == null && "POST".equalsIgnoreCase(method)) { + if (savedContentType == null && Method.POST.equals(method)) { savedContentType = Globals.CONTENT_TYPE_FORM_URL_ENCODING; } @@ -632,7 +630,7 @@ request.getCoyoteRequest().setContentType(contentType); } - request.getCoyoteRequest().method().setString(method); + request.getCoyoteRequest().setMethod(method); // The method, URI, queryString and protocol are normally stored as // bytes in the HttpInputBuffer and converted lazily to String. At this // point, the method has already been set as String in the line above @@ -646,8 +644,8 @@ request.getCoyoteRequest().queryString().toStringType(); request.getCoyoteRequest().protocol().toStringType(); - if (saved.getOriginalMaxInactiveInterval() > 0) { - session.setMaxInactiveInterval(saved.getOriginalMaxInactiveInterval()); + if (saved.getOriginalMaxInactiveIntervalOptional() != null) { + session.setMaxInactiveInterval(saved.getOriginalMaxInactiveIntervalOptional().intValue()); } return true; @@ -719,17 +717,20 @@ if (session instanceof HttpSession) { if (((HttpSession) session).isNew()) { int originalMaxInactiveInterval = session.getMaxInactiveInterval(); - if (originalMaxInactiveInterval > getAuthenticationSessionTimeout()) { + if (originalMaxInactiveInterval > getAuthenticationSessionTimeout() || + originalMaxInactiveInterval <= 0) { saved.setOriginalMaxInactiveInterval(originalMaxInactiveInterval); session.setMaxInactiveInterval(getAuthenticationSessionTimeout()); } - } else if (previousSavedRequest != null && previousSavedRequest.getOriginalMaxInactiveInterval() > 0) { + } else if (previousSavedRequest != null && + previousSavedRequest.getOriginalMaxInactiveIntervalOptional() != null) { /* * The user may have refreshed the browser page during authentication. Transfer the original max * inactive interval from previous saved request to current one else, once authentication is completed, - * the session will retain the the shorter authentication session timeout + * the session will retain the shorter authentication session timeout */ - saved.setOriginalMaxInactiveInterval(previousSavedRequest.getOriginalMaxInactiveInterval()); + saved.setOriginalMaxInactiveInterval( + previousSavedRequest.getOriginalMaxInactiveIntervalOptional().intValue()); } } diff -Nru tomcat10-10.1.40/java/org/apache/catalina/authenticator/LocalStrings.properties tomcat10-10.1.52/java/org/apache/catalina/authenticator/LocalStrings.properties --- tomcat10-10.1.40/java/org/apache/catalina/authenticator/LocalStrings.properties 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/authenticator/LocalStrings.properties 2026-01-23 19:33:36.000000000 +0000 @@ -42,7 +42,7 @@ authenticator.userDataPermissionFail=User data does not comply with the constraints of the resource authenticator.userPermissionFail=User [{0}] does not have authorization to access the resource -basicAuthenticator.invalidAuthorization=Invalid Authorization: [{0}] +basicAuthenticator.invalidAuthorization=Invalid Authorization header basicAuthenticator.invalidCharset=The only permitted values are null, the empty string or UTF-8 basicAuthenticator.notBase64=Basic Authorization credentials are not Base64 basicAuthenticator.notBasic=Authorization header method is not ''Basic'' @@ -76,9 +76,12 @@ singleSignOn.debug.principalNotFound=SSO did not find a cached Principal. Erasing SSO cookie for session [{0}] singleSignOn.debug.register=SSO registering SSO session [{0}] for user [{1}] with authentication type [{2}] singleSignOn.debug.removeSession=SSO removing application session [{0}] from SSO session [{1}] +singleSignOn.debug.sessionChangedId=SSO changing sessionID in session [{0}, oldSessionId {1}] from SSO session [{2}] singleSignOn.debug.sessionLogout=SSO processing a log out for SSO session [{0}] and application session [{1}] singleSignOn.debug.sessionTimeout=SSO processing a time out for SSO session [{0}] and application session [{1}] singleSignOn.debug.update=SSO updating SSO session [{0}] to authentication type [{1}] +singleSignOn.duplicateRealm=SSO found a realm defined on context [{0}], this will conflict with principals defined in the main realm +singleSignOn.noRealm=This SSO [{0}] has no realm associated with it singleSignOn.sessionExpire.contextNotFound=SSO unable to expire session [{0}] because the Context could not be found singleSignOn.sessionExpire.engineNull=SSO unable to expire session [{0}] because the Engine was null singleSignOn.sessionExpire.hostNotFound=SSO unable to expire session [{0}] because the Host could not be found @@ -92,6 +95,6 @@ spnegoAuthenticator.ticketValidateFail=Failed to validate client supplied ticket sslAuthenticatorValve.authFailed=Authentication with the provided certificates failed -sslAuthenticatorValve.http2=The context [{0}] in virtual host [{1}] is configured to use CLIENT-CERT authentication and [{2}] is configured to support HTTP/2. Use of CLIENT-CERT authentication is not compatible with the use of HTTP/2. +sslAuthenticatorValve.http2=The context [{0}] in virtual host [{1}] is configured to use CLIENT-CERT authentication and [{2}] is configured to support HTTP/2. Use of CLIENT-CERT authentication is not compatible with the use of HTTP/2 unless certificateVerification is set to required. sslAuthenticatorValve.noCertificates=No certificates are included with this request -sslAuthenticatorValve.tls13=The context [{0}] in virtual host [{1}] is configured to use CLIENT-CERT authentication and [{2}] is configured to support TLS 1.3 using JSSE. Use of CLIENT-CERT authentication is not compatible with the use of TLS 1.3 and JSSE. +sslAuthenticatorValve.tls13=The context [{0}] in virtual host [{1}] is configured to use CLIENT-CERT authentication and [{2}] is configured to support TLS 1.3 using JSSE. Use of CLIENT-CERT authentication is not compatible with the use of TLS 1.3 and JSSE unless certificateVerification is set to required. diff -Nru tomcat10-10.1.40/java/org/apache/catalina/authenticator/LocalStrings_fr.properties tomcat10-10.1.52/java/org/apache/catalina/authenticator/LocalStrings_fr.properties --- tomcat10-10.1.40/java/org/apache/catalina/authenticator/LocalStrings_fr.properties 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/authenticator/LocalStrings_fr.properties 2026-01-23 19:33:36.000000000 +0000 @@ -42,7 +42,7 @@ authenticator.userDataPermissionFail=Les données envoyées par l'utilisateur ne répondent pas aux contraintes définies pour la ressource authenticator.userPermissionFail=L''utilisateur [{0}] n''a pas l''autorisation d''accéder à la ressource -basicAuthenticator.invalidAuthorization=L''autorisation est invalide: [{0}] +basicAuthenticator.invalidAuthorization=L'autorisation est invalide basicAuthenticator.invalidCharset=Les seules valeurs permises sont null, la chaîne vide, ou des caractères UTF-8 basicAuthenticator.notBase64=Les informations d'identification Basic ne sont pas encodées en Base64 basicAuthenticator.notBasic=La méthode d'authentification n'est pas ''Basic'' @@ -76,9 +76,12 @@ singleSignOn.debug.principalNotFound=Le SSO n''a pas trouvé de principal en cache, le cookie SSO de la session [{0}] est effacé singleSignOn.debug.register=Enregistrement de la session SSO [{0}] pour l''utilisateur [{1}] avec le type d''authentification [{2}] singleSignOn.debug.removeSession=Le SSO retire la session applicative [{0}] de la session SSO [{1}] +singleSignOn.debug.sessionChangedId=Changement de l''id de session [{0}, ancien id {1}] dans la session SSO [{2}] singleSignOn.debug.sessionLogout=Le SSO effectue une déconnection pour la session SSO [{0}] et la session [{1}] de l''application singleSignOn.debug.sessionTimeout=Le SSO traite un timeout pour la session SSO [{0}] et la session [{1}] de l''application singleSignOn.debug.update=Le SSO met à jour la session SSO [{0}] avec le type d''authentification [{1}] +singleSignOn.duplicateRealm=Le SSO a trouvé un royaume défini sur le contexte [{0}] qui va entrer en conflit avec les principals définis dans le royaume du SSO +singleSignOn.noRealm=Ce SSO [{0}] n''a aucun royaume associé avec lui singleSignOn.sessionExpire.contextNotFound=Le SSO n''a pu faire expirer la session [{0}] parce que le contexte n''a pas été trouvé singleSignOn.sessionExpire.engineNull=Le SSO n''a pu faire expirer la session [{0}] parce que le moteur est null singleSignOn.sessionExpire.hostNotFound=SSO ne peut pas faire expirer le session [{0}] parce que l''hôte ("Host") n''a pas été trouvé diff -Nru tomcat10-10.1.40/java/org/apache/catalina/authenticator/LocalStrings_ja.properties tomcat10-10.1.52/java/org/apache/catalina/authenticator/LocalStrings_ja.properties --- tomcat10-10.1.40/java/org/apache/catalina/authenticator/LocalStrings_ja.properties 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/authenticator/LocalStrings_ja.properties 2026-01-23 19:33:36.000000000 +0000 @@ -42,7 +42,7 @@ authenticator.userDataPermissionFail=ユーザデータがリソースの制約に従っていません authenticator.userPermissionFail=ユーザ [{0}] にはリソースへのアクセス権限がありません -basicAuthenticator.invalidAuthorization=無効な認証: [{0}] +basicAuthenticator.invalidAuthorization=無効な認証 basicAuthenticator.invalidCharset=指定できる値は、null、空の文字列またはUTF-8です。 basicAuthenticator.notBase64=Basic認証の資格情報がBase64ではありません basicAuthenticator.notBasic=認証ヘッダメソッドが ''Basic'' ではありません @@ -76,9 +76,12 @@ singleSignOn.debug.principalNotFound=SSO はキャッシュされたプリンシパルを検出しませんでした。セッション [{0}] の SSO Cookie を消去しています singleSignOn.debug.register=SSO は認証タイプ [{2}] のユーザー [{1}] の SSO セッション [{0}] を登録しています singleSignOn.debug.removeSession=SSOはSSOセッション [{1}] からアプリケーションセッション [{0}] を削除しています +singleSignOn.debug.sessionChangedId=SSO は SSO セッション [{2}] からセッション [{0}、oldSessionId {1}] のセッション ID を変更しています singleSignOn.debug.sessionLogout=SSOはSSOセッション[{0}]とアプリケーションセッション[{1}]をログアウト処理しています singleSignOn.debug.sessionTimeout=SSOはSSOセッション[{0}]とアプリケーションセッション[{1}]のタイムアウトを処理しています singleSignOn.debug.update=SSOはSSOセッション [{0}] を認証タイプ [{1}] に更新します +singleSignOn.duplicateRealm=SSO はコンテキスト [{0}] で定義されたレルムを検出しました。これはメインレルムで定義されたプリンシパルと競合します +singleSignOn.noRealm=このSSO [{0}]にはレルムが関連付けられていません singleSignOn.sessionExpire.contextNotFound=Context が見つからないため、SSO はセッション [{0}] を破棄できません singleSignOn.sessionExpire.engineNull=Engine が null だったため、SSO はセッション [{0}] を破棄できません singleSignOn.sessionExpire.hostNotFound=ホストが見つからないため SSO セッション [{0}] を破棄できません diff -Nru tomcat10-10.1.40/java/org/apache/catalina/authenticator/LocalStrings_ru.properties tomcat10-10.1.52/java/org/apache/catalina/authenticator/LocalStrings_ru.properties --- tomcat10-10.1.40/java/org/apache/catalina/authenticator/LocalStrings_ru.properties 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/authenticator/LocalStrings_ru.properties 2026-01-23 19:33:36.000000000 +0000 @@ -16,4 +16,7 @@ # Do not edit this file directly. # To edit translations see: https://tomcat.apache.org/getinvolved.html#Translations +authenticator.check.found=Уже аутентифицирован [{0}] authenticator.noAuthHeader=Заголовок авторизации не был отправлен клиентом + +basicAuthenticator.invalidCharset=Единственные разрешенные значения это null, пустая строка или UTF-8 diff -Nru tomcat10-10.1.40/java/org/apache/catalina/authenticator/NonLoginAuthenticator.java tomcat10-10.1.52/java/org/apache/catalina/authenticator/NonLoginAuthenticator.java --- tomcat10-10.1.40/java/org/apache/catalina/authenticator/NonLoginAuthenticator.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/authenticator/NonLoginAuthenticator.java 2026-01-23 19:33:36.000000000 +0000 @@ -25,8 +25,6 @@ /** * An Authenticator and Valve implementation that checks only security constraints not involving user * authentication. - * - * @author Craig R. McClanahan */ public final class NonLoginAuthenticator extends AuthenticatorBase { diff -Nru tomcat10-10.1.40/java/org/apache/catalina/authenticator/SSLAuthenticator.java tomcat10-10.1.52/java/org/apache/catalina/authenticator/SSLAuthenticator.java --- tomcat10-10.1.40/java/org/apache/catalina/authenticator/SSLAuthenticator.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/authenticator/SSLAuthenticator.java 2026-01-23 19:33:36.000000000 +0000 @@ -37,12 +37,11 @@ import org.apache.juli.logging.LogFactory; import org.apache.tomcat.util.net.Constants; import org.apache.tomcat.util.net.SSLHostConfig; +import org.apache.tomcat.util.net.SSLHostConfig.CertificateVerification; /** * An Authenticator and Valve implementation of authentication that utilizes SSL certificates to identify * client users. - * - * @author Craig R. McClanahan */ public class SSLAuthenticator extends AuthenticatorBase { @@ -60,14 +59,17 @@ @Override protected boolean doAuthenticate(Request request, HttpServletResponse response) throws IOException { - // NOTE: We don't try to reauthenticate using any existing SSO session, - // because that will only work if the original authentication was - // BASIC or FORM, which are less secure than the CLIENT-CERT auth-type - // specified for this webapp - // - // Change to true below to allow previous FORM or BASIC authentications - // to authenticate users for this webapp - // TODO make this a configurable attribute (in SingleSignOn??) + /* + * Reauthentication using the cached user name and password (if any) is not enabled for CLIENT-CERT + * authentication. This was an historical design decision made because CLIENT-CERT authentication is viewed as + * more secure than BASIC/FORM. + * + * However, reauthentication was introduced to handle the case where the Realm took additional actions on + * authentication. Reauthenticating with the cached user name and password may not be sufficient for CLIENT-CERT + * since it will not make any TLS information (client certificate etc) available that a web application may + * depend on. Therefore, the reauthentication behaviour for CLIENT-CERT is to perform a normal CLIENT-CERT + * authentication. + */ if (checkForCachedAuthentication(request, response, false)) { return true; } @@ -175,28 +177,52 @@ Connector[] connectors = engine.getService().findConnectors(); for (Connector connector : connectors) { - // First check for upgrade - UpgradeProtocol[] upgradeProtocols = connector.findUpgradeProtocols(); - for (UpgradeProtocol upgradeProtocol : upgradeProtocols) { - if ("h2".equals(upgradeProtocol.getAlpnName())) { - log.warn(sm.getString("sslAuthenticatorValve.http2", context.getName(), host.getName(), connector)); + /* + * There are two underlying issues here. + * + * 1. JSSE does not implement post-handshake authentication (PHA) for TLS 1.3. That means CLIENT-CERT + * authentication will only work if the virtual host requires a certificate OR the client never requests a + * protected resource. + * + * 2. HTTP/2 does not permit re-negotiation nor PHA. That means CLIENT-CERT authentication will only work if + * the virtual host requires a certificate OR the client never requests a protected resource. + * + * We can't rely on the client never requesting a protected resource but we can check if all the virtual + * hosts are configured to require a certificate. + */ + boolean allHostsRequireCertificate = true; + for (SSLHostConfig sslHostConfig : connector.findSslHostConfigs()) { + if (sslHostConfig.getCertificateVerification() != CertificateVerification.REQUIRED) { + allHostsRequireCertificate = false; break; } } - // Then check for TLS 1.3 - SSLHostConfig[] sslHostConfigs = connector.findSslHostConfigs(); - for (SSLHostConfig sslHostConfig : sslHostConfigs) { - if (!sslHostConfig.isTls13RenegotiationAvailable()) { - String[] enabledProtocols = sslHostConfig.getEnabledProtocols(); - if (enabledProtocols == null) { - // Possibly boundOnInit is used, so use the less accurate protocols - enabledProtocols = sslHostConfig.getProtocols().toArray(new String[0]); + // Only need to check for use of HTTP/2 or TLS 1.3 if one or more hosts doesn't require a certificate + if (!allHostsRequireCertificate) { + // Check if the Connector is configured to support upgrade to HTTP/2 + UpgradeProtocol[] upgradeProtocols = connector.findUpgradeProtocols(); + for (UpgradeProtocol upgradeProtocol : upgradeProtocols) { + if ("h2".equals(upgradeProtocol.getAlpnName())) { + log.warn(sm.getString("sslAuthenticatorValve.http2", context.getName(), host.getName(), + connector)); + break; } - for (String enabledProtocol : enabledProtocols) { - if (Constants.SSL_PROTO_TLSv1_3.equals(enabledProtocol)) { - log.warn(sm.getString("sslAuthenticatorValve.tls13", context.getName(), host.getName(), - connector)); + } + + // Check if any of the virtual hosts support TLS 1.3 without supporting PHA + for (SSLHostConfig sslHostConfig : connector.findSslHostConfigs()) { + if (!sslHostConfig.isTls13RenegotiationAvailable()) { + String[] enabledProtocols = sslHostConfig.getEnabledProtocols(); + if (enabledProtocols == null) { + // Possibly boundOnInit is used, so use the less accurate protocols + enabledProtocols = sslHostConfig.getProtocols().toArray(new String[0]); + } + for (String enabledProtocol : enabledProtocols) { + if (Constants.SSL_PROTO_TLSv1_3.equals(enabledProtocol)) { + log.warn(sm.getString("sslAuthenticatorValve.tls13", context.getName(), host.getName(), + connector)); + } } } } diff -Nru tomcat10-10.1.40/java/org/apache/catalina/authenticator/SavedRequest.java tomcat10-10.1.52/java/org/apache/catalina/authenticator/SavedRequest.java --- tomcat10-10.1.40/java/org/apache/catalina/authenticator/SavedRequest.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/authenticator/SavedRequest.java 2026-01-23 19:33:36.000000000 +0000 @@ -35,8 +35,6 @@ *

    * IMPLEMENTATION NOTE - It is assumed that this object is accessed only from the context of a single thread, so * no synchronization around internal collection classes is performed. - * - * @author Craig R. McClanahan */ public final class SavedRequest implements Serializable { @@ -181,13 +179,26 @@ /** * The original maxInactiveInterval for the session. */ - private int originalMaxInactiveInterval = -1; + private Integer originalMaxInactiveInterval = null; - public int getOriginalMaxInactiveInterval() { + public Integer getOriginalMaxInactiveIntervalOptional() { return originalMaxInactiveInterval; } + /** + * Obtain the original session maxInactiveInterval. + * + * @return the original session maxInactiveInterval + * + * @deprecated This method will be removed in Tomcat 12.0.x onwards. Use + * {@link SavedRequest#getOriginalMaxInactiveIntervalOptional()} + */ + @Deprecated + public int getOriginalMaxInactiveInterval() { + return (originalMaxInactiveInterval == null) ? -1 : originalMaxInactiveInterval.intValue(); + } + public void setOriginalMaxInactiveInterval(int originalMaxInactiveInterval) { - this.originalMaxInactiveInterval = originalMaxInactiveInterval; + this.originalMaxInactiveInterval = Integer.valueOf(originalMaxInactiveInterval); } } diff -Nru tomcat10-10.1.40/java/org/apache/catalina/authenticator/SingleSignOn.java tomcat10-10.1.52/java/org/apache/catalina/authenticator/SingleSignOn.java --- tomcat10-10.1.40/java/org/apache/catalina/authenticator/SingleSignOn.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/authenticator/SingleSignOn.java 2026-01-23 19:33:36.000000000 +0000 @@ -28,6 +28,7 @@ import org.apache.catalina.Container; import org.apache.catalina.Context; import org.apache.catalina.Engine; +import org.apache.catalina.Host; import org.apache.catalina.LifecycleException; import org.apache.catalina.Manager; import org.apache.catalina.Realm; @@ -50,8 +51,33 @@ *

  • The web applications themselves must use one of the standard Authenticators found in the * org.apache.catalina.authenticator package.
  • * - * - * @author Craig R. McClanahan + *

    + * On first authentication to any web application, an SSO session is created and the authenticated Principal, the + * authentication type and the plain text user name and password used to authenticate (if available) are cached using a + * key based on the SSO session. On subsequent requests to a web application on the Host where this Valve is configured, + * the cached authenticated Principal and the authentication type are added to the request by the SSO Valve and no + * further authentication takes place. + *

    + * In some scenarios, adding the authenticated Principal and the authentication type is insufficient. This usually + * occurs when the web application depends on additional actions the Realm takes on authentication which are bypassed by + * the SSO Valve. Examples of this include the Realm setting security credentials on the request thread to support EJB + * access or the CLIENT-CERT authenticator providing the client certificate and other TLS attributes. To address this, + * the {@code requireReauthentication} flag can be set to {@code true} which will cause the SSO Valve not to set the + * cached Principal and authentication type on the request and the web application authenticator will authenticate the + * request. By default this reauthentication will occur in the following ways: + *

      + *
    • BASIC - call the realm using the plain text user name and password cached by the SSO Valve if available. If not + * cached, obtain those values from the request. If not present in the request, request them from the user agent.
    • + *
    • FORM - call the realm using the plain text user name and password cached by the SSO Valve if available. If not + * cached, request them from the user agent.
    • + *
    • DIGEST - call the realm using the credentials present in the request. If not present in the request, request them + * from the user agent.
    • + *
    • CLIENT-CERT - call the realm using the credentials present in the TLS connection. If not present in the TLS + * connection, request them from the user agent.
    • + *
    • SPNEGO - request authentication credentials from the user agent.
    • + *
    + * Note that this means that enabling reauthentication only makes sense if there are two or more web applications in the + * Host that use BASIC or FORM. If that is not the case, the SSO Valve will just add processing overhead. */ public class SingleSignOn extends ValveBase { @@ -426,8 +452,8 @@ Session session; try { session = manager.findSession(key.getSessionId()); - } catch (IOException e) { - containerLog.warn(sm.getString("singleSignOn.sessionExpire.managerError", key), e); + } catch (IOException ioe) { + containerLog.warn(sm.getString("singleSignOn.sessionExpire.managerError", key), ioe); return; } if (session == null) { @@ -439,8 +465,8 @@ /** - * Attempts reauthentication to the given Realm using the credentials associated with the single - * sign-on session identified by argument ssoId. + * Attempts reauthentication to the given Realm using the cached plain text credentials associated with + * the single sign-on session identified by argument ssoId. *

    * If reauthentication is successful, the Principal and authorization type associated with the SSO * session will be bound to the given Request object via calls to {@link Request#setAuthType @@ -480,6 +506,15 @@ } + protected void populateRequestFromSsoEntry(Request request, String ssoId) { + SingleSignOnEntry entry = cache.get(ssoId); + if (entry != null) { + request.setAuthType(entry.getAuthType()); + request.setUserPrincipal(entry.getPrincipal()); + } + } + + /** * Register the specified Principal as being associated with the specified value for the single sign on identifier. * @@ -571,12 +606,39 @@ @Override protected void startInternal() throws LifecycleException { - Container c = getContainer(); - while (c != null && !(c instanceof Engine)) { - c = c.getParent(); - } - if (c != null) { - engine = (Engine) c; + Container container = getContainer(); + while (container != null && !(container instanceof Engine)) { + container = container.getParent(); + } + if (container != null) { + engine = (Engine) container; + } + // Starting with the associated container, verify it has a realm associated, + // and that no child container returns a different realm + container = getContainer(); + Realm containerRealm = container.getRealm(); + if (containerRealm == null) { + containerLog.warn(sm.getString("singleSignOn.noRealm", container.getName())); + } else { + if (container instanceof Engine) { + for (Container host : engine.findChildren()) { + if (host.getRealm() != containerRealm) { + containerLog.warn(sm.getString("singleSignOn.duplicateRealm", host.getName())); + } else { + for (Container context : host.findChildren()) { + if (context.getRealm() != containerRealm) { + containerLog.warn(sm.getString("singleSignOn.duplicateRealm", context.getName())); + } + } + } + } + } else if (container instanceof Host) { + for (Container context : container.findChildren()) { + if (context.getRealm() != containerRealm) { + containerLog.warn(sm.getString("singleSignOn.duplicateRealm", context.getName())); + } + } + } } super.startInternal(); } @@ -587,4 +649,27 @@ super.stopInternal(); engine = null; } + + protected void sessionChangedId(String ssoId, Session session, String oldSessionId) { + if (containerLog.isDebugEnabled()) { + containerLog.debug(sm.getString("singleSignOn.debug.sessionChangedId", session, oldSessionId, ssoId)); + } + + SingleSignOnEntry entry = cache.get(ssoId); + if (entry == null) { + return; + } + + /* + * Associate the new sessionId with this SingleSignOnEntry. A SessionListener will be registered for the new + * sessionID. If not, then we would not notice any subsequent Session.SESSION_DESTROYED_EVENT for the session. + */ + entry.addSession(this, ssoId, session); + + /* + * Remove the obsolete sessionId from the SingleSignOnEntry. The sessionId part of the SingleSignOnSessionKey is + * final. + */ + entry.removeSession(session, oldSessionId); + } } diff -Nru tomcat10-10.1.40/java/org/apache/catalina/authenticator/SingleSignOnEntry.java tomcat10-10.1.52/java/org/apache/catalina/authenticator/SingleSignOnEntry.java --- tomcat10-10.1.40/java/org/apache/catalina/authenticator/SingleSignOnEntry.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/authenticator/SingleSignOnEntry.java 2026-01-23 19:33:36.000000000 +0000 @@ -34,8 +34,6 @@ * AuthenticatorBase subclasses that need it in order to perform reauthentications when SingleSignOn is in * use. * - * @author B Stansberry, based on work by Craig R. McClanahan - * * @see SingleSignOn * @see AuthenticatorBase#reauthenticateFromSSO */ @@ -101,6 +99,18 @@ sessionKeys.remove(key); } + /** + * Removes the given Session from the list of those associated with this SSO, using the previous + * sessionId + * + * @param session the Session to remove. + * @param oldSessionId the previous sessionId of the Session to remove. + */ + public void removeSession(Session session, String oldSessionId) { + SingleSignOnSessionKey key = new SingleSignOnSessionKey(session, oldSessionId); + sessionKeys.remove(key); + } + /** * Returns the HTTP Session identifiers associated with this SSO. * diff -Nru tomcat10-10.1.40/java/org/apache/catalina/authenticator/SingleSignOnListener.java tomcat10-10.1.52/java/org/apache/catalina/authenticator/SingleSignOnListener.java --- tomcat10-10.1.40/java/org/apache/catalina/authenticator/SingleSignOnListener.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/authenticator/SingleSignOnListener.java 2026-01-23 19:33:36.000000000 +0000 @@ -38,7 +38,8 @@ @Override public void sessionEvent(SessionEvent event) { - if (!Session.SESSION_DESTROYED_EVENT.equals(event.getType())) { + final String type = event.getType(); + if (!(Session.SESSION_DESTROYED_EVENT.equals(type) || Session.SESSION_CHANGED_ID_EVENT.equals(type))) { return; } @@ -56,6 +57,15 @@ if (sso == null) { return; } - sso.sessionDestroyed(ssoId, session); + + switch (type) { + case Session.SESSION_CHANGED_ID_EVENT: + sso.sessionChangedId(ssoId, session, (String) event.getData()); + break; + + case Session.SESSION_DESTROYED_EVENT: + sso.sessionDestroyed(ssoId, session); + break; + } } } diff -Nru tomcat10-10.1.40/java/org/apache/catalina/authenticator/SingleSignOnSessionKey.java tomcat10-10.1.52/java/org/apache/catalina/authenticator/SingleSignOnSessionKey.java --- tomcat10-10.1.40/java/org/apache/catalina/authenticator/SingleSignOnSessionKey.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/authenticator/SingleSignOnSessionKey.java 2026-01-23 19:33:36.000000000 +0000 @@ -41,6 +41,13 @@ this.hostName = context.getParent().getName(); } + public SingleSignOnSessionKey(Session session, String sessionId) { + this.sessionId = sessionId; + Context context = session.getManager().getContext(); + this.contextName = context.getName(); + this.hostName = context.getParent().getName(); + } + public String getSessionId() { return sessionId; } diff -Nru tomcat10-10.1.40/java/org/apache/catalina/authenticator/SpnegoAuthenticator.java tomcat10-10.1.52/java/org/apache/catalina/authenticator/SpnegoAuthenticator.java --- tomcat10-10.1.40/java/org/apache/catalina/authenticator/SpnegoAuthenticator.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/authenticator/SpnegoAuthenticator.java 2026-01-23 19:33:36.000000000 +0000 @@ -135,7 +135,17 @@ @Override protected boolean doAuthenticate(Request request, HttpServletResponse response) throws IOException { - if (checkForCachedAuthentication(request, response, true)) { + /* + * Reauthentication using the cached user name and password (if any) is not enabled for SPNEGO authentication. + * This is because the delegated credentials will nto be available unless a normal SPNEGO authentication takes + * place. + * + * Reauthentication was introduced to handle the case where the Realm took additional actions on authentication. + * Reauthenticating with the cached user name and password may not be sufficient for SPNEGO since it will not + * make the delegated credentials available that a web application may depend on. Therefore, the + * reauthentication behaviour for SPNEGO is to perform a normal SPNEGO authentication. + */ + if (checkForCachedAuthentication(request, response, false)) { return true; } diff -Nru tomcat10-10.1.40/java/org/apache/catalina/authenticator/jaspic/AuthConfigFactoryImpl.java tomcat10-10.1.52/java/org/apache/catalina/authenticator/jaspic/AuthConfigFactoryImpl.java --- tomcat10-10.1.40/java/org/apache/catalina/authenticator/jaspic/AuthConfigFactoryImpl.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/authenticator/jaspic/AuthConfigFactoryImpl.java 2026-01-23 19:33:36.000000000 +0000 @@ -556,7 +556,7 @@ @Override public AuthStatus validateRequest(MessageInfo messageInfo, Subject clientSubject, Subject serviceSubject) - throws AuthException { + throws AuthException { return module.validateRequest(messageInfo, clientSubject, serviceSubject); } diff -Nru tomcat10-10.1.40/java/org/apache/catalina/authenticator/jaspic/LocalStrings_ru.properties tomcat10-10.1.52/java/org/apache/catalina/authenticator/jaspic/LocalStrings_ru.properties --- tomcat10-10.1.40/java/org/apache/catalina/authenticator/jaspic/LocalStrings_ru.properties 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/authenticator/jaspic/LocalStrings_ru.properties 2026-01-23 19:33:36.000000000 +0000 @@ -18,4 +18,6 @@ authConfigFactoryImpl.zeroLengthAppContext=Название контекста приложения нулевой длины является недействительным +persistentProviderRegistrations.deleteFail=Временный файл [{0}] не может быть удален persistentProviderRegistrations.existsDeleteFail=Временный файл [{0}] уже существует и не может быть удалён +persistentProviderRegistrations.moveFail=Невозможно переместить [{0}] в [{1}] diff -Nru tomcat10-10.1.40/java/org/apache/catalina/authenticator/jaspic/PersistentProviderRegistrations.java tomcat10-10.1.52/java/org/apache/catalina/authenticator/jaspic/PersistentProviderRegistrations.java --- tomcat10-10.1.40/java/org/apache/catalina/authenticator/jaspic/PersistentProviderRegistrations.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/authenticator/jaspic/PersistentProviderRegistrations.java 2026-01-23 19:33:36.000000000 +0000 @@ -141,12 +141,12 @@ writer.write(" \n"); } writer.write("\n"); - } catch (IOException e) { + } catch (IOException ioe) { if (!configFileNew.delete()) { Log log = LogFactory.getLog(PersistentProviderRegistrations.class); log.warn(sm.getString("persistentProviderRegistrations.deleteFail", configFileNew.getAbsolutePath())); } - throw new SecurityException(e); + throw new SecurityException(ioe); } // Move the current file out of the way diff -Nru tomcat10-10.1.40/java/org/apache/catalina/connector/ClientAbortException.java tomcat10-10.1.52/java/org/apache/catalina/connector/ClientAbortException.java --- tomcat10-10.1.40/java/org/apache/catalina/connector/ClientAbortException.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/connector/ClientAbortException.java 2026-01-23 19:33:36.000000000 +0000 @@ -20,8 +20,6 @@ /** * Extend IOException to identify it as being caused by an abort of a request by a remote client. - * - * @author Glenn L. Nielsen */ public final class ClientAbortException extends BadRequestException { diff -Nru tomcat10-10.1.40/java/org/apache/catalina/connector/Connector.java tomcat10-10.1.52/java/org/apache/catalina/connector/Connector.java --- tomcat10-10.1.40/java/org/apache/catalina/connector/Connector.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/connector/Connector.java 2026-01-23 19:33:36.000000000 +0000 @@ -29,22 +29,22 @@ import org.apache.catalina.LifecycleException; import org.apache.catalina.LifecycleState; import org.apache.catalina.Service; -import org.apache.catalina.core.AprStatus; import org.apache.catalina.util.LifecycleMBeanBase; import org.apache.coyote.AbstractProtocol; import org.apache.coyote.Adapter; import org.apache.coyote.ProtocolHandler; import org.apache.coyote.UpgradeProtocol; import org.apache.coyote.http11.AbstractHttp11JsseProtocol; -import org.apache.coyote.http11.AbstractHttp11Protocol; import org.apache.juli.logging.Log; import org.apache.juli.logging.LogFactory; +import org.apache.tomcat.jni.AprStatus; import org.apache.tomcat.util.IntrospectionUtils; import org.apache.tomcat.util.buf.B2CConverter; import org.apache.tomcat.util.buf.CharsetUtil; import org.apache.tomcat.util.buf.EncodedSolidusHandling; import org.apache.tomcat.util.buf.StringUtils; import org.apache.tomcat.util.compat.JreCompat; +import org.apache.tomcat.util.http.Method; import org.apache.tomcat.util.net.SSLHostConfig; import org.apache.tomcat.util.net.openssl.OpenSSLImplementation; import org.apache.tomcat.util.net.openssl.OpenSSLStatus; @@ -53,9 +53,6 @@ /** * Implementation of a Coyote connector. - * - * @author Craig R. McClanahan - * @author Remy Maucherat */ public class Connector extends LifecycleMBeanBase { @@ -64,6 +61,22 @@ public static final String INTERNAL_EXECUTOR_NAME = "Internal"; + private static final boolean aprStatusPresent; + + static { + /* + * The AprStatus class has to be in the org.apache.tomcat.jni package so it can be referenced by the OpenSSL + * clean-up code to avoid a race condition on shutdown between the AprLifecycleListener shutting down the Tomcat + * Native library along with any remaining open connections and the OpenSSL clean-up code shutting down an + * individual connection that can trigger a JVM crash. + * + * In some deployment scenarios AprStatus is not present - e.g. because tomcat-jni.jar is not present. To avoid + * a CNFE in this class on Connector initialisation when AprStatus is not present - and ugly work-arounds that + * try loading the class and catching the exception - use getResource() to see if AprStatus is present. + */ + aprStatusPresent = + (Connector.class.getClassLoader().getResource("org/apache/tomcat/jni/AprStatus.class") != null); + } // ------------------------------------------------------------ Constructor @@ -212,6 +225,10 @@ */ protected int maxParameterCount = 10000; + private int maxPartCount = 50; + + private int maxPartHeaderSize = 512; + /** * Maximum size of a POST which will be automatically parsed by the container. 2 MiB by default. */ @@ -227,7 +244,7 @@ * Comma-separated list of HTTP methods that will be parsed according to POST-style rules for * application/x-www-form-urlencoded request bodies. */ - protected String parseBodyMethods = "POST"; + protected String parseBodyMethods = Method.POST; /** * A Set of methods determined by {@link #parseBodyMethods}. @@ -482,6 +499,26 @@ } + public int getMaxPartCount() { + return maxPartCount; + } + + + public void setMaxPartCount(int maxPartCount) { + this.maxPartCount = maxPartCount; + } + + + public int getMaxPartHeaderSize() { + return maxPartHeaderSize; + } + + + public void setMaxPartHeaderSize(int maxPartHeaderSize) { + this.maxPartHeaderSize = maxPartHeaderSize; + } + + /** * @return the maximum size of a POST which will be automatically parsed by the container. */ @@ -541,7 +578,7 @@ methodSet.addAll(Arrays.asList(StringUtils.splitCommaSeparated(methods))); } - if (methodSet.contains("TRACE")) { + if (methodSet.contains(Method.TRACE)) { throw new IllegalArgumentException(sm.getString("coyoteConnector.parseBodyMethodNoTrace")); } @@ -1025,25 +1062,21 @@ setParseBodyMethods(getParseBodyMethods()); } - if (JreCompat.isJre22Available() && OpenSSLStatus.getUseOpenSSL() && OpenSSLStatus.isAvailable() && - protocolHandler instanceof AbstractHttp11Protocol) { - // Use FFM and OpenSSL if available - AbstractHttp11JsseProtocol jsseProtocolHandler = (AbstractHttp11JsseProtocol) protocolHandler; - if (jsseProtocolHandler.isSSLEnabled() && jsseProtocolHandler.getSslImplementationName() == null) { - // OpenSSL is compatible with the JSSE configuration, so use it if it is available - jsseProtocolHandler - .setSslImplementationName("org.apache.tomcat.util.net.openssl.panama.OpenSSLImplementation"); - } - } else if (AprStatus.isAprAvailable() && AprStatus.getUseOpenSSL() && - protocolHandler instanceof AbstractHttp11Protocol) { - // Use tomcat-native and OpenSSL otherwise, if available + if (protocolHandler instanceof AbstractHttp11JsseProtocol) { AbstractHttp11JsseProtocol jsseProtocolHandler = (AbstractHttp11JsseProtocol) protocolHandler; if (jsseProtocolHandler.isSSLEnabled() && jsseProtocolHandler.getSslImplementationName() == null) { - // OpenSSL is compatible with the JSSE configuration, so use it if APR is available - jsseProtocolHandler.setSslImplementationName(OpenSSLImplementation.class.getName()); + // If SSL is enabled and a specific implementation isn't specified, select the correct default. + if (JreCompat.isJre22Available() && OpenSSLStatus.getUseOpenSSL() && OpenSSLStatus.isAvailable()) { + // Use FFM and OpenSSL if available + jsseProtocolHandler.setSslImplementationName( + "org.apache.tomcat.util.net.openssl.panama.OpenSSLImplementation"); + } else if (aprStatusPresent && AprStatus.isAprAvailable() && AprStatus.getUseOpenSSL()) { + // Use tomcat-native and OpenSSL otherwise, if available + jsseProtocolHandler.setSslImplementationName(OpenSSLImplementation.class.getName()); + } + // Otherwise the default JSSE will be used } } - // Otherwise the default JSSE will be used try { protocolHandler.init(); diff -Nru tomcat10-10.1.40/java/org/apache/catalina/connector/CoyoteAdapter.java tomcat10-10.1.52/java/org/apache/catalina/connector/CoyoteAdapter.java --- tomcat10-10.1.40/java/org/apache/catalina/connector/CoyoteAdapter.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/connector/CoyoteAdapter.java 2026-01-23 19:33:36.000000000 +0000 @@ -48,6 +48,7 @@ import org.apache.tomcat.util.buf.CharChunk; import org.apache.tomcat.util.buf.HexUtils; import org.apache.tomcat.util.buf.MessageBytes; +import org.apache.tomcat.util.http.Method; import org.apache.tomcat.util.http.ServerCookie; import org.apache.tomcat.util.http.ServerCookies; import org.apache.tomcat.util.net.SSLSupport; @@ -57,9 +58,6 @@ /** * Implementation of a request processor which delegates the processing to a Coyote processor. - * - * @author Craig R. McClanahan - * @author Remy Maucherat */ public class CoyoteAdapter implements Adapter { @@ -260,9 +258,9 @@ } success = false; } - } catch (IOException e) { + } catch (IOException ioe) { + // Issues that should be logged will have already been logged success = false; - // Ignore } catch (Throwable t) { ExceptionUtils.handleThrowable(t); success = false; @@ -373,8 +371,8 @@ response.finishResponse(); } - } catch (IOException e) { - // Ignore + } catch (IOException ignore) { + // Issues that should be logged will have already been logged } finally { AtomicBoolean error = new AtomicBoolean(false); res.action(ActionCode.IS_ERROR, error); @@ -595,7 +593,7 @@ // Check for ping OPTIONS * request if (undecodedURI.equals("*")) { - if (req.method().equals("OPTIONS")) { + if (Method.OPTIONS.equals(req.getMethod())) { StringBuilder allow = new StringBuilder(); allow.append("GET, HEAD, POST, PUT, DELETE, OPTIONS"); // Trace if allowed @@ -614,7 +612,7 @@ MessageBytes decodedURI = req.decodedURI(); // Filter CONNECT method - if (req.method().equals("CONNECT")) { + if (Method.CONNECT.equals(req.getMethod())) { response.sendError(HttpServletResponse.SC_NOT_IMPLEMENTED, sm.getString("coyoteAdapter.connect")); } else { // No URI for CONNECT requests @@ -782,8 +780,8 @@ // point. try { Thread.sleep(1000); - } catch (InterruptedException e) { - // Should never happen + } catch (InterruptedException ignore) { + // Should never happen but, if it does, just continue looping } // Reset mapping request.getMappingData().recycle(); @@ -813,14 +811,14 @@ } // Filter TRACE method - if (!connector.getAllowTrace() && req.method().equals("TRACE")) { + if (!connector.getAllowTrace() && Method.TRACE.equals(req.getMethod())) { Wrapper wrapper = request.getWrapper(); StringBuilder header = null; if (wrapper != null) { String[] methods = wrapper.getServletMethods(); if (methods != null) { for (String method : methods) { - if ("TRACE".equals(method)) { + if (Method.TRACE.equals(method)) { continue; } if (header == null) { diff -Nru tomcat10-10.1.40/java/org/apache/catalina/connector/CoyoteInputStream.java tomcat10-10.1.52/java/org/apache/catalina/connector/CoyoteInputStream.java --- tomcat10-10.1.40/java/org/apache/catalina/connector/CoyoteInputStream.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/connector/CoyoteInputStream.java 2026-01-23 19:33:36.000000000 +0000 @@ -31,8 +31,6 @@ /** * This class handles reading bytes. - * - * @author Remy Maucherat */ public class CoyoteInputStream extends ServletInputStream { diff -Nru tomcat10-10.1.40/java/org/apache/catalina/connector/CoyoteOutputStream.java tomcat10-10.1.52/java/org/apache/catalina/connector/CoyoteOutputStream.java --- tomcat10-10.1.40/java/org/apache/catalina/connector/CoyoteOutputStream.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/connector/CoyoteOutputStream.java 2026-01-23 19:33:36.000000000 +0000 @@ -27,9 +27,6 @@ /** * Coyote implementation of the servlet output stream. - * - * @author Costin Manolache - * @author Remy Maucherat */ public class CoyoteOutputStream extends ServletOutputStream { diff -Nru tomcat10-10.1.40/java/org/apache/catalina/connector/CoyotePrincipal.java tomcat10-10.1.52/java/org/apache/catalina/connector/CoyotePrincipal.java --- tomcat10-10.1.40/java/org/apache/catalina/connector/CoyotePrincipal.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/connector/CoyotePrincipal.java 2026-01-23 19:33:36.000000000 +0000 @@ -22,8 +22,6 @@ /** * Generic implementation of java.security.Principal that is used to represent principals authenticated * at the protocol handler level. - * - * @author Remy Maucherat */ public class CoyotePrincipal implements Principal, Serializable { diff -Nru tomcat10-10.1.40/java/org/apache/catalina/connector/CoyoteReader.java tomcat10-10.1.52/java/org/apache/catalina/connector/CoyoteReader.java --- tomcat10-10.1.40/java/org/apache/catalina/connector/CoyoteReader.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/connector/CoyoteReader.java 2026-01-23 19:33:36.000000000 +0000 @@ -22,8 +22,6 @@ /** * Coyote implementation of the buffered reader. - * - * @author Remy Maucherat */ public class CoyoteReader extends BufferedReader { diff -Nru tomcat10-10.1.40/java/org/apache/catalina/connector/CoyoteWriter.java tomcat10-10.1.52/java/org/apache/catalina/connector/CoyoteWriter.java --- tomcat10-10.1.40/java/org/apache/catalina/connector/CoyoteWriter.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/connector/CoyoteWriter.java 2026-01-23 19:33:36.000000000 +0000 @@ -21,8 +21,6 @@ /** * Coyote implementation of the servlet writer. - * - * @author Remy Maucherat */ public class CoyoteWriter extends PrintWriter { @@ -91,8 +89,8 @@ try { ob.flush(); - } catch (IOException e) { - setErrorException(e); + } catch (IOException ioe) { + setErrorException(ioe); } } @@ -105,7 +103,7 @@ // so the stream can be reused. We close ob. try { ob.close(); - } catch (IOException ex) { + } catch (IOException ignore) { // Ignore } error = false; @@ -129,8 +127,8 @@ try { ob.write(c); - } catch (IOException e) { - setErrorException(e); + } catch (IOException ioe) { + setErrorException(ioe); } } @@ -145,8 +143,8 @@ try { ob.write(buf, off, len); - } catch (IOException e) { - setErrorException(e); + } catch (IOException ioe) { + setErrorException(ioe); } } @@ -167,8 +165,8 @@ try { ob.write(s, off, len); - } catch (IOException e) { - setErrorException(e); + } catch (IOException ioe) { + setErrorException(ioe); } } diff -Nru tomcat10-10.1.40/java/org/apache/catalina/connector/InputBuffer.java tomcat10-10.1.52/java/org/apache/catalina/connector/InputBuffer.java --- tomcat10-10.1.40/java/org/apache/catalina/connector/InputBuffer.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/connector/InputBuffer.java 2026-01-23 19:33:36.000000000 +0000 @@ -48,8 +48,6 @@ * The buffer used by Tomcat request. This is a derivative of the Tomcat 3.3 OutputBuffer, adapted to handle input * instead of output. This allows complete recycling of the facade objects (the ServletInputStream and the * BufferedReader). - * - * @author Remy Maucherat */ public class InputBuffer extends Reader implements ByteChunk.ByteInputChannel, ApplicationBufferHandler { @@ -60,6 +58,8 @@ private static final Log log = LogFactory.getLog(InputBuffer.class); + private static final ByteBuffer EMPTY_BUFFER = ByteBuffer.allocate(0); + public static final int DEFAULT_BUFFER_SIZE = 8 * 1024; // The buffer can be used for byte[] and char[] reading @@ -76,8 +76,11 @@ // ----------------------------------------------------- Instance Variables - /** - * The byte buffer. + /* + * The byte buffer. Data is always injected into this class by calling {@link #setByteBuffer(ByteBuffer)} rather + * than copying data into any existing buffer. It is initialised to an empty buffer as there are code paths that + * access the buffer when it is expected to be empty and an empty buffer gives cleaner code than lots of null + * checks. */ private ByteBuffer bb; @@ -151,8 +154,8 @@ public InputBuffer(int size) { this.size = size; - bb = ByteBuffer.allocate(size); - clear(bb); + // Will be replaced when there is data to read so initialise to empty buffer. + bb = EMPTY_BUFFER; cb = CharBuffer.allocate(size); clear(cb); readLimit = size; @@ -191,7 +194,11 @@ } readLimit = size; markPos = -1; - clear(bb); + /* + * This buffer will have been replaced if there was data to read so re-initialise to an empty buffer to clear + * any reference to an injected buffer. + */ + bb = EMPTY_BUFFER; closed = false; if (conv != null) { diff -Nru tomcat10-10.1.40/java/org/apache/catalina/connector/LocalStrings.properties tomcat10-10.1.52/java/org/apache/catalina/connector/LocalStrings.properties --- tomcat10-10.1.40/java/org/apache/catalina/connector/LocalStrings.properties 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/connector/LocalStrings.properties 2026-01-23 19:33:36.000000000 +0000 @@ -62,6 +62,7 @@ coyoteRequest.noAsync=Unable to start async because the following classes in the processing chain do not support async [{0}] coyoteRequest.noMultipartConfig=Unable to process parts as no multi-part configuration has been provided coyoteRequest.parseParameters=Exception thrown whilst processing POSTed parameters +coyoteRequest.partsParseException=Exception [{0}] occurred parsing parts and will be thrown coyoteRequest.postTooLarge=Parameters were not parsed because the size of the posted data was too big. Use the maxPostSize attribute of the connector to resolve this if the application should accept large POSTs. coyoteRequest.sendfileNotCanonical=Unable to determine canonical name of file [{0}] specified for use with sendfile coyoteRequest.sessionCreateCommitted=Cannot create a session after the response has been committed @@ -91,6 +92,7 @@ request.fragmentInDispatchPath=The fragment in dispatch path [{0}] has been removed request.illegalWrap=The request wrapper must wrap the request obtained from getRequest() request.notAsync=It is illegal to call this method if the current request is not in asynchronous mode (i.e. isAsyncStarted() returns false) +request.partCleanup.failed=Unable to delete temporary file for uploaded part after multi-part processing failed request.session.failed=Failed to load session [{0}] due to [{1}] requestFacade.nullRequest=The request object has been recycled and is no longer associated with this facade diff -Nru tomcat10-10.1.40/java/org/apache/catalina/connector/LocalStrings_es.properties tomcat10-10.1.52/java/org/apache/catalina/connector/LocalStrings_es.properties --- tomcat10-10.1.40/java/org/apache/catalina/connector/LocalStrings_es.properties 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/connector/LocalStrings_es.properties 2026-01-23 19:33:36.000000000 +0000 @@ -38,7 +38,7 @@ coyoteRequest.attributeEvent=Excepción lanzada mediante el escuchador de eventos de atributos coyoteRequest.authenticate.ise=No puedo llamar a authenticate() tras haberse acometido la respuesta coyoteRequest.changeSessionId=No se puede cambiar el ID de sesión. No hay sesión asociada con esta solicitud -coyoteRequest.chunkedPostTooLarge=No se han analizado los parámetros porque la medida de los datos enviados meiante "post" era demasiado grande. Debido a que este requerimiento es una parte del original, no puede ser procesado. Utiliza el atributo "maxPostSize" del conector para resolver esta situación, en caso de que la aplicación deba de aceptar POSTs mayores. +coyoteRequest.chunkedPostTooLarge=No se han analizado los parámetros porque la medida de los datos enviados meiante POST era demasiado grande. Debido a que este requerimiento es una parte del original, no puede ser procesado. Utiliza el atributo "maxPostSize" del conector para resolver esta situación, en caso de que la aplicación deba de aceptar POSTs mayores. coyoteRequest.filterAsyncSupportUnknown=Imposible determinar si algún filtro no soporta procesamiento asincrónico coyoteRequest.getInputStream.ise=getReader() ya ha sido llamado para este requerimiento coyoteRequest.getReader.ise=getInputStream() ya ha sido llamado para este requerimiento diff -Nru tomcat10-10.1.40/java/org/apache/catalina/connector/LocalStrings_fr.properties tomcat10-10.1.52/java/org/apache/catalina/connector/LocalStrings_fr.properties --- tomcat10-10.1.40/java/org/apache/catalina/connector/LocalStrings_fr.properties 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/connector/LocalStrings_fr.properties 2026-01-23 19:33:36.000000000 +0000 @@ -62,6 +62,7 @@ coyoteRequest.noAsync=Impossible de démarrer le mode asynchrone car les classes [{0}] de la chaîne de traitement ne le supportent pas coyoteRequest.noMultipartConfig=Impossible de traiter des parties, parce qu'aucune configuration multi-parties n'a été fournie coyoteRequest.parseParameters=Exception lors du traitement des paramètres envoyés par POST +coyoteRequest.partsParseException=Une exception [{0}] s''est produite lors du traitement des portions du message et sera lancée coyoteRequest.postTooLarge=Les paramètres n'ont pas été évalués car la taille des données postées est trop important. Utilisez l'attribut maxPostSize du connecteur pour corriger ce problème si votre application doit accepter des POSTs importants. coyoteRequest.sendfileNotCanonical=Impossible d''obtenir le nom canonique du fichier [{0}] qui a été donné pour le sendfile coyoteRequest.sessionCreateCommitted=Impossible de créer une session après que la réponse ait été envoyée @@ -91,6 +92,7 @@ request.fragmentInDispatchPath=Le fragment dans le chemin de dispatch [{0}] a été enlevé request.illegalWrap=L'enrobeur de la réponse doit enrober la requête obtenue à partir de getRequest() request.notAsync=Il est interdit d'appeler cette méthode si la requête actuelle n'est pas en mode asynchrone (isAsyncStarted() a renvoyé false) +request.partCleanup.failed=Impossible d'effacer le fichier temporaire pour la partie envoyée après l'échec de traitement du multi partie request.session.failed=Erreur de chargement de la session [{0}] à cause de [{1}] requestFacade.nullRequest=L'objet requête a été recyclé et n'est plus associé à cette façade diff -Nru tomcat10-10.1.40/java/org/apache/catalina/connector/LocalStrings_ja.properties tomcat10-10.1.52/java/org/apache/catalina/connector/LocalStrings_ja.properties --- tomcat10-10.1.40/java/org/apache/catalina/connector/LocalStrings_ja.properties 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/connector/LocalStrings_ja.properties 2026-01-23 19:33:36.000000000 +0000 @@ -62,8 +62,9 @@ coyoteRequest.noAsync=処理チェーン内の次のクラスが非同期をサポートしていないため、非同期を開始できません [{0}] coyoteRequest.noMultipartConfig=multi-part 構成が提供されていないため、partを処理できません coyoteRequest.parseParameters=POST パラメーターの処理中に例外を投げました。 +coyoteRequest.partsParseException=パートの解析中に例外 [{0}] が発生しました coyoteRequest.postTooLarge=POSTされたデータが大きすぎたので、パラメータが構文解析できませんでした。そのアプリケーションが巨大なPOSTを受け付けねばならない場合には、これを解決するためにコネクタのmaxPostSize属性を使用してください。 -coyoteRequest.sendfileNotCanonical=sendfile に指定されたファイル [{0}] の正式名を取得できません +coyoteRequest.sendfileNotCanonical=sendfile に指定されたファイル [{0}] の正規名を取得できません coyoteRequest.sessionCreateCommitted=レスポンスをコミットした後でセッションを作成できません coyoteRequest.sessionEndAccessFail=リクエストの再利用中に行ったセッションへのアクセス終了処理で例外が送出されました。 coyoteRequest.setAttribute.namenull=setAttributeを名前を指定せずに呼び出すことはできません @@ -91,6 +92,7 @@ request.fragmentInDispatchPath=ディスパッチパス [{0}] 中のフラグメントは除去されました request.illegalWrap=リクエストラッパーは getRequest() で取得したリクエストをラップしなければなりません。 request.notAsync=非同期モードではないリクエストでこのメソッドを呼び出すことはできません。(例えば isAsyncStarted() が false を返す場合) +request.partCleanup.failed=マルチパート処理が失敗した後、アップロードされたパートのテンポラリファイルを削除できませんでした request.session.failed=[{1}]が原因で、セッション[{0}]の読み込みに失敗しました requestFacade.nullRequest=リクエストオブジェクトは回収されこのファサードに関連付けられなくなりました。 diff -Nru tomcat10-10.1.40/java/org/apache/catalina/connector/LocalStrings_ru.properties tomcat10-10.1.52/java/org/apache/catalina/connector/LocalStrings_ru.properties --- tomcat10-10.1.40/java/org/apache/catalina/connector/LocalStrings_ru.properties 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/connector/LocalStrings_ru.properties 2026-01-23 19:33:36.000000000 +0000 @@ -25,5 +25,6 @@ coyoteInputStream.nbNotready=В неблокирующем режиме невозможно читать из ServletInputStream до тех пор пока не завершится предыдущее чтение и IsReady() не вернёт true +coyoteRequest.changeSessionId=Невозможно изменить ID сессии. Нет сессии связаной с этим запросом. coyoteRequest.sendfileNotCanonical=Невозможно определить каноническое имя файла [{0}] указанное для использования с sendfile coyoteRequest.sessionEndAccessFail=Исключение вызвало прекращение доступа к сессии при очистке запроса diff -Nru tomcat10-10.1.40/java/org/apache/catalina/connector/OutputBuffer.java tomcat10-10.1.52/java/org/apache/catalina/connector/OutputBuffer.java --- tomcat10-10.1.40/java/org/apache/catalina/connector/OutputBuffer.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/connector/OutputBuffer.java 2026-01-23 19:33:36.000000000 +0000 @@ -37,14 +37,12 @@ import org.apache.coyote.Response; import org.apache.tomcat.util.buf.B2CConverter; import org.apache.tomcat.util.buf.C2BConverter; +import org.apache.tomcat.util.http.Method; import org.apache.tomcat.util.res.StringManager; /** * The buffer used by Tomcat response. This is a derivative of the Tomcat 3.3 OutputBuffer, with the removal of some of * the state handling (which in Coyote is mostly the Processor's responsibility). - * - * @author Costin Manolache - * @author Remy Maucherat */ public class OutputBuffer extends Writer { @@ -238,8 +236,8 @@ // - the content length has not been explicitly set // AND // - some content has been written OR this is NOT a HEAD request - if ((!coyoteResponse.isCommitted()) && (coyoteResponse.getContentLengthLong() == -1) && - ((bb.remaining() > 0 || !coyoteResponse.getRequest().method().equals("HEAD")))) { + if (!coyoteResponse.isCommitted() && coyoteResponse.getContentLengthLong() == -1 && + (bb.remaining() > 0 || !Method.HEAD.equals(coyoteResponse.getRequest().getMethod()))) { coyoteResponse.setContentLength(bb.remaining()); } @@ -335,11 +333,11 @@ // Prevent further output for this response closed = true; throw e; - } catch (IOException e) { + } catch (IOException ioe) { // An IOException on a write is almost always due to // the remote client aborting the request. Wrap this // so that it can be handled better by the error dispatcher. - throw new ClientAbortException(e); + throw new ClientAbortException(ioe); } } diff -Nru tomcat10-10.1.40/java/org/apache/catalina/connector/Request.java tomcat10-10.1.52/java/org/apache/catalina/connector/Request.java --- tomcat10-10.1.40/java/org/apache/catalina/connector/Request.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/connector/Request.java 2026-01-23 19:33:36.000000000 +0000 @@ -111,6 +111,7 @@ import org.apache.tomcat.util.http.fileupload.FileItem; import org.apache.tomcat.util.http.fileupload.FileUpload; import org.apache.tomcat.util.http.fileupload.disk.DiskFileItemFactory; +import org.apache.tomcat.util.http.fileupload.impl.FileCountLimitExceededException; import org.apache.tomcat.util.http.fileupload.impl.InvalidContentTypeException; import org.apache.tomcat.util.http.fileupload.impl.SizeException; import org.apache.tomcat.util.http.fileupload.servlet.ServletRequestContext; @@ -124,9 +125,6 @@ /** * Wrapper object for the Coyote request. - * - * @author Remy Maucherat - * @author Craig R. McClanahan */ public class Request implements HttpServletRequest { @@ -143,6 +141,11 @@ */ public Request(Connector connector) { this.connector = connector; + if (connector != null) { + maxParameterCount = connector.getMaxParameterCount(); + maxPartCount = connector.getMaxPartCount(); + maxPartHeaderSize = connector.getMaxPartHeaderSize(); + } } @@ -411,14 +414,22 @@ private HttpServletRequest applicationRequest = null; + /** + * The maximum number of request parameters + */ + private int maxParameterCount = -1; + + private int maxPartCount = -1; + + private int maxPartHeaderSize = -1; // --------------------------------------------------------- Public Methods - protected void addPathParameter(String name, String value) { + public void addPathParameter(String name, String value) { coyoteRequest.addPathParameter(name, value); } - protected String getPathParameter(String name) { + public String getPathParameter(String name) { return coyoteRequest.getPathParameter(name); } @@ -441,6 +452,15 @@ userPrincipal = null; subject = null; parametersParsed = false; + if (connector != null) { + maxParameterCount = connector.getMaxParameterCount(); + maxPartCount = connector.getMaxPartCount(); + maxPartHeaderSize = connector.getMaxPartHeaderSize(); + } else { + maxParameterCount = -1; + maxPartCount = -1; + maxPartHeaderSize = -1; + } if (parts != null) { for (Part part : parts) { try { @@ -505,7 +525,7 @@ } - protected void recycleSessionInfo() { + public void recycleSessionInfo() { if (session != null) { try { session.endAccess(); @@ -829,6 +849,36 @@ } + /** + * Set the maximum number of request parameters (GET plus POST including multipart) for a single request. + * + * @param maxParameterCount The maximum number of request parameters + */ + public void setMaxParameterCount(int maxParameterCount) { + this.maxParameterCount = maxParameterCount; + } + + + /** + * Set the maximum number of parts for a single multipart request. + * + * @param maxPartCount The maximum number of request parts + */ + public void setMaxPartCount(int maxPartCount) { + this.maxPartCount = maxPartCount; + } + + + /** + * Set the maximum header size per part for a single multipart request. + * + * @param maxPartHeaderSize The maximum size of the headers for one part + */ + public void setMaxPartHeaderSize(int maxPartHeaderSize) { + this.maxPartHeaderSize = maxPartHeaderSize; + } + + // ------------------------------------------------- ServletRequest Methods @Override @@ -900,8 +950,8 @@ * {@inheritDoc} *

    * The attribute names returned will only be those for the attributes set via {@link #setAttribute(String, Object)}. - * Tomcat internal attributes will not be included even though they are accessible via {@link #getAttribute(String)}. - * The Tomcat internal attributes include: + * Tomcat internal attributes will not be included even though they are accessible via + * {@link #getAttribute(String)}. The Tomcat internal attributes include: *

      *
    • {@link Globals#DISPATCHER_TYPE_ATTR}
    • *
    • {@link Globals#DISPATCHER_REQUEST_PATH_ATTR}
    • @@ -1381,8 +1431,8 @@ String canonicalPath; try { canonicalPath = new File(value.toString()).getCanonicalPath(); - } catch (IOException e) { - throw new SecurityException(sm.getString("coyoteRequest.sendfileNotCanonical", value), e); + } catch (IOException ioe) { + throw new SecurityException(sm.getString("coyoteRequest.sendfileNotCanonical", value), ioe); } // Sendfile is performed in Tomcat's security context so need to // check if the web app is permitted to access the file while still @@ -2110,7 +2160,7 @@ @Override public String getMethod() { - return coyoteRequest.method().toStringType(); + return coyoteRequest.getMethod(); } @@ -2252,8 +2302,8 @@ Session session = null; try { session = manager.findSession(requestedSessionId); - } catch (IOException e) { - // Can't find the session + } catch (IOException ignore) { + // Error looking up session. Treat it as not found. } if ((session == null) || !session.isValid()) { @@ -2265,8 +2315,8 @@ if (ctxt.getManager().findSession(requestedSessionId) != null) { return true; } - } catch (IOException e) { - // Ignore + } catch (IOException ignore) { + // Error looking up session. Treat it as not found. } } } @@ -2484,6 +2534,11 @@ parseParts(true); if (partsParseException != null) { + Context context = getContext(); + if (context != null && context.getLogger().isDebugEnabled()) { + context.getLogger() + .debug(sm.getString("coyoteRequest.partsParseException", partsParseException.getMessage())); + } if (partsParseException instanceof IOException) { throw (IOException) partsParseException; } else if (partsParseException instanceof IllegalStateException) { @@ -2514,15 +2569,33 @@ } else { if (explicit) { partsParseException = new IllegalStateException(sm.getString("coyoteRequest.noMultipartConfig")); - return; } else { parts = Collections.emptyList(); - return; } + return; } } - int maxParameterCount = getConnector().getMaxParameterCount(); + /* + * When the request body is multipart/form-data, both the parts and the query string count towards + * maxParameterCount. If parseParts() is called before getParameterXXX() then the parts will be parsed before + * the query string. Otherwise, the query string will be parsed first. + * + * maxParameterCount must be respected regardless of which is parsed first. + * + * maxParameterCount is reset from the Connector at the start of every request. + * + * If parts are parsed first, non-file parts will be added to the parameter map and any files will reduce + * maxParameterCount by 1 so that when the query string is parsed the difference between the size of the + * parameter map and maxParameterCount will be the original maxParameterCount less the number of parts. i.e. the + * maxParameterCount applied to the query string will be the original maxParameterCount less the number of + * parts. + * + * If the query string is parsed first, all parameters will be added to the parameter map and, ignoring + * maxPartCount, the part limit will be set to the original maxParameterCount less the size of the parameter + * map. i.e. the maxParameterCount applied to the parts will be the original maxParameterCount less the number + * of query parameters. + */ Parameters parameters = coyoteRequest.getParameters(); parameters.setLimit(maxParameterCount); @@ -2571,35 +2644,53 @@ upload.setFileItemFactory(factory); upload.setFileSizeMax(mce.getMaxFileSize()); upload.setSizeMax(mce.getMaxRequestSize()); - if (maxParameterCount > -1) { - // There is a limit. The limit for parts needs to be reduced by - // the number of parameters we have already parsed. - // Must be under the limit else parsing parameters would have - // triggered an exception. - upload.setFileCountMax(maxParameterCount - parameters.size()); + upload.setPartHeaderSizeMax(maxPartHeaderSize); + /* + * There are two independent limits on the number of parts. + * + * 1. The limit based on parameters. This is maxParameterCount less the number of parameters already + * processed. + * + * 2. The limit based on parts. This is maxPartCount. + * + * The lower of these two limits will be applied to this request. + * + * Note: Either of both limits may be set to -1 (unlimited). + */ + int partLimit = maxParameterCount; + if (partLimit > -1) { + partLimit = partLimit - parameters.size(); + } + int maxPartCount = this.maxPartCount; + if (maxPartCount > -1) { + if (partLimit < 0 || partLimit > maxPartCount) { + partLimit = maxPartCount; + } } + upload.setFileCountMax(partLimit); parts = new ArrayList<>(); + List items = null; try { - List items = upload.parseRequest(new ServletRequestContext(this)); + items = upload.parseRequest(new ServletRequestContext(this)); int maxPostSize = getConnector().getMaxPostSize(); - int postSize = 0; + long postSize = 0; Charset charset = getCharset(); for (FileItem item : items) { ApplicationPart part = new ApplicationPart(item, location); - parts.add(part); if (part.getSubmittedFileName() == null) { String name = part.getName(); if (maxPostSize >= 0) { // Have to calculate equivalent size. Not completely // accurate but close enough. - postSize += name.getBytes(charset).length; + // Name + postSize = Math.addExact(postSize, name.getBytes(charset).length); // Equals sign - postSize++; + postSize = Math.addExact(postSize, 1); // Value length - postSize += part.getSize(); + postSize = Math.addExact(postSize, part.getSize()); // Value separator - postSize++; + postSize = Math.addExact(postSize, 1); if (postSize > maxPostSize) { parameters.setParseFailedReason(FailReason.POST_TOO_LARGE); throw new IllegalStateException(sm.getString("coyoteRequest.maxPostSizeExceeded")); @@ -2612,24 +2703,46 @@ // Not possible } parameters.addParameter(name, value); + } else { + // Adjust the limit to account for a file part which is not added to the parameter map. + maxParameterCount--; } + parts.add(part); } success = true; } catch (InvalidContentTypeException e) { parameters.setParseFailedReason(FailReason.INVALID_CONTENT_TYPE); partsParseException = new ServletException(e); - } catch (SizeException e) { + } catch (SizeException | FileCountLimitExceededException e) { parameters.setParseFailedReason(FailReason.POST_TOO_LARGE); checkSwallowInput(); partsParseException = new IllegalStateException(e); - } catch (IOException e) { + } catch (IOException ioe) { parameters.setParseFailedReason(FailReason.IO_ERROR); - partsParseException = e; + partsParseException = ioe; } catch (IllegalStateException e) { // addParameters() will set parseFailedReason checkSwallowInput(); partsParseException = e; + } finally { + /* + * GC will delete any temporary copies of uploaded files left in the work directory but if we know that + * the upload has failed then explicitly clean up now. + */ + if (!success) { + parts.clear(); + if (items != null) { + for (FileItem item : items) { + try { + item.delete(); + } catch (Throwable t) { + ExceptionUtils.handleThrowable(t); + log.warn(sm.getString("request.partCleanup.failed"), t); + } + } + } + } } } finally { // This might look odd but is correct. setParseFailedReason() only @@ -2680,11 +2793,11 @@ if (requestedSessionId != null) { try { session = manager.findSession(requestedSessionId); - } catch (IOException e) { + } catch (IOException ioe) { if (log.isDebugEnabled()) { - log.debug(sm.getString("request.session.failed", requestedSessionId, e.getMessage()), e); + log.debug(sm.getString("request.session.failed", requestedSessionId, ioe.getMessage()), ioe); } else { - log.info(sm.getString("request.session.failed", requestedSessionId, e.getMessage())); + log.info(sm.getString("request.session.failed", requestedSessionId, ioe.getMessage())); } session = null; } @@ -2693,6 +2806,8 @@ } if (session != null) { session.access(); + // The client has chosen to join the session + session.setNew(false); return session; } } @@ -2733,9 +2848,8 @@ found = true; break; } - } catch (IOException e) { - // Ignore. Problems with this manager will be - // handled elsewhere. + } catch (IOException ignore) { + // Error looking up session. Treat it as not found. } } } @@ -2845,7 +2959,7 @@ scookie.getValue().getByteChunk().setCharset(getCookieProcessor().getCharset()); cookie.setValue(unescape(scookie.getValue().toString())); cookies[idx++] = cookie; - } catch (IllegalArgumentException e) { + } catch (IllegalArgumentException ignore) { // Ignore bad cookie } } @@ -2864,14 +2978,30 @@ parametersParsed = true; + /* + * When the request body is multipart/form-data, both the parts and the query string count towards + * maxParameterCount. If parseParts() is called before getParameterXXX() then the parts will be parsed before + * the query string. Otherwise, the query string will be parsed first. + * + * maxParameterCount must be respected regardless of which is parsed first. + * + * maxParameterCount is reset from the Connector at the start of every request. + * + * If parts are parsed first, non-file parts will be added to the parameter map and any files will reduce + * maxParameterCount by 1 so that when the query string is parsed the difference between the size of the + * parameter map and maxParameterCount will be the original maxParameterCount less the number of parts. i.e. the + * maxParameterCount applied to the query string will be the original maxParameterCount less the number of + * parts. + * + * If the query string is parsed first, all parameters will be added to the parameter map and, ignoring + * maxPartCount, the part limit will be set to the original maxParameterCount less the size of the parameter + * map. i.e. the maxParameterCount applied to the parts will be the original maxParameterCount less the number + * of query parameters. + */ Parameters parameters = coyoteRequest.getParameters(); boolean success = false; try { // Set this every time in case limit has been changed via JMX - int maxParameterCount = getConnector().getMaxParameterCount(); - if (parts != null && maxParameterCount > 0) { - maxParameterCount -= parts.size(); - } parameters.setLimit(maxParameterCount); // getCharacterEncoding() may have been overridden to search for @@ -2935,17 +3065,18 @@ } try { readPostBodyFully(formData, len); - } catch (IOException e) { + } catch (IOException ioe) { // Client disconnect Context context = getContext(); if (context != null && context.getLogger().isDebugEnabled()) { - context.getLogger().debug(sm.getString("coyoteRequest.parseParameters"), e); + context.getLogger().debug(sm.getString("coyoteRequest.parseParameters"), ioe); } parameters.setParseFailedReason(FailReason.CLIENT_DISCONNECT); return; } parameters.processParameters(formData, 0, len); - } else if ("chunked".equalsIgnoreCase(coyoteRequest.getHeader("transfer-encoding"))) { + } else if (coyoteRequest.protocol().equals("HTTP/2.0") || + "chunked".equalsIgnoreCase(coyoteRequest.getHeader("transfer-encoding"))) { byte[] formData = null; try { formData = readChunkedPostBody(); @@ -2957,12 +3088,12 @@ context.getLogger().debug(sm.getString("coyoteRequest.parseParameters"), ise); } return; - } catch (IOException e) { + } catch (IOException ioe) { // Client disconnect parameters.setParseFailedReason(FailReason.CLIENT_DISCONNECT); Context context = getContext(); if (context != null && context.getLogger().isDebugEnabled()) { - context.getLogger().debug(sm.getString("coyoteRequest.parseParameters"), e); + context.getLogger().debug(sm.getString("coyoteRequest.parseParameters"), ioe); } return; } @@ -3107,7 +3238,7 @@ List acceptLanguages; try { acceptLanguages = AcceptLanguage.parse(new StringReader(value)); - } catch (IOException e) { + } catch (IOException ioe) { // Mal-formed headers are ignore. Do the same in the unlikely event // of an IOException. return; diff -Nru tomcat10-10.1.40/java/org/apache/catalina/connector/RequestFacade.java tomcat10-10.1.52/java/org/apache/catalina/connector/RequestFacade.java --- tomcat10-10.1.40/java/org/apache/catalina/connector/RequestFacade.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/connector/RequestFacade.java 2026-01-23 19:33:36.000000000 +0000 @@ -49,9 +49,6 @@ /** * Facade class that wraps a Coyote request object. All methods are delegated to the wrapped request. - * - * @author Craig R. McClanahan - * @author Remy Maucherat */ public class RequestFacade implements HttpServletRequest { diff -Nru tomcat10-10.1.40/java/org/apache/catalina/connector/Response.java tomcat10-10.1.52/java/org/apache/catalina/connector/Response.java --- tomcat10-10.1.40/java/org/apache/catalina/connector/Response.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/connector/Response.java 2026-01-23 19:33:36.000000000 +0000 @@ -67,9 +67,6 @@ /** * Wrapper object for the Coyote response. - * - * @author Remy Maucherat - * @author Craig R. McClanahan */ public class Response implements HttpServletResponse { @@ -1404,8 +1401,8 @@ redirectURLCC.append(':'); redirectURLCC.append(location, 0, location.length()); return redirectURLCC.toString(); - } catch (IOException e) { - throw new IllegalArgumentException(location, e); + } catch (IOException ioe) { + throw new IllegalArgumentException(location, ioe); } } else if (leadingSlash || !UriUtil.hasScheme(location)) { @@ -1446,8 +1443,8 @@ redirectURLCC.append(location, 0, location.length()); normalize(redirectURLCC); - } catch (IOException e) { - throw new IllegalArgumentException(location, e); + } catch (IOException ioe) { + throw new IllegalArgumentException(location, ioe); } return redirectURLCC.toString(); @@ -1481,8 +1478,8 @@ if (cc.endsWith("/.") || cc.endsWith("/..")) { try { cc.append('/'); - } catch (IOException e) { - throw new IllegalArgumentException(cc.toString(), e); + } catch (IOException ioe) { + throw new IllegalArgumentException(cc.toString(), ioe); } } diff -Nru tomcat10-10.1.40/java/org/apache/catalina/connector/ResponseFacade.java tomcat10-10.1.52/java/org/apache/catalina/connector/ResponseFacade.java --- tomcat10-10.1.40/java/org/apache/catalina/connector/ResponseFacade.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/connector/ResponseFacade.java 2026-01-23 19:33:36.000000000 +0000 @@ -37,8 +37,6 @@ /** * Facade class that wraps a Coyote response object. All methods are delegated to the wrapped response. - * - * @author Remy Maucherat */ public class ResponseFacade implements HttpServletResponse { diff -Nru tomcat10-10.1.40/java/org/apache/catalina/core/ApplicationContext.java tomcat10-10.1.52/java/org/apache/catalina/core/ApplicationContext.java --- tomcat10-10.1.40/java/org/apache/catalina/core/ApplicationContext.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/core/ApplicationContext.java 2026-01-23 19:33:36.000000000 +0000 @@ -83,9 +83,6 @@ /** * Standard implementation of ServletContext that represents a web application's execution environment. An * instance of this class is associated with each instance of StandardContext. - * - * @author Craig R. McClanahan - * @author Remy Maucherat */ public class ApplicationContext implements ServletContext { @@ -374,7 +371,7 @@ // From this point, the removal of path parameters, decoding and normalization is only for mapping purposes. // Remove path parameters - String uriToMap = stripPathParams(uri); + String uriToMap = org.apache.catalina.util.RequestUtil.stripPathParams(uri, null); // Decode only if the uri derived from the provided path is expected to be encoded if (getContext().getDispatchersUseEncodedPaths()) { @@ -449,34 +446,6 @@ } - // Package private to facilitate testing - static String stripPathParams(String input) { - // Shortcut - if (input.indexOf(';') < 0) { - return input; - } - - StringBuilder sb = new StringBuilder(input.length()); - int pos = 0; - int limit = input.length(); - while (pos < limit) { - int nextSemiColon = input.indexOf(';', pos); - if (nextSemiColon < 0) { - nextSemiColon = limit; - } - sb.append(input, pos, nextSemiColon); - int followingSlash = input.indexOf('/', nextSemiColon); - if (followingSlash < 0) { - pos = limit; - } else { - pos = followingSlash; - } - } - - return sb.toString(); - } - - @Override public URL getResource(String path) throws MalformedURLException { diff -Nru tomcat10-10.1.40/java/org/apache/catalina/core/ApplicationContextFacade.java tomcat10-10.1.52/java/org/apache/catalina/core/ApplicationContextFacade.java --- tomcat10-10.1.40/java/org/apache/catalina/core/ApplicationContextFacade.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/core/ApplicationContextFacade.java 2026-01-23 19:33:36.000000000 +0000 @@ -51,8 +51,6 @@ /** * Facade object which masks the internal ApplicationContext object from the web application. - * - * @author Remy Maucherat */ public class ApplicationContextFacade implements ServletContext { diff -Nru tomcat10-10.1.40/java/org/apache/catalina/core/ApplicationDispatcher.java tomcat10-10.1.52/java/org/apache/catalina/core/ApplicationDispatcher.java --- tomcat10-10.1.40/java/org/apache/catalina/core/ApplicationDispatcher.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/core/ApplicationDispatcher.java 2026-01-23 19:33:36.000000000 +0000 @@ -56,8 +56,6 @@ * resource. This implementation allows application level servlets to wrap the request and/or response objects that are * passed on to the called resource, as long as the wrapping classes extend * jakarta.servlet.ServletRequestWrapper and jakarta.servlet.ServletResponseWrapper. - * - * @author Craig R. McClanahan */ final class ApplicationDispatcher implements AsyncDispatcher, RequestDispatcher { @@ -364,7 +362,7 @@ } catch (IllegalStateException | IOException f) { // Ignore } - } catch (IOException e) { + } catch (IOException ignore) { // Ignore } } @@ -594,11 +592,11 @@ wrapper.getLogger().error(sm.getString("applicationDispatcher.allocateException", wrapper.getName()), StandardWrapper.getRootCause(e)); servletException = e; - } catch (Throwable e) { - ExceptionUtils.handleThrowable(e); - wrapper.getLogger().error(sm.getString("applicationDispatcher.allocateException", wrapper.getName()), e); + } catch (Throwable t) { + ExceptionUtils.handleThrowable(t); + wrapper.getLogger().error(sm.getString("applicationDispatcher.allocateException", wrapper.getName()), t); servletException = - new ServletException(sm.getString("applicationDispatcher.allocateException", wrapper.getName()), e); + new ServletException(sm.getString("applicationDispatcher.allocateException", wrapper.getName()), t); // servlet = null; is already done so no need to do it explicitly } @@ -614,9 +612,9 @@ // Servlet Service Method is called by the FilterChain } catch (BadRequestException | CloseNowException e) { ioException = e; - } catch (IOException e) { - wrapper.getLogger().error(sm.getString("applicationDispatcher.serviceException", wrapper.getName()), e); - ioException = e; + } catch (IOException ioe) { + wrapper.getLogger().error(sm.getString("applicationDispatcher.serviceException", wrapper.getName()), ioe); + ioException = ioe; } catch (UnavailableException e) { wrapper.getLogger().error(sm.getString("applicationDispatcher.serviceException", wrapper.getName()), e); servletException = e; @@ -646,11 +644,11 @@ } catch (ServletException e) { wrapper.getLogger().error(sm.getString("applicationDispatcher.deallocateException", wrapper.getName()), e); servletException = e; - } catch (Throwable e) { - ExceptionUtils.handleThrowable(e); - wrapper.getLogger().error(sm.getString("applicationDispatcher.deallocateException", wrapper.getName()), e); + } catch (Throwable t) { + ExceptionUtils.handleThrowable(t); + wrapper.getLogger().error(sm.getString("applicationDispatcher.deallocateException", wrapper.getName()), t); servletException = new ServletException( - sm.getString("applicationDispatcher.deallocateException", wrapper.getName()), e); + sm.getString("applicationDispatcher.deallocateException", wrapper.getName()), t); } // Reset the old context class loader diff -Nru tomcat10-10.1.40/java/org/apache/catalina/core/ApplicationFilterChain.java tomcat10-10.1.52/java/org/apache/catalina/core/ApplicationFilterChain.java --- tomcat10-10.1.40/java/org/apache/catalina/core/ApplicationFilterChain.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/core/ApplicationFilterChain.java 2026-01-23 19:33:36.000000000 +0000 @@ -40,8 +40,6 @@ * Implementation of jakarta.servlet.FilterChain used to manage the execution of a set of filters for a * particular request. When the set of defined filters has all been executed, the next call to doFilter() * will execute the servlet's service() method itself. - * - * @author Craig R. McClanahan */ public final class ApplicationFilterChain implements FilterChain { @@ -165,10 +163,10 @@ } } catch (IOException | ServletException | RuntimeException e) { throw e; - } catch (Throwable e) { - e = ExceptionUtils.unwrapInvocationTargetException(e); - ExceptionUtils.handleThrowable(e); - throw new ServletException(sm.getString("filterChain.filter"), e); + } catch (Throwable t) { + t = ExceptionUtils.unwrapInvocationTargetException(t); + ExceptionUtils.handleThrowable(t); + throw new ServletException(sm.getString("filterChain.filter"), t); } return; } @@ -196,10 +194,10 @@ } } catch (IOException | ServletException | RuntimeException e) { throw e; - } catch (Throwable e) { - e = ExceptionUtils.unwrapInvocationTargetException(e); - ExceptionUtils.handleThrowable(e); - throw new ServletException(sm.getString("filterChain.servlet"), e); + } catch (Throwable t) { + t = ExceptionUtils.unwrapInvocationTargetException(t); + ExceptionUtils.handleThrowable(t); + throw new ServletException(sm.getString("filterChain.servlet"), t); } finally { if (dispatcherWrapsSameObject) { lastServicedRequest.set(null); diff -Nru tomcat10-10.1.40/java/org/apache/catalina/core/ApplicationFilterConfig.java tomcat10-10.1.52/java/org/apache/catalina/core/ApplicationFilterConfig.java --- tomcat10-10.1.40/java/org/apache/catalina/core/ApplicationFilterConfig.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/core/ApplicationFilterConfig.java 2026-01-23 19:33:36.000000000 +0000 @@ -49,8 +49,6 @@ /** * Implementation of a jakarta.servlet.FilterConfig useful in managing the filter instances instantiated * when a web application is first started. - * - * @author Craig R. McClanahan */ public final class ApplicationFilterConfig implements FilterConfig, Serializable { @@ -179,11 +177,8 @@ @Override public String toString() { - return "ApplicationFilterConfig[" + "name=" + - filterDef.getFilterName() + - ", filterClass=" + - filterDef.getFilterClass() + - ']'; + return "ApplicationFilterConfig[" + "name=" + filterDef.getFilterName() + ", filterClass=" + + filterDef.getFilterClass() + ']'; } // --------------------------------------------------------- Public Methods @@ -323,8 +318,8 @@ try { oname = new ObjectName(onameStr); Registry.getRegistry(null).registerComponent(this, oname, null); - } catch (Exception ex) { - log.warn(sm.getString("applicationFilterConfig.jmxRegisterFail", getFilterClass(), getFilterName()), ex); + } catch (Exception e) { + log.warn(sm.getString("applicationFilterConfig.jmxRegisterFail", getFilterClass(), getFilterName()), e); } } @@ -337,9 +332,9 @@ if (log.isDebugEnabled()) { log.debug(sm.getString("applicationFilterConfig.jmxUnregister", getFilterClass(), getFilterName())); } - } catch (Exception ex) { + } catch (Exception e) { log.warn(sm.getString("applicationFilterConfig.jmxUnregisterFail", getFilterClass(), getFilterName()), - ex); + e); } } } diff -Nru tomcat10-10.1.40/java/org/apache/catalina/core/ApplicationFilterFactory.java tomcat10-10.1.52/java/org/apache/catalina/core/ApplicationFilterFactory.java --- tomcat10-10.1.40/java/org/apache/catalina/core/ApplicationFilterFactory.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/core/ApplicationFilterFactory.java 2026-01-23 19:33:36.000000000 +0000 @@ -31,9 +31,6 @@ /** * Factory for the creation and caching of Filters and creation of Filter Chains. - * - * @author Greg Murray - * @author Remy Maucherat */ public final class ApplicationFilterFactory { diff -Nru tomcat10-10.1.40/java/org/apache/catalina/core/ApplicationHttpRequest.java tomcat10-10.1.52/java/org/apache/catalina/core/ApplicationHttpRequest.java --- tomcat10-10.1.40/java/org/apache/catalina/core/ApplicationHttpRequest.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/core/ApplicationHttpRequest.java 2026-01-23 19:33:36.000000000 +0000 @@ -63,9 +63,6 @@ * WARNING: Due to Java's lack of support for multiple inheritance, all of the logic in * ApplicationRequest is duplicated in ApplicationHttpRequest. Make sure that you keep these * two classes in synchronization when making changes! - * - * @author Craig R. McClanahan - * @author Remy Maucherat */ class ApplicationHttpRequest extends HttpServletRequestWrapper { @@ -550,7 +547,7 @@ if (localSession != null && !localSession.isValid()) { localSession = null; } - } catch (IOException e) { + } catch (IOException ignore) { // Ignore } if (localSession == null && create) { @@ -596,7 +593,7 @@ Session session = null; try { session = manager.findSession(requestedSessionId); - } catch (IOException e) { + } catch (IOException ignore) { // Ignore } return (session != null) && session.isValid(); diff -Nru tomcat10-10.1.40/java/org/apache/catalina/core/ApplicationHttpResponse.java tomcat10-10.1.52/java/org/apache/catalina/core/ApplicationHttpResponse.java --- tomcat10-10.1.40/java/org/apache/catalina/core/ApplicationHttpResponse.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/core/ApplicationHttpResponse.java 2026-01-23 19:33:36.000000000 +0000 @@ -33,8 +33,6 @@ * WARNING: Due to Java's lack of support for multiple inheritance, all of the logic in * ApplicationResponse is duplicated in ApplicationHttpResponse. Make sure that you keep these * two classes in synchronization when making changes! - * - * @author Craig R. McClanahan */ class ApplicationHttpResponse extends HttpServletResponseWrapper { diff -Nru tomcat10-10.1.40/java/org/apache/catalina/core/ApplicationPushBuilder.java tomcat10-10.1.52/java/org/apache/catalina/core/ApplicationPushBuilder.java --- tomcat10-10.1.40/java/org/apache/catalina/core/ApplicationPushBuilder.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/core/ApplicationPushBuilder.java 2026-01-23 19:33:36.000000000 +0000 @@ -293,7 +293,7 @@ org.apache.coyote.Request pushTarget = new org.apache.coyote.Request(); - pushTarget.method().setString(method); + pushTarget.setMethod(method); // The next three are implied by the Javadoc getPath() pushTarget.serverName().setString(baseRequest.getServerName()); pushTarget.setServerPort(baseRequest.getServerPort()); diff -Nru tomcat10-10.1.40/java/org/apache/catalina/core/ApplicationRequest.java tomcat10-10.1.52/java/org/apache/catalina/core/ApplicationRequest.java --- tomcat10-10.1.40/java/org/apache/catalina/core/ApplicationRequest.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/core/ApplicationRequest.java 2026-01-23 19:33:36.000000000 +0000 @@ -36,8 +36,6 @@ * WARNING: Due to Java's lack of support for multiple inheritance, all of the logic in * ApplicationRequest is duplicated in ApplicationHttpRequest. Make sure that you keep these * two classes in synchronization when making changes! - * - * @author Craig R. McClanahan */ class ApplicationRequest extends ServletRequestWrapper { @@ -59,8 +57,7 @@ */ private static final Set specialsSet = new HashSet<>(Arrays.asList(specials)); - private static final int shortestSpecialNameLength = - specialsSet.stream().mapToInt(String::length).min().getAsInt(); + private static final int shortestSpecialNameLength = specialsSet.stream().mapToInt(String::length).min().getAsInt(); /** diff -Nru tomcat10-10.1.40/java/org/apache/catalina/core/ApplicationResponse.java tomcat10-10.1.52/java/org/apache/catalina/core/ApplicationResponse.java --- tomcat10-10.1.40/java/org/apache/catalina/core/ApplicationResponse.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/core/ApplicationResponse.java 2026-01-23 19:33:36.000000000 +0000 @@ -31,8 +31,6 @@ * WARNING: Due to Java's lack of support for multiple inheritance, all of the logic in * ApplicationResponse is duplicated in ApplicationHttpResponse. Make sure that you keep these * two classes in synchronization when making changes! - * - * @author Craig R. McClanahan */ class ApplicationResponse extends ServletResponseWrapper { diff -Nru tomcat10-10.1.40/java/org/apache/catalina/core/AprLifecycleListener.java tomcat10-10.1.52/java/org/apache/catalina/core/AprLifecycleListener.java --- tomcat10-10.1.40/java/org/apache/catalina/core/AprLifecycleListener.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/core/AprLifecycleListener.java 2026-01-23 19:33:36.000000000 +0000 @@ -19,6 +19,7 @@ import java.lang.reflect.Method; import java.util.ArrayList; import java.util.List; +import java.util.concurrent.locks.Lock; import org.apache.catalina.Lifecycle; import org.apache.catalina.LifecycleEvent; @@ -63,12 +64,17 @@ // ---------------------------------------------- Constants - protected static final int TCN_REQUIRED_MAJOR = 1; - protected static final int TCN_REQUIRED_MINOR = 2; - protected static final int TCN_REQUIRED_PATCH = 34; + private static final int TCN_1_REQUIRED_MINOR = 3; + private static final int TCN_1_REQUIRED_PATCH = 4; + private static final int TCN_1_RECOMMENDED_MINOR = 3; + private static final int TCN_1_RECOMMENDED_PATCH = 4; + + protected static final int TCN_REQUIRED_MAJOR = 2; + protected static final int TCN_REQUIRED_MINOR = 0; + protected static final int TCN_REQUIRED_PATCH = 12; protected static final int TCN_RECOMMENDED_MAJOR = 2; protected static final int TCN_RECOMMENDED_MINOR = 0; - protected static final int TCN_RECOMMENDED_PV = 5; + protected static final int TCN_RECOMMENDED_PV = 12; // ---------------------------------------------- Properties @@ -99,25 +105,27 @@ private static final int FIPS_OFF = 0; - protected static final Object lock = new Object(); - - // Guarded by lock + // Guarded APRStatus.getStatusLock() private static int referenceCount = 0; private boolean instanceInitialized = false; public static boolean isAprAvailable() { // https://bz.apache.org/bugzilla/show_bug.cgi?id=48613 - if (AprStatus.isInstanceCreated()) { - synchronized (lock) { + if (org.apache.tomcat.jni.AprStatus.isInstanceCreated()) { + Lock writeLock = org.apache.tomcat.jni.AprStatus.getStatusLock().writeLock(); + writeLock.lock(); + try { init(); + } finally { + writeLock.unlock(); } } - return AprStatus.isAprAvailable(); + return org.apache.tomcat.jni.AprStatus.isAprAvailable(); } public AprLifecycleListener() { - AprStatus.setInstanceCreated(true); + org.apache.tomcat.jni.AprStatus.setInstanceCreated(true); } // ---------------------------------------------- LifecycleListener Methods @@ -131,7 +139,9 @@ public void lifecycleEvent(LifecycleEvent event) { if (Lifecycle.BEFORE_INIT_EVENT.equals(event.getType())) { - synchronized (lock) { + Lock writeLock = org.apache.tomcat.jni.AprStatus.getStatusLock().writeLock(); + writeLock.lock(); + try { instanceInitialized = true; if (!(event.getLifecycle() instanceof Server)) { log.warn(sm.getString("listener.notServer", event.getLifecycle().getClass().getSimpleName())); @@ -145,7 +155,7 @@ log.info(msg); } initInfoLogMessages.clear(); - if (AprStatus.isAprAvailable()) { + if (org.apache.tomcat.jni.AprStatus.isAprAvailable()) { try { initializeSSL(); } catch (Throwable t) { @@ -156,15 +166,18 @@ } // Failure to initialize FIPS mode is fatal if (!(null == FIPSMode || "off".equalsIgnoreCase(FIPSMode)) && !isFIPSModeActive()) { - String errorMessage = sm.getString("aprListener.initializeFIPSFailed"); - Error e = new Error(errorMessage); + Error e = new Error(sm.getString("aprListener.initializeFIPSFailed")); // Log here, because thrown error might be not logged - log.fatal(errorMessage, e); + log.fatal(e.getMessage(), e); throw e; } + } finally { + writeLock.unlock(); } } else if (Lifecycle.AFTER_DESTROY_EVENT.equals(event.getType())) { - synchronized (lock) { + Lock writeLock = org.apache.tomcat.jni.AprStatus.getStatusLock().writeLock(); + writeLock.lock(); + try { // Instance may get destroyed without ever being initialized if (instanceInitialized) { referenceCount--; @@ -173,7 +186,7 @@ // Still being used return; } - if (!AprStatus.isAprAvailable()) { + if (!org.apache.tomcat.jni.AprStatus.isAprAvailable()) { return; } try { @@ -181,16 +194,18 @@ } catch (Throwable t) { Throwable throwable = ExceptionUtils.unwrapInvocationTargetException(t); ExceptionUtils.handleThrowable(throwable); - log.info(sm.getString("aprListener.aprDestroy")); + log.warn(sm.getString("aprListener.aprDestroy"), throwable); } + } finally { + writeLock.unlock(); } } } private static void terminateAPR() { - AprStatus.setAprInitialized(false); - AprStatus.setAprAvailable(false); + org.apache.tomcat.jni.AprStatus.setAprInitialized(false); + org.apache.tomcat.jni.AprStatus.setAprAvailable(false); fipsModeActive = false; sslInitialized = false; // terminate() will clean the pool // There could be unreferenced SSL_CTX still waiting for GC @@ -199,13 +214,10 @@ } private static void init() { - int rqver = TCN_REQUIRED_MAJOR * 1000 + TCN_REQUIRED_MINOR * 100 + TCN_REQUIRED_PATCH; - int rcver = TCN_RECOMMENDED_MAJOR * 1000 + TCN_RECOMMENDED_MINOR * 100 + TCN_RECOMMENDED_PV; - - if (AprStatus.isAprInitialized()) { + if (org.apache.tomcat.jni.AprStatus.isAprInitialized()) { return; } - AprStatus.setAprInitialized(true); + org.apache.tomcat.jni.AprStatus.setAprInitialized(true); try { Library.initialize(null); @@ -239,9 +251,34 @@ } return; } + + /* + * With parallel development of 1.x and 2.x there are now minimum and recommended versions for both branches. + * + * The minimum required version is increased when the Tomcat Native API is changed (typically extended) to + * include functionality that Tomcat expects to always be present. + * + * The minimum recommended version is increased when there is a change in Tomcat Native that while not required + * is recommended (such as bug fixes). + */ + int rqver; + int rcver; + if (tcnMajor == 1) { + rqver = 1000 + TCN_1_REQUIRED_MINOR * 100 + TCN_1_REQUIRED_PATCH; + rcver = 1000 + TCN_1_RECOMMENDED_MINOR * 100 + TCN_1_RECOMMENDED_PATCH; + } else { + rqver = TCN_REQUIRED_MAJOR * 1000 + TCN_REQUIRED_MINOR * 100 + TCN_REQUIRED_PATCH; + rcver = TCN_RECOMMENDED_MAJOR * 1000 + TCN_RECOMMENDED_MINOR * 100 + TCN_RECOMMENDED_PV; + } + if (tcnVersion < rqver) { - log.error(sm.getString("aprListener.tcnInvalid", Library.versionString(), - TCN_REQUIRED_MAJOR + "." + TCN_REQUIRED_MINOR + "." + TCN_REQUIRED_PATCH)); + if (tcnMajor == 1) { + log.error(sm.getString("aprListener.tcnInvalid.1", Library.versionString(), + "1." + TCN_1_REQUIRED_MINOR + "." + TCN_1_REQUIRED_PATCH)); + } else { + log.error(sm.getString("aprListener.tcnInvalid", Library.versionString(), + TCN_REQUIRED_MAJOR + "." + TCN_REQUIRED_MINOR + "." + TCN_REQUIRED_PATCH)); + } try { // Terminate the APR in case the version // is below required. @@ -253,14 +290,19 @@ return; } if (tcnVersion < rcver) { - initInfoLogMessages.add(sm.getString("aprListener.tcnVersion", Library.versionString(), - TCN_RECOMMENDED_MAJOR + "." + TCN_RECOMMENDED_MINOR + "." + TCN_RECOMMENDED_PV)); + if (tcnMajor == 1) { + initInfoLogMessages.add(sm.getString("aprListener.tcnVersion.1", Library.versionString(), + "1." + TCN_1_RECOMMENDED_MINOR + "." + TCN_1_RECOMMENDED_PATCH)); + } else { + initInfoLogMessages.add(sm.getString("aprListener.tcnVersion", Library.versionString(), + TCN_RECOMMENDED_MAJOR + "." + TCN_RECOMMENDED_MINOR + "." + TCN_RECOMMENDED_PV)); + } } initInfoLogMessages .add(sm.getString("aprListener.tcnValid", Library.versionString(), Library.aprVersionString())); - AprStatus.setAprAvailable(true); + org.apache.tomcat.jni.AprStatus.setAprAvailable(true); } private static void initializeSSL() throws Exception { @@ -290,7 +332,7 @@ method = clazz.getMethod(methodName, paramTypes); method.invoke(null, paramValues); - AprStatus.setOpenSSLVersion(SSL.version()); + org.apache.tomcat.jni.AprStatus.setOpenSSLVersion(SSL.version()); // OpenSSL 3 onwards uses providers boolean usingProviders = tcnMajor > 1 || (tcnVersion > 1233 && (SSL.version() & 0xF0000000L) > 0x20000000); @@ -430,17 +472,17 @@ } public void setUseOpenSSL(boolean useOpenSSL) { - if (useOpenSSL != AprStatus.getUseOpenSSL()) { - AprStatus.setUseOpenSSL(useOpenSSL); + if (useOpenSSL != org.apache.tomcat.jni.AprStatus.getUseOpenSSL()) { + org.apache.tomcat.jni.AprStatus.setUseOpenSSL(useOpenSSL); } } public static boolean getUseOpenSSL() { - return AprStatus.getUseOpenSSL(); + return org.apache.tomcat.jni.AprStatus.getUseOpenSSL(); } public static boolean isInstanceCreated() { - return AprStatus.isInstanceCreated(); + return org.apache.tomcat.jni.AprStatus.isInstanceCreated(); } } diff -Nru tomcat10-10.1.40/java/org/apache/catalina/core/AprStatus.java tomcat10-10.1.52/java/org/apache/catalina/core/AprStatus.java --- tomcat10-10.1.40/java/org/apache/catalina/core/AprStatus.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/core/AprStatus.java 2026-01-23 19:33:36.000000000 +0000 @@ -18,58 +18,56 @@ /** * Holds APR status without the need to load other classes. + * + * @deprecated Unused. Use {@link org.apache.tomcat.jni.AprStatus} instead. This class will be removed in Tomcat 12 + * onwards. */ +@Deprecated public class AprStatus { - private static volatile boolean aprInitialized = false; - private static volatile boolean aprAvailable = false; - private static volatile boolean useOpenSSL = true; - private static volatile boolean instanceCreated = false; - private static volatile int openSSLVersion = 0; public static boolean isAprInitialized() { - return aprInitialized; + return org.apache.tomcat.jni.AprStatus.isAprInitialized(); } public static boolean isAprAvailable() { - return aprAvailable; + return org.apache.tomcat.jni.AprStatus.isAprAvailable(); } public static boolean getUseOpenSSL() { - return useOpenSSL; + return org.apache.tomcat.jni.AprStatus.getUseOpenSSL(); } public static boolean isInstanceCreated() { - return instanceCreated; + return org.apache.tomcat.jni.AprStatus.isInstanceCreated(); } public static void setAprInitialized(boolean aprInitialized) { - AprStatus.aprInitialized = aprInitialized; + org.apache.tomcat.jni.AprStatus.setAprInitialized(aprInitialized); } public static void setAprAvailable(boolean aprAvailable) { - AprStatus.aprAvailable = aprAvailable; + org.apache.tomcat.jni.AprStatus.setAprAvailable(aprAvailable); } public static void setUseOpenSSL(boolean useOpenSSL) { - AprStatus.useOpenSSL = useOpenSSL; + org.apache.tomcat.jni.AprStatus.setUseOpenSSL(useOpenSSL); } public static void setInstanceCreated(boolean instanceCreated) { - AprStatus.instanceCreated = instanceCreated; + org.apache.tomcat.jni.AprStatus.setInstanceCreated(instanceCreated); } /** * @return the openSSLVersion */ public static int getOpenSSLVersion() { - return openSSLVersion; + return org.apache.tomcat.jni.AprStatus.getOpenSSLVersion(); } /** * @param openSSLVersion the openSSLVersion to set */ public static void setOpenSSLVersion(int openSSLVersion) { - AprStatus.openSSLVersion = openSSLVersion; + org.apache.tomcat.jni.AprStatus.setOpenSSLVersion(openSSLVersion); } - } diff -Nru tomcat10-10.1.40/java/org/apache/catalina/core/ContainerBase.java tomcat10-10.1.52/java/org/apache/catalina/core/ContainerBase.java --- tomcat10-10.1.40/java/org/apache/catalina/core/ContainerBase.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/core/ContainerBase.java 2026-01-23 19:33:36.000000000 +0000 @@ -118,8 +118,6 @@ *
    *
    Examples of Returned Values
    * Subclasses that fire additional events should document them in the class comments of the implementation class. - * - * @author Craig R. McClanahan */ public abstract class ContainerBase extends LifecycleMBeanBase implements Container { @@ -754,12 +752,12 @@ for (Future result : results) { try { result.get(); - } catch (Throwable e) { - log.error(sm.getString("containerBase.threadedStartFailed"), e); + } catch (Throwable t) { + log.error(sm.getString("containerBase.threadedStartFailed"), t); if (multiThrowable == null) { multiThrowable = new MultiThrowable(); } - multiThrowable.add(e); + multiThrowable.add(t); } } diff -Nru tomcat10-10.1.40/java/org/apache/catalina/core/DefaultInstanceManager.java tomcat10-10.1.52/java/org/apache/catalina/core/DefaultInstanceManager.java --- tomcat10-10.1.40/java/org/apache/catalina/core/DefaultInstanceManager.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/core/DefaultInstanceManager.java 2026-01-23 19:33:36.000000000 +0000 @@ -189,8 +189,7 @@ } /** - * Call postConstruct method on the specified instance recursively from the deepest superclass - * to actual class. + * Call postConstruct method on the specified instance recursively from the deepest superclass to actual class. * * @param instance object to call postconstruct methods on * @param clazz (super) class to examine for postConstruct annotation. @@ -227,8 +226,7 @@ /** - * Call preDestroy method on the specified instance recursively from the deepest superclass - * to actual class. + * Call preDestroy method on the specified instance recursively from the deepest superclass to actual class. * * @param instance object to call preDestroy methods on * @param clazz (super) class to examine for preDestroy annotation. @@ -330,13 +328,11 @@ } else if (JPA_PRESENT && (persistenceContextAnnotation = method.getAnnotation(PersistenceContext.class)) != null) { annotations.add(new AnnotationCacheEntry(method.getName(), method.getParameterTypes(), - persistenceContextAnnotation.name(), - AnnotationCacheEntryType.SETTER)); + persistenceContextAnnotation.name(), AnnotationCacheEntryType.SETTER)); } else if (JPA_PRESENT && (persistenceUnitAnnotation = method.getAnnotation(PersistenceUnit.class)) != null) { annotations.add(new AnnotationCacheEntry(method.getName(), method.getParameterTypes(), - persistenceUnitAnnotation.name(), - AnnotationCacheEntryType.SETTER)); + persistenceUnitAnnotation.name(), AnnotationCacheEntryType.SETTER)); } } @@ -383,17 +379,15 @@ AnnotationCacheEntryType.FIELD)); } else if (WS_PRESENT && (webServiceRefAnnotation = field.getAnnotation(WebServiceRef.class)) != null) { - annotations.add(new AnnotationCacheEntry(fieldName, null, - webServiceRefAnnotation.name(), AnnotationCacheEntryType.FIELD)); + annotations.add(new AnnotationCacheEntry(fieldName, null, webServiceRefAnnotation.name(), + AnnotationCacheEntryType.FIELD)); } else if (JPA_PRESENT && (persistenceContextAnnotation = field.getAnnotation(PersistenceContext.class)) != null) { annotations.add(new AnnotationCacheEntry(fieldName, null, - persistenceContextAnnotation.name(), - AnnotationCacheEntryType.FIELD)); + persistenceContextAnnotation.name(), AnnotationCacheEntryType.FIELD)); } else if (JPA_PRESENT && (persistenceUnitAnnotation = field.getAnnotation(PersistenceUnit.class)) != null) { - annotations.add(new AnnotationCacheEntry(fieldName, null, - persistenceUnitAnnotation.name(), + annotations.add(new AnnotationCacheEntry(fieldName, null, persistenceUnitAnnotation.name(), AnnotationCacheEntryType.FIELD)); } } diff -Nru tomcat10-10.1.40/java/org/apache/catalina/core/JreMemoryLeakPreventionListener.java tomcat10-10.1.52/java/org/apache/catalina/core/JreMemoryLeakPreventionListener.java --- tomcat10-10.1.40/java/org/apache/catalina/core/JreMemoryLeakPreventionListener.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/core/JreMemoryLeakPreventionListener.java 2026-01-23 19:33:36.000000000 +0000 @@ -78,9 +78,9 @@ } /** - * The first access to {@link DriverManager} will trigger the loading of all {@link java.sql.Driver}s in the - * current class loader. The web application level memory leak protection can take care of this in most cases but - * triggering the loading here has fewer side effects. + * The first access to {@link DriverManager} will trigger the loading of all {@link java.sql.Driver}s in the current + * class loader. The web application level memory leak protection can take care of this in most cases but triggering + * the loading here has fewer side effects. */ private boolean driverManagerProtection = true; diff -Nru tomcat10-10.1.40/java/org/apache/catalina/core/LocalStrings.properties tomcat10-10.1.52/java/org/apache/catalina/core/LocalStrings.properties --- tomcat10-10.1.40/java/org/apache/catalina/core/LocalStrings.properties 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/core/LocalStrings.properties 2026-01-23 19:33:36.000000000 +0000 @@ -90,9 +90,11 @@ aprListener.skipFIPSInitialization=Already in FIPS mode; skipping FIPS initialization. aprListener.sslInit=Failed to initialize the SSLEngine. aprListener.sslRequired=[{0}] is not a valid value for SSLEngine when using version [{1}] of the Tomcat Native library since SSL is required for version 2.x onwards. -aprListener.tcnInvalid=An incompatible version [{0}] of the Apache Tomcat Native library is installed, while Tomcat requires version [{1}] +aprListener.tcnInvalid=An incompatible version [{0}] of the Apache Tomcat Native library is installed, while Tomcat requires at least version [{1}] +aprListener.tcnInvalid.1=An incompatible version [{0}] of the Apache Tomcat Native library is installed, while Tomcat requires at least version [{1}] of Tomcat Native 1.x aprListener.tcnValid=Loaded Apache Tomcat Native library [{0}] using APR version [{1}]. aprListener.tcnVersion=An older version [{0}] of the Apache Tomcat Native library is installed, while Tomcat recommends a minimum version of [{1}] +aprListener.tcnVersion.1=An older version [{0}] of the Apache Tomcat Native library is installed, while Tomcat recommends a minimum version of [{1}] of Tomcat Native 1.x aprListener.tooLateForFIPSMode=Cannot setFIPSMode: SSL has already been initialized aprListener.tooLateForSSLEngine=Cannot setSSLEngine: SSL has already been initialized aprListener.tooLateForSSLRandomSeed=Cannot setSSLRandomSeed: SSL has already been initialized @@ -276,7 +278,9 @@ standardHost.notContext=Child of a Host must be a Context standardHost.nullName=Host name is required standardHost.problematicAppBase=Using an empty string for appBase on host [{0}] will set it to CATALINA_BASE, which is a bad idea +standardHost.problematicAppBaseParent=appBase on host [{0}] is a parent folder of CATALINA_BASE, which is a bad idea standardHost.problematicLegacyAppBase=Using an empty string for legacyAppBase on host [{0}] will set it to CATALINA_BASE, which is a bad idea +standardHost.problematicLegacyAppBaseParent=legacyAppBase on host [{0}] is a parent folder of CATALINA_BASE, which is a bad idea standardHostValve.customStatusFailed=Custom error page [{0}] could not be dispatched correctly standardHostValve.exception=Exception Processing [{0}] diff -Nru tomcat10-10.1.40/java/org/apache/catalina/core/LocalStrings_ja.properties tomcat10-10.1.52/java/org/apache/catalina/core/LocalStrings_ja.properties --- tomcat10-10.1.40/java/org/apache/catalina/core/LocalStrings_ja.properties 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/core/LocalStrings_ja.properties 2026-01-23 19:33:36.000000000 +0000 @@ -276,7 +276,9 @@ standardHost.notContext=Host の子供はContextでなければいけません standardHost.nullName=ホスト名が必要です standardHost.problematicAppBase=ホスト [{0}] のappBaseに空の文字列を使用すると、CATALINA_BASEに設定されますが、これは悪い考えです +standardHost.problematicAppBaseParent=Host [{0}] の appBase は CATALINA_BASE の親フォルダですが、これは適切ではありません standardHost.problematicLegacyAppBase=ホスト [{0}] のlegacyAppBaseに空の文字列を使用すると、CATALINA_BASEに設定されます。これは悪い考えです +standardHost.problematicLegacyAppBaseParent=Host [{0}] の legacyAppBase は CATALINA_BASE の親フォルダですが、これは適切ではありません standardHostValve.customStatusFailed=カスタムエラーページ [{0}] を正しくディスパッチできませんでした standardHostValve.exception=例外処理 [{0}] diff -Nru tomcat10-10.1.40/java/org/apache/catalina/core/LocalStrings_ru.properties tomcat10-10.1.52/java/org/apache/catalina/core/LocalStrings_ru.properties --- tomcat10-10.1.40/java/org/apache/catalina/core/LocalStrings_ru.properties 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/core/LocalStrings_ru.properties 2026-01-23 19:33:36.000000000 +0000 @@ -28,17 +28,22 @@ applicationHttpRequest.sessionEndAccessFail=Исключение вызвало прекращение доступа к сессии при очистке запроса aprListener.initializingFIPS=Инициализируется режим FIPS... +aprListener.tcnVersion=Была обнаружена более старая версия [{0}] библиотеки Apache Tomcat Native, в то время как Tomcat рекомендует использовать как минимум версию [{1}] filterChain.filter=При выполнении фильтра выброшено исключение +naming.addEnvEntry=Добавляется переменная окружения [{0}] naming.unbindFailed=Ошибка при отвязывании объекта: [{0}] naming.wsdlFailed=wsdl файл не найден: [{0}] standardContext.filterStart=Ошибка при старте фильтра [{0}] standardContext.invalidWrapperClass=[{0}] не является подклассом StandardWrapper +standardContext.managerFail=Невозможно запустить менеджер сессий +standardContext.notStarted=Контекст с именем [{0}] ещё небыл запущен standardContext.parameter.duplicate=Дублированный параметр инициализации контекста [{0}] standardContext.predestroy.duplicate=Дублированное определение метода @PreDestroy для класса [{0}] standardContext.securityConstraint.mixHttpMethod=Запрещено смешивать и в одной и той же коллекции веб-ресурсов +standardContext.securityConstraint.pattern=Некорректный [{0}] в ограничении безопасности standardContext.startingContext=Ошибка запуска контекста с именем [{0}] standardWrapper.allocate=Ошибка при выделении экземпляра сервлета diff -Nru tomcat10-10.1.40/java/org/apache/catalina/core/NamingContextListener.java tomcat10-10.1.52/java/org/apache/catalina/core/NamingContextListener.java --- tomcat10-10.1.40/java/org/apache/catalina/core/NamingContextListener.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/core/NamingContextListener.java 2026-01-23 19:33:36.000000000 +0000 @@ -76,8 +76,6 @@ /** * Helper class used to initialize and populate the JNDI context associated with each context and server. - * - * @author Remy Maucherat */ public class NamingContextListener implements LifecycleListener, PropertyChangeListener { @@ -235,7 +233,7 @@ try { createNamingContext(); } catch (NamingException e) { - log.error(sm.getString("naming.namingContextCreationFailed", e)); + log.error(sm.getString("naming.namingContextCreationFailed", container), e); } namingResources.addPropertyChangeListener(this); @@ -248,7 +246,7 @@ ContextBindings.bindClassLoader(container, token, ((Context) container).getLoader().getClassLoader()); } catch (NamingException e) { - log.error(sm.getString("naming.bindFailed", e)); + log.error(sm.getString("naming.bindFailed", container), e); } } @@ -257,7 +255,7 @@ try { ContextBindings.bindClassLoader(container, token, this.getClass().getClassLoader()); } catch (NamingException e) { - log.error(sm.getString("naming.bindFailed", e)); + log.error(sm.getString("naming.bindFailed", container), e); } if (container instanceof StandardServer) { ((StandardServer) container).setGlobalNamingContext(namingContext); @@ -491,6 +489,13 @@ } else { compCtx = namingContext.createSubcontext("comp"); envCtx = compCtx.createSubcontext("env"); + /* + * Jakarta Platform Specification, 5.2.2: Application Component Environment Namespaces + * + * "java:module" and "java:comp" refer to the same namespace in a web module (i.e. a web application). + * Implement this by binding the "comp" sub-context we just created to the "module" name as well. + */ + namingContext.bind("module", compCtx); } int i; @@ -565,7 +570,7 @@ // Ignore because UserTransaction was obviously // added via ResourceLink } catch (NamingException e) { - log.error(sm.getString("naming.bindFailed", e)); + log.error(sm.getString("naming.bindFailed", "UserTransaction"), e); } } @@ -574,7 +579,7 @@ try { compCtx.bind("Resources", ((Context) container).getResources()); } catch (NamingException e) { - log.error(sm.getString("naming.bindFailed", e)); + log.error(sm.getString("naming.bindFailed", "Resources"), e); } } @@ -648,7 +653,7 @@ createSubcontexts(envCtx, ejb.getName()); envCtx.bind(ejb.getName(), ref); } catch (NamingException e) { - log.error(sm.getString("naming.bindFailed", e)); + log.error(sm.getString("naming.bindFailed", ejb.getName()), e); } } @@ -748,7 +753,7 @@ createSubcontexts(envCtx, env.getName()); envCtx.bind(env.getName(), value); } catch (NamingException e) { - log.error(sm.getString("naming.invalidEnvEntryValue", e)); + log.error(sm.getString("naming.invalidEnvEntryValue", env.getName()), e); } } } @@ -839,7 +844,7 @@ log.debug(sm.getString("naming.addSlash", service.getWsdlfile())); } } catch (MalformedURLException e) { - log.error(sm.getString("naming.wsdlFailed", e)); + log.error(sm.getString("naming.wsdlFailed", service.getWsdlfile()), e); } } if (wsdlURL == null) { @@ -874,7 +879,7 @@ log.debug(sm.getString("naming.addSlash", service.getJaxrpcmappingfile())); } } catch (MalformedURLException e) { - log.error(sm.getString("naming.wsdlFailed", e)); + log.error(sm.getString("naming.wsdlFailed", service.getJaxrpcmappingfile()), e); } } if (jaxrpcURL == null) { @@ -935,7 +940,7 @@ createSubcontexts(envCtx, service.getName()); envCtx.bind(service.getName(), ref); } catch (NamingException e) { - log.error(sm.getString("naming.bindFailed", e)); + log.error(sm.getString("naming.bindFailed", service.getName()), e); } } @@ -970,7 +975,7 @@ createSubcontexts(envCtx, resource.getName()); envCtx.bind(resource.getName(), ref); } catch (NamingException e) { - log.error(sm.getString("naming.bindFailed", e)); + log.error(sm.getString("naming.bindFailed", resource.getName()), e); } if (("javax.sql.DataSource".equals(ref.getClassName()) || @@ -982,7 +987,7 @@ Registry.getRegistry(null).registerComponent(actualResource, on, null); objectNames.put(resource.getName(), on); } catch (Exception e) { - log.warn(sm.getString("naming.jmxRegistrationFailed", e)); + log.warn(sm.getString("naming.jmxRegistrationFailed", resource.getName()), e); } // Bug 63210. DBCP2 DataSources require an explicit close. This goes // further and cleans up and AutoCloseable DataSource by default. @@ -1022,7 +1027,7 @@ createSubcontexts(envCtx, resourceEnvRef.getName()); envCtx.bind(resourceEnvRef.getName(), ref); } catch (NamingException e) { - log.error(sm.getString("naming.bindFailed", e)); + log.error(sm.getString("naming.bindFailed", resourceEnvRef.getName()), e); } } @@ -1054,7 +1059,7 @@ createSubcontexts(envCtx, resourceLink.getName()); ctx.bind(resourceLink.getName(), ref); } catch (NamingException e) { - log.error(sm.getString("naming.bindFailed", e)); + log.error(sm.getString("naming.bindFailed", resourceLink.getName()), e); } ResourceLinkFactory.registerGlobalResourceAccess(getGlobalNamingContext(), resourceLink.getName(), diff -Nru tomcat10-10.1.40/java/org/apache/catalina/core/OpenSSLLifecycleListener.java tomcat10-10.1.52/java/org/apache/catalina/core/OpenSSLLifecycleListener.java --- tomcat10-10.1.40/java/org/apache/catalina/core/OpenSSLLifecycleListener.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/core/OpenSSLLifecycleListener.java 2026-01-23 19:33:36.000000000 +0000 @@ -125,7 +125,7 @@ } catch (Throwable t) { Throwable throwable = ExceptionUtils.unwrapInvocationTargetException(t); ExceptionUtils.handleThrowable(throwable); - log.info(sm.getString("openssllistener.destroy")); + log.warn(sm.getString("openssllistener.destroy"), throwable); } } } diff -Nru tomcat10-10.1.40/java/org/apache/catalina/core/PropertiesRoleMappingListener.java tomcat10-10.1.52/java/org/apache/catalina/core/PropertiesRoleMappingListener.java --- tomcat10-10.1.40/java/org/apache/catalina/core/PropertiesRoleMappingListener.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/core/PropertiesRoleMappingListener.java 2026-01-23 19:33:36.000000000 +0000 @@ -111,9 +111,9 @@ Context context = (Context) event.getLifecycle(); try (Resource resource = context.findConfigFileResource(roleMappingFile)) { props.load(resource.getInputStream()); - } catch (IOException e) { + } catch (IOException ioe) { throw new IllegalStateException( - sm.getString("propertiesRoleMappingListener.roleMappingFileFail", roleMappingFile), e); + sm.getString("propertiesRoleMappingListener.roleMappingFileFail", roleMappingFile), ioe); } int linkCount = 0; diff -Nru tomcat10-10.1.40/java/org/apache/catalina/core/StandardContext.java tomcat10-10.1.52/java/org/apache/catalina/core/StandardContext.java --- tomcat10-10.1.40/java/org/apache/catalina/core/StandardContext.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/core/StandardContext.java 2026-01-23 19:33:36.000000000 +0000 @@ -42,6 +42,7 @@ import java.util.Set; import java.util.TreeMap; import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.atomic.AtomicLong; import java.util.concurrent.locks.Lock; @@ -141,9 +142,6 @@ /** * Standard implementation of the Context interface. Each child container must be a Wrapper implementation to * process the requests directed to a particular servlet. - * - * @author Craig R. McClanahan - * @author Remy Maucherat */ public class StandardContext extends ContainerBase implements Context, NotificationEmitter { @@ -423,7 +421,7 @@ /** * The MIME mappings for this web application, keyed by extension. */ - private final Map mimeMappings = new HashMap<>(); + private final ConcurrentMap mimeMappings = new ConcurrentHashMap<>(); /** @@ -2454,8 +2452,8 @@ if (!workDir.isAbsolute()) { try { workDir = new File(getCatalinaBase().getCanonicalFile(), getWorkDir()); - } catch (IOException e) { - log.warn(sm.getString("standardContext.workPath", getName()), e); + } catch (IOException ioe) { + log.warn(sm.getString("standardContext.workPath", getName()), ioe); } } return workDir.getAbsolutePath(); @@ -2827,12 +2825,8 @@ @Override public void addMimeMapping(String extension, String mimeType) { - - synchronized (mimeMappings) { - mimeMappings.put(extension.toLowerCase(Locale.ENGLISH), mimeType); - } + mimeMappings.put(extension.toLowerCase(Locale.ENGLISH), mimeType); fireContainerEvent("addMimeMapping", extension); - } @@ -3106,9 +3100,7 @@ @Override public String[] findMimeMappings() { - synchronized (mimeMappings) { - return mimeMappings.keySet().toArray(new String[0]); - } + return mimeMappings.keySet().toArray(new String[0]); } @@ -3403,12 +3395,8 @@ @Override public void removeMimeMapping(String extension) { - - synchronized (mimeMappings) { - mimeMappings.remove(extension); - } + mimeMappings.remove(extension); fireContainerEvent("removeMimeMapping", extension); - } @@ -4108,7 +4096,7 @@ Throwable throwable = ExceptionUtils.unwrapInvocationTargetException(t); ExceptionUtils.handleThrowable(throwable); getLogger().error(sm.getString("standardContext.listenerStop", listeners[j].getClass().getName()), - throwable); + throwable); ok = false; } } @@ -4130,7 +4118,7 @@ Throwable throwable = ExceptionUtils.unwrapInvocationTargetException(t); ExceptionUtils.handleThrowable(throwable); getLogger().error(sm.getString("standardContext.listenerStop", listeners[j].getClass().getName()), - throwable); + throwable); ok = false; } } @@ -4403,8 +4391,8 @@ if ((getCluster() != null) && distributable) { try { contextManager = getCluster().createManager(getName()); - } catch (Exception ex) { - log.error(sm.getString("standardContext.cluster.managerError"), ex); + } catch (Exception e) { + log.error(sm.getString("standardContext.cluster.managerError"), e); ok = false; } } else { @@ -4763,8 +4751,8 @@ // This object will no longer be visible or used. try { resetContext(); - } catch (Exception ex) { - log.error(sm.getString("standardContext.resetContextFail", getName()), ex); + } catch (Exception e) { + log.error(sm.getString("standardContext.resetContextFail", getName()), e); } // reset the instance manager @@ -5012,9 +5000,8 @@ if (isUseNaming()) { try { ContextBindings.bindThread(this, getNamingToken()); - } catch (NamingException e) { - // Silent catch, as this is a normal case during the early - // startup stages + } catch (NamingException ignore) { + // Silent catch, as this is a normal case during the early startup stages } } @@ -5349,8 +5336,9 @@ try { catalinaHomePath = getCatalinaBase().getCanonicalPath(); dir = new File(catalinaHomePath, workDir); - } catch (IOException e) { - log.warn(sm.getString("standardContext.workCreateException", workDir, getCatalinaBase(), getName()), e); + } catch (IOException ioe) { + log.warn(sm.getString("standardContext.workCreateException", workDir, getCatalinaBase(), getName()), + ioe); } } if (!dir.mkdirs() && !dir.isDirectory()) { @@ -5435,11 +5423,8 @@ @Override protected String getObjectNameKeyProperties() { - return "j2eeType=WebModule," + getObjectKeyPropertiesNameOnly() + - ",J2EEApplication=" + - getJ2EEApplication() + - ",J2EEServer=" + - getJ2EEServer(); + return "j2eeType=WebModule," + getObjectKeyPropertiesNameOnly() + ",J2EEApplication=" + getJ2EEApplication() + + ",J2EEServer=" + getJ2EEServer(); } private String getObjectKeyPropertiesNameOnly() { diff -Nru tomcat10-10.1.40/java/org/apache/catalina/core/StandardContextValve.java tomcat10-10.1.52/java/org/apache/catalina/core/StandardContextValve.java --- tomcat10-10.1.40/java/org/apache/catalina/core/StandardContextValve.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/core/StandardContextValve.java 2026-01-23 19:33:36.000000000 +0000 @@ -34,8 +34,6 @@ * Valve that implements the default basic behavior for the StandardContext container implementation. *

    * USAGE CONSTRAINT: This implementation is likely to be useful only when processing HTTP requests. - * - * @author Craig R. McClanahan */ final class StandardContextValve extends ValveBase { diff -Nru tomcat10-10.1.40/java/org/apache/catalina/core/StandardEngine.java tomcat10-10.1.52/java/org/apache/catalina/core/StandardEngine.java --- tomcat10-10.1.40/java/org/apache/catalina/core/StandardEngine.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/core/StandardEngine.java 2026-01-23 19:33:36.000000000 +0000 @@ -45,8 +45,6 @@ /** * Standard implementation of the Engine interface. Each child container must be a Host implementation to process * the specific fully qualified host name of that virtual host. - * - * @author Craig R. McClanahan */ public class StandardEngine extends ContainerBase implements Engine { diff -Nru tomcat10-10.1.40/java/org/apache/catalina/core/StandardEngineValve.java tomcat10-10.1.52/java/org/apache/catalina/core/StandardEngineValve.java --- tomcat10-10.1.40/java/org/apache/catalina/core/StandardEngineValve.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/core/StandardEngineValve.java 2026-01-23 19:33:36.000000000 +0000 @@ -29,8 +29,6 @@ * Valve that implements the default basic behavior for the StandardEngine container implementation. *

    * USAGE CONSTRAINT: This implementation is likely to be useful only when processing HTTP requests. - * - * @author Craig R. McClanahan */ final class StandardEngineValve extends ValveBase { diff -Nru tomcat10-10.1.40/java/org/apache/catalina/core/StandardHost.java tomcat10-10.1.52/java/org/apache/catalina/core/StandardHost.java --- tomcat10-10.1.40/java/org/apache/catalina/core/StandardHost.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/core/StandardHost.java 2026-01-23 19:33:36.000000000 +0000 @@ -18,6 +18,7 @@ import java.io.File; import java.io.IOException; +import java.nio.file.Path; import java.util.ArrayList; import java.util.Arrays; import java.util.List; @@ -49,9 +50,6 @@ /** * Standard implementation of the Host interface. Each child container must be a Context implementation to * process the requests directed to a particular web application. - * - * @author Craig R. McClanahan - * @author Remy Maucherat */ public class StandardHost extends ContainerBase implements Host { @@ -232,6 +230,12 @@ // Ignore } + Path appBasePath = file.toPath(); + Path basePath = getCatalinaBase().toPath(); + if (basePath.startsWith(appBasePath)) { + log.warn(sm.getString("standardHost.problematicAppBaseParent", getName())); + } + this.appBaseFile = file; return file; } @@ -275,6 +279,12 @@ // Ignore } + Path appBasePath = file.toPath(); + Path basePath = getCatalinaBase().toPath(); + if (basePath.startsWith(appBasePath)) { + log.warn(sm.getString("standardHost.problematicLegacyAppBaseParent", getName())); + } + this.legacyAppBaseFile = file; return file; } @@ -331,7 +341,8 @@ } try { file = file.getCanonicalFile(); - } catch (IOException e) {// ignore + } catch (IOException ignore) { + // Ignore } this.hostConfigBase = file; return file; diff -Nru tomcat10-10.1.40/java/org/apache/catalina/core/StandardHostValve.java tomcat10-10.1.52/java/org/apache/catalina/core/StandardHostValve.java --- tomcat10-10.1.40/java/org/apache/catalina/core/StandardHostValve.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/core/StandardHostValve.java 2026-01-23 19:33:36.000000000 +0000 @@ -44,9 +44,6 @@ * Valve that implements the default basic behavior for the StandardHost container implementation. *

    * USAGE CONSTRAINT: This implementation is likely to be useful only when processing HTTP requests. - * - * @author Craig R. McClanahan - * @author Remy Maucherat */ final class StandardHostValve extends ValveBase { @@ -212,8 +209,8 @@ response.finishResponse(); } catch (ClientAbortException e) { // Ignore - } catch (IOException e) { - container.getLogger().warn(sm.getString("standardHostValve.exception", errorPage), e); + } catch (IOException ioe) { + container.getLogger().warn(sm.getString("standardHostValve.exception", errorPage), ioe); } } } @@ -266,8 +263,8 @@ if (custom(request, response, errorPage)) { try { response.finishResponse(); - } catch (IOException e) { - container.getLogger().warn(sm.getString("standardHostValve.exception", errorPage), e); + } catch (IOException ioe) { + container.getLogger().warn(sm.getString("standardHostValve.exception", errorPage), ioe); } } } diff -Nru tomcat10-10.1.40/java/org/apache/catalina/core/StandardPipeline.java tomcat10-10.1.52/java/org/apache/catalina/core/StandardPipeline.java --- tomcat10-10.1.40/java/org/apache/catalina/core/StandardPipeline.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/core/StandardPipeline.java 2026-01-23 19:33:36.000000000 +0000 @@ -43,8 +43,6 @@ * This implementation assumes that no calls to addValve() or removeValve are allowed while a * request is currently being processed. Otherwise, the mechanism by which per-thread state is maintained will need to * be modified. - * - * @author Craig R. McClanahan */ public class StandardPipeline extends LifecycleBase implements Pipeline { diff -Nru tomcat10-10.1.40/java/org/apache/catalina/core/StandardServer.java tomcat10-10.1.52/java/org/apache/catalina/core/StandardServer.java --- tomcat10-10.1.40/java/org/apache/catalina/core/StandardServer.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/core/StandardServer.java 2026-01-23 19:33:36.000000000 +0000 @@ -62,8 +62,6 @@ /** * Standard implementation of the Server interface, available for use (but not required) when deploying and * starting Catalina. - * - * @author Craig R. McClanahan */ public final class StandardServer extends LifecycleMBeanBase implements Server { @@ -491,14 +489,14 @@ awaitSocket = null; try { s.close(); - } catch (IOException e) { + } catch (IOException ignore) { // Ignored } } t.interrupt(); try { t.join(1000); - } catch (InterruptedException e) { + } catch (InterruptedException ignore) { // Ignored } } @@ -531,9 +529,9 @@ // Set up a server socket to wait on try { awaitSocket = new ServerSocket(getPortWithOffset(), 1, InetAddress.getByName(address)); - } catch (IOException e) { + } catch (IOException ioe) { log.error(sm.getString("standardServer.awaitSocket.fail", address, String.valueOf(getPortWithOffset()), - String.valueOf(getPort()), String.valueOf(getPortOffset())), e); + String.valueOf(getPort()), String.valueOf(getPortOffset())), ioe); return; } @@ -566,12 +564,12 @@ } catch (AccessControlException ace) { log.warn(sm.getString("standardServer.accept.security"), ace); continue; - } catch (IOException e) { + } catch (IOException ioe) { if (stopAwait) { // Wait was aborted with socket.close() break; } - log.error(sm.getString("standardServer.accept.error"), e); + log.error(sm.getString("standardServer.accept.error"), ioe); break; } @@ -587,8 +585,8 @@ int ch; try { ch = stream.read(); - } catch (IOException e) { - log.warn(sm.getString("standardServer.accept.readError"), e); + } catch (IOException ioe) { + log.warn(sm.getString("standardServer.accept.readError"), ioe); ch = -1; } // Control character or EOF (-1) terminates loop @@ -604,7 +602,7 @@ if (socket != null) { socket.close(); } - } catch (IOException e) { + } catch (IOException ignore) { // Ignore } } @@ -627,7 +625,7 @@ if (serverSocket != null) { try { serverSocket.close(); - } catch (IOException e) { + } catch (IOException ignore) { // Ignore } } diff -Nru tomcat10-10.1.40/java/org/apache/catalina/core/StandardService.java tomcat10-10.1.52/java/org/apache/catalina/core/StandardService.java --- tomcat10-10.1.40/java/org/apache/catalina/core/StandardService.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/core/StandardService.java 2026-01-23 19:33:36.000000000 +0000 @@ -46,8 +46,6 @@ /** * Standard implementation of the Service interface. The associated Container is generally an instance of * Engine, but this is not required. - * - * @author Craig R. McClanahan */ public class StandardService extends LifecycleMBeanBase implements Service { diff -Nru tomcat10-10.1.40/java/org/apache/catalina/core/StandardWrapper.java tomcat10-10.1.52/java/org/apache/catalina/core/StandardWrapper.java --- tomcat10-10.1.40/java/org/apache/catalina/core/StandardWrapper.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/core/StandardWrapper.java 2026-01-23 19:33:36.000000000 +0000 @@ -65,9 +65,6 @@ /** * Standard implementation of the Wrapper interface that represents an individual servlet definition. No child * Containers are allowed, and the parent Container must be a Context. - * - * @author Craig R. McClanahan - * @author Remy Maucherat */ public class StandardWrapper extends ContainerBase implements ServletConfig, Wrapper, NotificationEmitter { @@ -585,9 +582,9 @@ countAllocated.incrementAndGet(); } catch (ServletException e) { throw e; - } catch (Throwable e) { - ExceptionUtils.handleThrowable(e); - throw new ServletException(sm.getString("standardWrapper.allocate"), e); + } catch (Throwable t) { + ExceptionUtils.handleThrowable(t); + throw new ServletException(sm.getString("standardWrapper.allocate"), t); } } if (!instanceInitialized) { @@ -722,8 +719,8 @@ try { jspMonitorON = new ObjectName(oname.toString()); Registry.getRegistry(null).registerComponent(instance, jspMonitorON, null); - } catch (Exception ex) { - log.warn(sm.getString("standardWrapper.jspMonitorError", instance)); + } catch (Exception e) { + log.warn(sm.getString("standardWrapper.jspMonitorError", instance), e); } } } @@ -766,8 +763,8 @@ unavailable(null); // Restore the context ClassLoader throw new ServletException(sm.getString("standardWrapper.notServlet", servletClass), e); - } catch (Throwable e) { - Throwable throwable = ExceptionUtils.unwrapInvocationTargetException(e); + } catch (Throwable t) { + Throwable throwable = ExceptionUtils.unwrapInvocationTargetException(t); ExceptionUtils.handleThrowable(throwable); unavailable(null); diff -Nru tomcat10-10.1.40/java/org/apache/catalina/core/StandardWrapperFacade.java tomcat10-10.1.52/java/org/apache/catalina/core/StandardWrapperFacade.java --- tomcat10-10.1.40/java/org/apache/catalina/core/StandardWrapperFacade.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/core/StandardWrapperFacade.java 2026-01-23 19:33:36.000000000 +0000 @@ -25,8 +25,6 @@ /** * Facade for the StandardWrapper object. - * - * @author Remy Maucherat */ public final class StandardWrapperFacade implements ServletConfig { diff -Nru tomcat10-10.1.40/java/org/apache/catalina/core/StandardWrapperValve.java tomcat10-10.1.52/java/org/apache/catalina/core/StandardWrapperValve.java --- tomcat10-10.1.40/java/org/apache/catalina/core/StandardWrapperValve.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/core/StandardWrapperValve.java 2026-01-23 19:33:36.000000000 +0000 @@ -44,8 +44,6 @@ /** * Valve that implements the default basic behavior for the StandardWrapper container implementation. - * - * @author Craig R. McClanahan */ final class StandardWrapperValve extends ValveBase { @@ -122,11 +120,11 @@ StandardWrapper.getRootCause(e)); throwable = e; exception(request, response, e); - } catch (Throwable e) { - ExceptionUtils.handleThrowable(e); - container.getLogger().error(sm.getString("standardWrapper.allocateException", wrapper.getName()), e); - throwable = e; - exception(request, response, e); + } catch (Throwable t) { + ExceptionUtils.handleThrowable(t); + container.getLogger().error(sm.getString("standardWrapper.allocateException", wrapper.getName()), t); + throwable = t; + exception(request, response, t); // servlet = null; is set here } @@ -183,11 +181,11 @@ } throwable = e; exception(request, response, e); - } catch (IOException e) { + } catch (IOException ioe) { container.getLogger() - .error(sm.getString("standardWrapper.serviceException", wrapper.getName(), context.getName()), e); - throwable = e; - exception(request, response, e); + .error(sm.getString("standardWrapper.serviceException", wrapper.getName(), context.getName()), ioe); + throwable = ioe; + exception(request, response, ioe); } catch (UnavailableException e) { container.getLogger() .error(sm.getString("standardWrapper.serviceException", wrapper.getName(), context.getName()), e); @@ -203,12 +201,12 @@ } throwable = e; exception(request, response, e); - } catch (Throwable e) { - ExceptionUtils.handleThrowable(e); + } catch (Throwable t) { + ExceptionUtils.handleThrowable(t); container.getLogger() - .error(sm.getString("standardWrapper.serviceException", wrapper.getName(), context.getName()), e); - throwable = e; - exception(request, response, e); + .error(sm.getString("standardWrapper.serviceException", wrapper.getName(), context.getName()), t); + throwable = t; + exception(request, response, t); } finally { // Release the filter chain (if any) for this request if (filterChain != null) { @@ -220,12 +218,12 @@ if (servlet != null) { wrapper.deallocate(servlet); } - } catch (Throwable e) { - ExceptionUtils.handleThrowable(e); - container.getLogger().error(sm.getString("standardWrapper.deallocateException", wrapper.getName()), e); + } catch (Throwable t) { + ExceptionUtils.handleThrowable(t); + container.getLogger().error(sm.getString("standardWrapper.deallocateException", wrapper.getName()), t); if (throwable == null) { - throwable = e; - exception(request, response, e); + throwable = t; + exception(request, response, t); } } @@ -235,11 +233,11 @@ if ((servlet != null) && (wrapper.getAvailable() == Long.MAX_VALUE)) { wrapper.unload(); } - } catch (Throwable e) { - ExceptionUtils.handleThrowable(e); - container.getLogger().error(sm.getString("standardWrapper.unloadException", wrapper.getName()), e); + } catch (Throwable t) { + ExceptionUtils.handleThrowable(t); + container.getLogger().error(sm.getString("standardWrapper.unloadException", wrapper.getName()), t); if (throwable == null) { - exception(request, response, e); + exception(request, response, t); } } long t2 = System.currentTimeMillis(); diff -Nru tomcat10-10.1.40/java/org/apache/catalina/core/ThreadLocalLeakPreventionListener.java tomcat10-10.1.52/java/org/apache/catalina/core/ThreadLocalLeakPreventionListener.java --- tomcat10-10.1.40/java/org/apache/catalina/core/ThreadLocalLeakPreventionListener.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/core/ThreadLocalLeakPreventionListener.java 2026-01-23 19:33:36.000000000 +0000 @@ -73,8 +73,7 @@ stopIdleThreads((Context) lifecycle); } } catch (Exception e) { - String msg = sm.getString("threadLocalLeakPreventionListener.lifecycleEvent.error", event); - log.error(msg, e); + log.error(sm.getString("threadLocalLeakPreventionListener.lifecycleEvent.error", event), e); } } @@ -83,8 +82,7 @@ try { super.containerEvent(event); } catch (Exception e) { - String msg = sm.getString("threadLocalLeakPreventionListener.containerEvent.error", event); - log.error(msg, e); + log.error(sm.getString("threadLocalLeakPreventionListener.containerEvent.error", event), e); } } diff -Nru tomcat10-10.1.40/java/org/apache/catalina/deploy/NamingResourcesImpl.java tomcat10-10.1.52/java/org/apache/catalina/deploy/NamingResourcesImpl.java --- tomcat10-10.1.40/java/org/apache/catalina/deploy/NamingResourcesImpl.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/deploy/NamingResourcesImpl.java 2026-01-23 19:33:36.000000000 +0000 @@ -61,8 +61,6 @@ /** * Holds and manages the naming resources defined in the Jakarta EE Naming Context and their associated JNDI context. - * - * @author Remy Maucherat */ public class NamingResourcesImpl extends LifecycleMBeanBase implements Serializable, NamingResources { @@ -513,8 +511,8 @@ /** - * @return the array of defined environment entries for this web application. If none have been defined, a zero-length - * array is returned. + * @return the array of defined environment entries for this web application. If none have been defined, a + * zero-length array is returned. */ public ContextEnvironment[] findEnvironments() { @@ -649,8 +647,8 @@ /** - * @return the array of resource environment reference names for this web application. If none have been specified, a - * zero-length array is returned. + * @return the array of resource environment reference names for this web application. If none have been specified, + * a zero-length array is returned. */ public ContextResourceEnvRef[] findResourceEnvRefs() { @@ -977,10 +975,10 @@ try { m = resource.getClass().getMethod(closeMethod, (Class[]) null); } catch (SecurityException e) { - log.debug(sm.getString("namingResources.cleanupCloseSecurity", closeMethod, name, container)); + log.debug(sm.getString("namingResources.cleanupCloseSecurity", closeMethod, name, container), e); return; } catch (NoSuchMethodException e) { - log.debug(sm.getString("namingResources.cleanupNoClose", name, container, closeMethod)); + log.debug(sm.getString("namingResources.cleanupNoClose", name, container, closeMethod), e); return; } try { diff -Nru tomcat10-10.1.40/java/org/apache/catalina/filters/Constants.java tomcat10-10.1.52/java/org/apache/catalina/filters/Constants.java --- tomcat10-10.1.40/java/org/apache/catalina/filters/Constants.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/filters/Constants.java 2026-01-23 19:33:36.000000000 +0000 @@ -16,11 +16,10 @@ */ package org.apache.catalina.filters; +import org.apache.tomcat.util.http.Method; /** * Manifest constants for this Java package. - * - * @author Craig R. McClanahan */ public final class Constants { @@ -44,7 +43,8 @@ */ public static final String CSRF_NONCE_REQUEST_PARAM_NAME_KEY = "org.apache.catalina.filters.CSRF_NONCE_PARAM_NAME"; - public static final String METHOD_GET = "GET"; + @Deprecated + public static final String METHOD_GET = Method.GET; public static final String CSRF_REST_NONCE_HEADER_NAME = "X-CSRF-Token"; diff -Nru tomcat10-10.1.40/java/org/apache/catalina/filters/CorsFilter.java tomcat10-10.1.52/java/org/apache/catalina/filters/CorsFilter.java --- tomcat10-10.1.40/java/org/apache/catalina/filters/CorsFilter.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/filters/CorsFilter.java 2026-01-23 19:33:36.000000000 +0000 @@ -36,6 +36,7 @@ import org.apache.catalina.Globals; import org.apache.juli.logging.Log; import org.apache.juli.logging.LogFactory; +import org.apache.tomcat.util.http.Method; import org.apache.tomcat.util.http.RequestUtil; import org.apache.tomcat.util.http.ResponseUtil; import org.apache.tomcat.util.http.parser.MediaType; @@ -405,7 +406,7 @@ response.addHeader(RESPONSE_HEADER_ACCESS_CONTROL_EXPOSE_HEADERS, exposedHeadersString); } - if ("OPTIONS".equals(method)) { + if (Method.OPTIONS.equals(method)) { // For an OPTIONS request, the response will vary based on the // value or absence of the following headers. Hence, they need to be // included in the Vary header. @@ -546,7 +547,7 @@ if (originHeader.isEmpty() || !RequestUtil.isValidOrigin(originHeader)) { return CORSRequestType.INVALID_CORS; } - if(RequestUtil.isSameOrigin(request, originHeader)) { + if (RequestUtil.isSameOrigin(request, originHeader)) { return CORSRequestType.NOT_CORS; } String method = request.getMethod(); @@ -554,8 +555,9 @@ return CORSRequestType.INVALID_CORS; } switch (method) { - case "OPTIONS": - String accessControlRequestMethodHeader = request.getHeader(REQUEST_HEADER_ACCESS_CONTROL_REQUEST_METHOD); + case Method.OPTIONS: + String accessControlRequestMethodHeader = + request.getHeader(REQUEST_HEADER_ACCESS_CONTROL_REQUEST_METHOD); if (accessControlRequestMethodHeader != null) { if (accessControlRequestMethodHeader.isEmpty()) { return CORSRequestType.INVALID_CORS; @@ -563,10 +565,10 @@ return CORSRequestType.PRE_FLIGHT; } return CORSRequestType.ACTUAL; - case "GET": - case "HEAD": + case Method.GET: + case Method.HEAD: return CORSRequestType.SIMPLE; - case "POST": + case Method.POST: String mediaType = MediaType.parseMediaTypeOnly(request.getContentType()); if (mediaType == null || SIMPLE_HTTP_REQUEST_CONTENT_TYPE_VALUES.contains(mediaType)) { return CORSRequestType.SIMPLE; @@ -892,7 +894,7 @@ * @see http://www.w3.org/TR/cors/#terminology */ public static final Collection SIMPLE_HTTP_REQUEST_CONTENT_TYPE_VALUES = - Set.of(Globals.CONTENT_TYPE_FORM_URL_ENCODING, "multipart/form-data", "text/plain"); + Set.of(Globals.CONTENT_TYPE_FORM_URL_ENCODING, "multipart/form-data", "text/plain"); // ------------------------------------------------ Configuration Defaults /** diff -Nru tomcat10-10.1.40/java/org/apache/catalina/filters/CsrfPreventionFilter.java tomcat10-10.1.52/java/org/apache/catalina/filters/CsrfPreventionFilter.java --- tomcat10-10.1.40/java/org/apache/catalina/filters/CsrfPreventionFilter.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/filters/CsrfPreventionFilter.java 2026-01-23 19:33:36.000000000 +0000 @@ -41,6 +41,7 @@ import org.apache.juli.logging.Log; import org.apache.juli.logging.LogFactory; +import org.apache.tomcat.util.http.Method; /** * Provides basic CSRF protection for a web application. The filter assumes that: @@ -446,7 +447,7 @@ } protected boolean skipNonceCheck(HttpServletRequest request) { - if (!Constants.METHOD_GET.equals(request.getMethod())) { + if (!Method.GET.equals(request.getMethod())) { return false; } @@ -545,6 +546,8 @@ @Override public String encodeRedirectURL(String url) { + url = removeQueryParameters(url, nonceRequestParameterName); + if (shouldAddNonce(url)) { return addNonce(super.encodeRedirectURL(url)); } else { @@ -554,6 +557,8 @@ @Override public String encodeURL(String url) { + url = removeQueryParameters(url, nonceRequestParameterName); + if (shouldAddNonce(url)) { return addNonce(super.encodeURL(url)); } else { @@ -575,6 +580,85 @@ return true; } + /** + * Removes zero or more query parameters from a URL. All instances of the query parameter and any associated + * values will be removed. + * + * @param url The URL whose query parameters should be removed. + * @param parameterName The name of the parameter to remove. + * + * @return The URL without any instances of the query parameter parameterName present. + */ + public static String removeQueryParameters(String url, String parameterName) { + if (null != parameterName) { + // Check for query string + int q = url.indexOf('?'); + if (q > -1) { + + // Look for parameter end + int start = q + 1; + int pos = url.indexOf('&', start); + + int iterations = 0; + + while (-1 < pos) { + // Process all parameters + if (++iterations > 100000) { + // Just in case things get out of control + throw new IllegalStateException("Way too many loop iterations"); + } + + int eq = url.indexOf('=', start); + int paramNameEnd; + if (-1 == eq || eq > pos) { + paramNameEnd = pos; + // Found no equal sign at all or past next & ; Parameter is all name. + } else { + // Found this param's equal sign + paramNameEnd = eq; + } + if (parameterName.equals(url.substring(start, paramNameEnd))) { + // Remove the parameter + url = url.substring(0, start) + url.substring(pos + 1); // +1 to consume the & + } else { + start = pos + 1; // Go to next parameter + } + pos = url.indexOf('&', start); + } + + // Check final parameter + String paramName; + pos = url.indexOf('=', start); + + if (-1 < pos) { + paramName = url.substring(start, pos); + } else { + paramName = url.substring(start); + // No value + } + if (paramName.equals(parameterName)) { + // Remove this parameter + + // Remove any trailing ? or & as well + char c = url.charAt(start - 1); + if ('?' == c || '&' == c) { + start--; + } + + url = url.substring(0, start); + } else { + // Remove trailing ? if it's there. Is this worth it? + int length = url.length(); + if (length == q + 1) { + url = url.substring(0, length - 1); + } + } + } + } + + return url; + } + /* * Return the specified URL with the nonce added to the query string. * diff -Nru tomcat10-10.1.40/java/org/apache/catalina/filters/ExpiresFilter.java tomcat10-10.1.52/java/org/apache/catalina/filters/ExpiresFilter.java --- tomcat10-10.1.40/java/org/apache/catalina/filters/ExpiresFilter.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/filters/ExpiresFilter.java 2026-01-23 19:33:36.000000000 +0000 @@ -44,6 +44,7 @@ import org.apache.juli.logging.Log; import org.apache.juli.logging.LogFactory; import org.apache.tomcat.util.buf.StringUtils; +import org.apache.tomcat.util.http.Method; /** *

    @@ -510,7 +511,7 @@ * ({@link StartingPoint#ACCESS_TIME}) or the last time the HTML-page/servlet-response was modified ( * {@link StartingPoint#LAST_MODIFICATION_TIME}). */ - public enum StartingPoint { + public enum StartingPoint { ACCESS_TIME, LAST_MODIFICATION_TIME } @@ -1403,7 +1404,7 @@ // Don't add cache headers unless the request is a GET or a HEAD request String method = request.getMethod(); - if (!"GET".equals(method) && !"HEAD".equals(method)) { + if (!Method.GET.equals(method) && !Method.HEAD.equals(method)) { if (log.isDebugEnabled()) { log.debug(sm.getString("expiresFilter.invalidMethod", request.getRequestURI(), method)); } diff -Nru tomcat10-10.1.40/java/org/apache/catalina/filters/RemoteAddrFilter.java tomcat10-10.1.52/java/org/apache/catalina/filters/RemoteAddrFilter.java --- tomcat10-10.1.40/java/org/apache/catalina/filters/RemoteAddrFilter.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/filters/RemoteAddrFilter.java 2026-01-23 19:33:36.000000000 +0000 @@ -30,8 +30,9 @@ * Concrete implementation of RequestFilter that filters based on the string representation of the remote * client's IP address. * - * @author Craig R. McClanahan + * @deprecated This Filter will be removed in Tomcat 12 onwards. Use {@link RemoteCIDRFilter} instead. */ +@Deprecated public final class RemoteAddrFilter extends RequestFilter { // Log must be non-static as loggers are created per class-loader and this diff -Nru tomcat10-10.1.40/java/org/apache/catalina/filters/RemoteCIDRFilter.java tomcat10-10.1.52/java/org/apache/catalina/filters/RemoteCIDRFilter.java --- tomcat10-10.1.40/java/org/apache/catalina/filters/RemoteCIDRFilter.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/filters/RemoteCIDRFilter.java 2026-01-23 19:33:36.000000000 +0000 @@ -20,8 +20,6 @@ import java.io.PrintWriter; import java.net.InetAddress; import java.net.UnknownHostException; -import java.util.ArrayList; -import java.util.Collections; import java.util.List; import jakarta.servlet.FilterChain; @@ -31,9 +29,9 @@ import jakarta.servlet.http.HttpServletResponse; import org.apache.catalina.util.NetMask; +import org.apache.catalina.util.NetMaskSet; import org.apache.juli.logging.Log; import org.apache.juli.logging.LogFactory; -import org.apache.tomcat.util.buf.StringUtils; public final class RemoteCIDRFilter extends FilterBase { @@ -49,14 +47,14 @@ private final Log log = LogFactory.getLog(RemoteCIDRFilter.class); // must not be static /** - * The list of allowed {@link NetMask}s + * The allowed {@link NetMask}s. */ - private final List allow = new ArrayList<>(); + private final NetMaskSet allow = new NetMaskSet(); /** - * The list of denied {@link NetMask}s + * The denied {@link NetMask}s. */ - private final List deny = new ArrayList<>(); + private final NetMaskSet deny = new NetMaskSet(); /** @@ -77,7 +75,7 @@ * @throws IllegalArgumentException One or more netmasks are invalid */ public void setAllow(final String input) { - final List messages = fillFromInput(input, allow); + final List messages = allow.addAll(input); if (messages.isEmpty()) { return; @@ -109,7 +107,7 @@ * @throws IllegalArgumentException One or more netmasks are invalid */ public void setDeny(final String input) { - final List messages = fillFromInput(input, deny); + final List messages = deny.addAll(input); if (messages.isEmpty()) { return; @@ -174,22 +172,17 @@ return false; } - for (final NetMask nm : deny) { - if (nm.matches(addr)) { - return false; - } + if (deny.contains(addr)) { + return false; } - for (final NetMask nm : allow) { - if (nm.matches(addr)) { - return true; - } + if (allow.contains(addr)) { + return true; } // Allow if deny is specified but allow isn't // Deny this request otherwise return !deny.isEmpty() && allow.isEmpty(); - } @@ -199,35 +192,4 @@ writer.write(sm.getString("http.403")); writer.flush(); } - - - /** - * Fill a {@link NetMask} list from a string input containing a comma-separated list of (hopefully valid) - * {@link NetMask}s. - * - * @param input The input string - * @param target The list to fill - * - * @return a string list of processing errors (empty when no errors) - */ - private List fillFromInput(final String input, final List target) { - target.clear(); - if (input == null || input.isEmpty()) { - return Collections.emptyList(); - } - - final List messages = new ArrayList<>(); - NetMask nm; - - for (final String s : StringUtils.splitCommaSeparated(input)) { - try { - nm = new NetMask(s); - target.add(nm); - } catch (IllegalArgumentException e) { - messages.add(s + ": " + e.getMessage()); - } - } - - return Collections.unmodifiableList(messages); - } } diff -Nru tomcat10-10.1.40/java/org/apache/catalina/filters/RemoteHostFilter.java tomcat10-10.1.52/java/org/apache/catalina/filters/RemoteHostFilter.java --- tomcat10-10.1.40/java/org/apache/catalina/filters/RemoteHostFilter.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/filters/RemoteHostFilter.java 2026-01-23 19:33:36.000000000 +0000 @@ -28,8 +28,6 @@ /** * Concrete implementation of RequestFilter that filters based on the remote client's host name. - * - * @author Craig R. McClanahan */ public final class RemoteHostFilter extends RequestFilter { diff -Nru tomcat10-10.1.40/java/org/apache/catalina/filters/RemoteIpFilter.java tomcat10-10.1.52/java/org/apache/catalina/filters/RemoteIpFilter.java --- tomcat10-10.1.40/java/org/apache/catalina/filters/RemoteIpFilter.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/filters/RemoteIpFilter.java 2026-01-23 19:33:36.000000000 +0000 @@ -194,6 +194,7 @@ *

    * XForwardedFilter configuration: *

    + * *
      * <filter>
      *    <filter-name>RemoteIpFilter</filter-name>
    @@ -220,7 +221,8 @@
      *    <filter-name>RemoteIpFilter</filter-name>
      *    <url-pattern>/*</url-pattern>
      *    <dispatcher>REQUEST</dispatcher>
    - * </filter-mapping>
    + * </filter-mapping> + * * * * @@ -273,6 +275,7 @@ *

    * RemoteIpFilter configuration: *

    + * *
      * <filter>
      *    <filter-name>RemoteIpFilter</filter-name>
    @@ -299,7 +302,8 @@
      *    <filter-name>RemoteIpFilter</filter-name>
      *    <url-pattern>/*</url-pattern>
      *    <dispatcher>REQUEST</dispatcher>
    - * </filter-mapping>
    + * </filter-mapping> + * *
    Request Values
    * * @@ -335,6 +339,7 @@ *

    * RemoteIpFilter configuration: *

    + * *
      * <filter>
      *    <filter-name>RemoteIpFilter</filter-name>
    @@ -361,7 +366,8 @@
      *    <filter-name>RemoteIpFilter</filter-name>
      *    <url-pattern>/*</url-pattern>
      *    <dispatcher>REQUEST</dispatcher>
    - * </filter-mapping>
    + * </filter-mapping> + * *
    Request Values
    * * @@ -398,6 +404,7 @@ *

    * RemoteIpFilter configuration: *

    + * *
      * <filter>
      *    <filter-name>RemoteIpFilter</filter-name>
    @@ -424,7 +431,8 @@
      *    <filter-name>RemoteIpFilter</filter-name>
      *    <url-pattern>/*</url-pattern>
      *    <dispatcher>REQUEST</dispatcher>
    - * </filter-mapping>
    + * </filter-mapping> + * *
    Request Values
    * * @@ -742,14 +750,13 @@ /** * @see #setInternalProxies(String) */ - private Pattern internalProxies = - Pattern.compile("10\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}|" + "192\\.168\\.\\d{1,3}\\.\\d{1,3}|" + - "169\\.254\\.\\d{1,3}\\.\\d{1,3}|" + "127\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}|" + - "100\\.6[4-9]{1}\\.\\d{1,3}\\.\\d{1,3}|" + "100\\.[7-9]{1}\\d{1}\\.\\d{1,3}\\.\\d{1,3}|" + - "100\\.1[0-1]{1}\\d{1}\\.\\d{1,3}\\.\\d{1,3}|" + "100\\.12[0-7]{1}\\.\\d{1,3}\\.\\d{1,3}|" + - "172\\.1[6-9]{1}\\.\\d{1,3}\\.\\d{1,3}|" + "172\\.2[0-9]{1}\\.\\d{1,3}\\.\\d{1,3}|" + - "172\\.3[0-1]{1}\\.\\d{1,3}\\.\\d{1,3}|" + "0:0:0:0:0:0:0:1|::1|" + - "fe[89ab]\\p{XDigit}:.*|" + "f[cd]\\p{XDigit}{2}+:.*"); + private Pattern internalProxies = Pattern.compile("10\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}|" + + "192\\.168\\.\\d{1,3}\\.\\d{1,3}|" + "169\\.254\\.\\d{1,3}\\.\\d{1,3}|" + + "127\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}|" + "100\\.6[4-9]{1}\\.\\d{1,3}\\.\\d{1,3}|" + + "100\\.[7-9]{1}\\d{1}\\.\\d{1,3}\\.\\d{1,3}|" + "100\\.1[0-1]{1}\\d{1}\\.\\d{1,3}\\.\\d{1,3}|" + + "100\\.12[0-7]{1}\\.\\d{1,3}\\.\\d{1,3}|" + "172\\.1[6-9]{1}\\.\\d{1,3}\\.\\d{1,3}|" + + "172\\.2[0-9]{1}\\.\\d{1,3}\\.\\d{1,3}|" + "172\\.3[0-1]{1}\\.\\d{1,3}\\.\\d{1,3}|" + + "0:0:0:0:0:0:0:1|::1|" + "fe[89ab]\\p{XDigit}:.*|" + "f[cd]\\p{XDigit}{2}+:.*"); /** * @see #setProtocolHeader(String) @@ -898,7 +905,7 @@ } } catch (IllegalArgumentException iae) { - log.debug(sm.getString("remoteIpFilter.invalidHostHeader", hostHeaderValue, hostHeader)); + log.debug(sm.getString("remoteIpFilter.invalidHostHeader", hostHeaderValue, hostHeader), iae); } } } @@ -960,7 +967,7 @@ try { port = Integer.parseInt(portHeaderValue); } catch (NumberFormatException nfe) { - log.debug(sm.getString("remoteIpFilter.invalidPort", portHeaderValue, getPortHeader())); + log.debug(sm.getString("remoteIpFilter.invalidPort", portHeaderValue, getPortHeader()), nfe); } } } diff -Nru tomcat10-10.1.40/java/org/apache/catalina/filters/RequestDumperFilter.java tomcat10-10.1.52/java/org/apache/catalina/filters/RequestDumperFilter.java --- tomcat10-10.1.40/java/org/apache/catalina/filters/RequestDumperFilter.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/filters/RequestDumperFilter.java 2026-01-23 19:33:36.000000000 +0000 @@ -46,8 +46,6 @@ * org.apache.catalina.filter.RequestDumperFilter logger is directed to a dedicated file and that the * org.apache.juli.VerbatimFormatter is used. *

    - * - * @author Craig R. McClanahan */ public class RequestDumperFilter extends GenericFilter { diff -Nru tomcat10-10.1.40/java/org/apache/catalina/ha/ClusterListener.java tomcat10-10.1.52/java/org/apache/catalina/ha/ClusterListener.java --- tomcat10-10.1.40/java/org/apache/catalina/ha/ClusterListener.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/ha/ClusterListener.java 2026-01-23 19:33:36.000000000 +0000 @@ -26,8 +26,6 @@ /** * Receive SessionID cluster change from other backup node after primary session node is failed. - * - * @author Peter Rossbach */ public abstract class ClusterListener implements ChannelListener { diff -Nru tomcat10-10.1.40/java/org/apache/catalina/ha/ClusterManager.java tomcat10-10.1.52/java/org/apache/catalina/ha/ClusterManager.java --- tomcat10-10.1.40/java/org/apache/catalina/ha/ClusterManager.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/ha/ClusterManager.java 2026-01-23 19:33:36.000000000 +0000 @@ -26,8 +26,6 @@ /** * The common interface used by all cluster manager. This is so that we can have a more pluggable way of swapping * session managers for different algorithms. - * - * @author Peter Rossbach */ public interface ClusterManager extends Manager { diff -Nru tomcat10-10.1.40/java/org/apache/catalina/ha/ClusterRuleSet.java tomcat10-10.1.52/java/org/apache/catalina/ha/ClusterRuleSet.java --- tomcat10-10.1.40/java/org/apache/catalina/ha/ClusterRuleSet.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/ha/ClusterRuleSet.java 2026-01-23 19:33:36.000000000 +0000 @@ -20,11 +20,7 @@ import org.apache.tomcat.util.digester.RuleSet; /** - *

    * RuleSet for processing the contents of a Cluster definition element. - *

    - * - * @author Peter Rossbach */ public class ClusterRuleSet implements RuleSet { diff -Nru tomcat10-10.1.40/java/org/apache/catalina/ha/ClusterValve.java tomcat10-10.1.52/java/org/apache/catalina/ha/ClusterValve.java --- tomcat10-10.1.40/java/org/apache/catalina/ha/ClusterValve.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/ha/ClusterValve.java 2026-01-23 19:33:36.000000000 +0000 @@ -21,8 +21,6 @@ /** * Cluster valves are a simple extension to the Tomcat valve architecture with a small addition of being able to * reference the cluster component in the container it sits in. - * - * @author Peter Rossbach */ public interface ClusterValve extends Valve { /** diff -Nru tomcat10-10.1.40/java/org/apache/catalina/ha/authenticator/ClusterSingleSignOn.java tomcat10-10.1.52/java/org/apache/catalina/ha/authenticator/ClusterSingleSignOn.java --- tomcat10-10.1.40/java/org/apache/catalina/ha/authenticator/ClusterSingleSignOn.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/ha/authenticator/ClusterSingleSignOn.java 2026-01-23 19:33:36.000000000 +0000 @@ -46,8 +46,6 @@ *
  • The web applications themselves must use one of the standard Authenticators found in the * org.apache.catalina.authenticator package.
  • * - * - * @author Fabien Carrion */ public class ClusterSingleSignOn extends SingleSignOn implements ClusterValve, MapOwner { diff -Nru tomcat10-10.1.40/java/org/apache/catalina/ha/backend/HeartbeatListener.java tomcat10-10.1.52/java/org/apache/catalina/ha/backend/HeartbeatListener.java --- tomcat10-10.1.40/java/org/apache/catalina/ha/backend/HeartbeatListener.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/ha/backend/HeartbeatListener.java 2026-01-23 19:33:36.000000000 +0000 @@ -199,8 +199,8 @@ coll = new CollectedInfo(host, port); this.port = coll.port; this.host = coll.host; - } catch (Exception ex) { - log.error(sm.getString("heartbeatListener.errorCollectingInfo"), ex); + } catch (Exception e) { + log.error(sm.getString("heartbeatListener.errorCollectingInfo"), e); coll = null; return; } @@ -209,8 +209,8 @@ /* Start or restart sender */ try { sender.init(this); - } catch (Exception ex) { - log.error(sm.getString("heartbeatListener.senderInitError"), ex); + } catch (Exception e) { + log.error(sm.getString("heartbeatListener.senderInitError"), e); sender = null; return; } @@ -218,16 +218,16 @@ /* refresh the connector information and send it */ try { coll.refresh(); - } catch (Exception ex) { - log.error(sm.getString("heartbeatListener.refreshError"), ex); + } catch (Exception e) { + log.error(sm.getString("heartbeatListener.refreshError"), e); coll = null; return; } String output = "v=1&ready=" + coll.ready + "&busy=" + coll.busy + "&port=" + port; try { sender.send(output); - } catch (Exception ex) { - log.error(sm.getString("heartbeatListener.sendError"), ex); + } catch (Exception e) { + log.error(sm.getString("heartbeatListener.sendError"), e); } } } diff -Nru tomcat10-10.1.40/java/org/apache/catalina/ha/backend/MultiCastSender.java tomcat10-10.1.52/java/org/apache/catalina/ha/backend/MultiCastSender.java --- tomcat10-10.1.40/java/org/apache/catalina/ha/backend/MultiCastSender.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/ha/backend/MultiCastSender.java 2026-01-23 19:33:36.000000000 +0000 @@ -60,8 +60,8 @@ s.setTimeToLive(config.getTtl()); s.joinGroup(new InetSocketAddress(group, 0), null); - } catch (Exception ex) { - log.error(sm.getString("multiCastSender.multiCastFailed"), ex); + } catch (Exception e) { + log.error(sm.getString("multiCastSender.multiCastFailed"), e); s = null; return -1; } @@ -72,8 +72,8 @@ DatagramPacket data = new DatagramPacket(buf, buf.length, group, config.getMultiport()); try { s.send(data); - } catch (Exception ex) { - log.error(sm.getString("multiCastSender.sendFailed"), ex); + } catch (Exception e) { + log.error(sm.getString("multiCastSender.sendFailed"), e); s.close(); s = null; return -1; diff -Nru tomcat10-10.1.40/java/org/apache/catalina/ha/backend/TcpSender.java tomcat10-10.1.52/java/org/apache/catalina/ha/backend/TcpSender.java --- tomcat10-10.1.40/java/org/apache/catalina/ha/backend/TcpSender.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/ha/backend/TcpSender.java 2026-01-23 19:33:36.000000000 +0000 @@ -106,8 +106,8 @@ } connectionReaders[i] = new BufferedReader(new InputStreamReader(connections[i].getInputStream())); connectionWriters[i] = new BufferedWriter(new OutputStreamWriter(connections[i].getOutputStream())); - } catch (Exception ex) { - log.error(sm.getString("tcpSender.connectionFailed"), ex); + } catch (Exception e) { + log.error(sm.getString("tcpSender.connectionFailed"), e); close(i); } } @@ -125,8 +125,8 @@ writer.write(mess); writer.write("\r\n"); writer.flush(); - } catch (Exception ex) { - log.error(sm.getString("tcpSender.sendFailed"), ex); + } catch (Exception e) { + log.error(sm.getString("tcpSender.sendFailed"), e); close(i); } if (connections[i] == null) { @@ -192,7 +192,7 @@ if (connectionReaders[i] != null) { connectionReaders[i].close(); } - } catch (IOException e) { + } catch (IOException ignore) { // Ignore } connectionReaders[i] = null; @@ -200,7 +200,7 @@ if (connectionWriters[i] != null) { connectionWriters[i].close(); } - } catch (IOException e) { + } catch (IOException ignore) { // Ignore } connectionWriters[i] = null; @@ -208,7 +208,7 @@ if (connections[i] != null) { connections[i].close(); } - } catch (IOException e) { + } catch (IOException ignore) { // Ignore } connections[i] = null; diff -Nru tomcat10-10.1.40/java/org/apache/catalina/ha/context/ReplicatedContext.java tomcat10-10.1.52/java/org/apache/catalina/ha/context/ReplicatedContext.java --- tomcat10-10.1.40/java/org/apache/catalina/ha/context/ReplicatedContext.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/ha/context/ReplicatedContext.java 2026-01-23 19:33:36.000000000 +0000 @@ -62,9 +62,9 @@ map.setChannelSendOptions(mapSendOptions); ((ReplApplContext) this.context).setAttributeMap(map); } - } catch (Exception x) { - log.error(sm.getString("replicatedContext.startUnable", getName()), x); - throw new LifecycleException(sm.getString("replicatedContext.startFailed", getName()), x); + } catch (Exception e) { + log.error(sm.getString("replicatedContext.startUnable", getName()), e); + throw new LifecycleException(sm.getString("replicatedContext.startFailed", getName()), e); } } diff -Nru tomcat10-10.1.40/java/org/apache/catalina/ha/deploy/FarmWarDeployer.java tomcat10-10.1.52/java/org/apache/catalina/ha/deploy/FarmWarDeployer.java --- tomcat10-10.1.40/java/org/apache/catalina/ha/deploy/FarmWarDeployer.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/ha/deploy/FarmWarDeployer.java 2026-01-23 19:33:36.000000000 +0000 @@ -51,8 +51,6 @@ *
  • tempDir - a temporaryDirectory to store binary data when downloading a war from the cluster
  • * * Currently we only support deployment of WAR files since they are easier to send across the wire. - * - * @author Peter Rossbach */ public class FarmWarDeployer extends ClusterListener implements ClusterDeployer, FileChangeListener { /*--Static Variables----------------------------------------*/ @@ -237,8 +235,8 @@ } else { log.error(sm.getString("farmWarDeployer.servicingDeploy", contextName, name)); } - } catch (Exception ex) { - log.error(sm.getString("farmWarDeployer.fileMessageError"), ex); + } catch (Exception e) { + log.error(sm.getString("farmWarDeployer.fileMessageError"), e); } finally { removeFactory(fmsg); } @@ -262,12 +260,12 @@ } else { log.error(sm.getString("farmWarDeployer.servicingUndeploy", contextName)); } - } catch (Exception ex) { - log.error(sm.getString("farmWarDeployer.undeployMessageError"), ex); + } catch (Exception e) { + log.error(sm.getString("farmWarDeployer.undeployMessageError"), e); } } - } catch (IOException x) { - log.error(sm.getString("farmWarDeployer.msgIoe"), x); + } catch (IOException ioe) { + log.error(sm.getString("farmWarDeployer.msgIoe"), ioe); } } @@ -395,8 +393,8 @@ log.error(sm.getString("farmWarDeployer.removeFailRemote", contextName)); } - } catch (Exception ex) { - log.error(sm.getString("farmWarDeployer.removeFailLocal", contextName), ex); + } catch (Exception e) { + log.error(sm.getString("farmWarDeployer.removeFailLocal", contextName), e); } } @@ -428,8 +426,8 @@ log.error(sm.getString("farmWarDeployer.servicingDeploy", cn.getName(), deployWar.getName())); } install(cn.getName(), deployWar); - } catch (Exception x) { - log.error(sm.getString("farmWarDeployer.modInstallFail"), x); + } catch (Exception e) { + log.error(sm.getString("farmWarDeployer.modInstallFail"), e); } } @@ -441,8 +439,8 @@ log.info(sm.getString("farmWarDeployer.removeLocal", cn.getName())); } remove(cn.getName(), true); - } catch (Exception x) { - log.error(sm.getString("farmWarDeployer.removeLocalFail"), x); + } catch (Exception e) { + log.error(sm.getString("farmWarDeployer.removeLocalFail"), e); } } @@ -681,8 +679,8 @@ return false; } } - } catch (IOException e) { - log.error(sm.getString("farmWarDeployer.fileCopyFail", from, to), e); + } catch (IOException ioe) { + log.error(sm.getString("farmWarDeployer.fileCopyFail", from, to), ioe); return false; } @@ -696,8 +694,8 @@ } os.write(buf, 0, len); } - } catch (IOException e) { - log.error(sm.getString("farmWarDeployer.fileCopyFail", from, to), e); + } catch (IOException ioe) { + log.error(sm.getString("farmWarDeployer.fileCopyFail", from, to), ioe); return false; } return true; @@ -720,7 +718,8 @@ } try { dir = dir.getCanonicalFile(); - } catch (IOException e) {// ignore + } catch (IOException ignore) { + // Ignore } return dir; } diff -Nru tomcat10-10.1.40/java/org/apache/catalina/ha/deploy/FileMessageFactory.java tomcat10-10.1.52/java/org/apache/catalina/ha/deploy/FileMessageFactory.java --- tomcat10-10.1.40/java/org/apache/catalina/ha/deploy/FileMessageFactory.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/ha/deploy/FileMessageFactory.java 2026-01-23 19:33:36.000000000 +0000 @@ -286,12 +286,14 @@ try { in.close(); } catch (IOException ignore) { + // Ignore } } if (out != null) { try { out.close(); } catch (IOException ignore) { + // Ignore } } in = null; diff -Nru tomcat10-10.1.40/java/org/apache/catalina/ha/deploy/WarWatcher.java tomcat10-10.1.52/java/org/apache/catalina/ha/deploy/WarWatcher.java --- tomcat10-10.1.40/java/org/apache/catalina/ha/deploy/WarWatcher.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/ha/deploy/WarWatcher.java 2026-01-23 19:33:36.000000000 +0000 @@ -28,8 +28,6 @@ /** * The WarWatcher watches the deployDir for changes made to the directory (adding new WAR files->deploy or * remove WAR files->undeploy) and notifies a listener of the changes made. - * - * @author Peter Rossbach */ public class WarWatcher { diff -Nru tomcat10-10.1.40/java/org/apache/catalina/ha/session/BackupManager.java tomcat10-10.1.52/java/org/apache/catalina/ha/session/BackupManager.java --- tomcat10-10.1.40/java/org/apache/catalina/ha/session/BackupManager.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/ha/session/BackupManager.java 2026-01-23 19:33:36.000000000 +0000 @@ -145,9 +145,9 @@ map.setChannelSendOptions(mapSendOptions); map.setAccessTimeout(accessTimeout); this.sessions = map; - } catch (Exception x) { - log.error(sm.getString("backupManager.startUnable", getName()), x); - throw new LifecycleException(sm.getString("backupManager.startFailed", getName()), x); + } catch (Exception e) { + log.error(sm.getString("backupManager.startUnable", getName()), e); + throw new LifecycleException(sm.getString("backupManager.startFailed", getName()), e); } setState(LifecycleState.STARTING); } diff -Nru tomcat10-10.1.40/java/org/apache/catalina/ha/session/ClusterSessionListener.java tomcat10-10.1.52/java/org/apache/catalina/ha/session/ClusterSessionListener.java --- tomcat10-10.1.40/java/org/apache/catalina/ha/session/ClusterSessionListener.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/ha/session/ClusterSessionListener.java 2026-01-23 19:33:36.000000000 +0000 @@ -27,8 +27,6 @@ /** * Receive replicated SessionMessage form other cluster node. - * - * @author Peter Rossbach */ public class ClusterSessionListener extends ClusterListener { diff -Nru tomcat10-10.1.40/java/org/apache/catalina/ha/session/DeltaManager.java tomcat10-10.1.52/java/org/apache/catalina/ha/session/DeltaManager.java --- tomcat10-10.1.40/java/org/apache/catalina/ha/session/DeltaManager.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/ha/session/DeltaManager.java 2026-01-23 19:33:36.000000000 +0000 @@ -23,6 +23,8 @@ import java.io.ObjectOutputStream; import java.util.ArrayList; import java.util.Date; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.concurrent.atomic.AtomicLong; import org.apache.catalina.Engine; import org.apache.catalina.Host; @@ -48,9 +50,6 @@ *

    * IMPLEMENTATION NOTE : Correct behavior of session storing and reloading depends upon external calls to the * start() and stop() methods of this class at the correct times. - * - * @author Craig R. McClanahan - * @author Peter Rossbach */ public class DeltaManager extends ClusterManagerBase { @@ -76,6 +75,7 @@ private int stateTransferTimeout = 60; private boolean sendAllSessions = true; private int sendAllSessionsSize = 1000; + private boolean enableStatistics = true; /** * wait time between send session block (default 2 sec) @@ -88,25 +88,25 @@ // -------------------------------------------------------- stats attributes - private volatile long sessionReplaceCounter = 0; - private volatile long counterReceive_EVT_GET_ALL_SESSIONS = 0; - private volatile long counterReceive_EVT_ALL_SESSION_DATA = 0; - private volatile long counterReceive_EVT_SESSION_CREATED = 0; - private volatile long counterReceive_EVT_SESSION_EXPIRED = 0; - private volatile long counterReceive_EVT_SESSION_ACCESSED = 0; - private volatile long counterReceive_EVT_SESSION_DELTA = 0; - private volatile int counterReceive_EVT_ALL_SESSION_TRANSFERCOMPLETE = 0; - private volatile long counterReceive_EVT_CHANGE_SESSION_ID = 0; - private volatile long counterReceive_EVT_ALL_SESSION_NOCONTEXTMANAGER = 0; - private volatile long counterSend_EVT_GET_ALL_SESSIONS = 0; - private volatile long counterSend_EVT_ALL_SESSION_DATA = 0; - private volatile long counterSend_EVT_SESSION_CREATED = 0; - private volatile long counterSend_EVT_SESSION_DELTA = 0; - private volatile long counterSend_EVT_SESSION_ACCESSED = 0; - private volatile long counterSend_EVT_SESSION_EXPIRED = 0; - private volatile int counterSend_EVT_ALL_SESSION_TRANSFERCOMPLETE = 0; - private volatile long counterSend_EVT_CHANGE_SESSION_ID = 0; - private volatile int counterNoStateTransferred = 0; + private final AtomicLong sessionReplaceCounter = new AtomicLong(0); + private final AtomicLong counterReceive_EVT_GET_ALL_SESSIONS = new AtomicLong(0); + private final AtomicLong counterReceive_EVT_ALL_SESSION_DATA = new AtomicLong(0); + private final AtomicLong counterReceive_EVT_SESSION_CREATED = new AtomicLong(0); + private final AtomicLong counterReceive_EVT_SESSION_EXPIRED = new AtomicLong(0); + private final AtomicLong counterReceive_EVT_SESSION_ACCESSED = new AtomicLong(0); + private final AtomicLong counterReceive_EVT_SESSION_DELTA = new AtomicLong(0); + private final AtomicInteger counterReceive_EVT_ALL_SESSION_TRANSFERCOMPLETE = new AtomicInteger(0); + private final AtomicLong counterReceive_EVT_CHANGE_SESSION_ID = new AtomicLong(0); + private final AtomicLong counterReceive_EVT_ALL_SESSION_NOCONTEXTMANAGER = new AtomicLong(0); + private final AtomicLong counterSend_EVT_GET_ALL_SESSIONS = new AtomicLong(0); + private final AtomicLong counterSend_EVT_ALL_SESSION_DATA = new AtomicLong(0); + private final AtomicLong counterSend_EVT_SESSION_CREATED = new AtomicLong(0); + private final AtomicLong counterSend_EVT_SESSION_DELTA = new AtomicLong(0); + private final AtomicLong counterSend_EVT_SESSION_ACCESSED = new AtomicLong(0); + private final AtomicLong counterSend_EVT_SESSION_EXPIRED = new AtomicLong(0); + private final AtomicInteger counterSend_EVT_ALL_SESSION_TRANSFERCOMPLETE = new AtomicInteger(0); + private final AtomicLong counterSend_EVT_CHANGE_SESSION_ID = new AtomicLong(0); + private final AtomicInteger counterNoStateTransferred = new AtomicInteger(0); // ------------------------------------------------------------- Constructor @@ -130,98 +130,98 @@ * @return Returns the counterSend_EVT_GET_ALL_SESSIONS. */ public long getCounterSend_EVT_GET_ALL_SESSIONS() { - return counterSend_EVT_GET_ALL_SESSIONS; + return counterSend_EVT_GET_ALL_SESSIONS.get(); } /** * @return Returns the counterSend_EVT_SESSION_ACCESSED. */ public long getCounterSend_EVT_SESSION_ACCESSED() { - return counterSend_EVT_SESSION_ACCESSED; + return counterSend_EVT_SESSION_ACCESSED.get(); } /** * @return Returns the counterSend_EVT_SESSION_CREATED. */ public long getCounterSend_EVT_SESSION_CREATED() { - return counterSend_EVT_SESSION_CREATED; + return counterSend_EVT_SESSION_CREATED.get(); } /** * @return Returns the counterSend_EVT_SESSION_DELTA. */ public long getCounterSend_EVT_SESSION_DELTA() { - return counterSend_EVT_SESSION_DELTA; + return counterSend_EVT_SESSION_DELTA.get(); } /** * @return Returns the counterSend_EVT_SESSION_EXPIRED. */ public long getCounterSend_EVT_SESSION_EXPIRED() { - return counterSend_EVT_SESSION_EXPIRED; + return counterSend_EVT_SESSION_EXPIRED.get(); } /** * @return Returns the counterSend_EVT_ALL_SESSION_DATA. */ public long getCounterSend_EVT_ALL_SESSION_DATA() { - return counterSend_EVT_ALL_SESSION_DATA; + return counterSend_EVT_ALL_SESSION_DATA.get(); } /** * @return Returns the counterSend_EVT_ALL_SESSION_TRANSFERCOMPLETE. */ public int getCounterSend_EVT_ALL_SESSION_TRANSFERCOMPLETE() { - return counterSend_EVT_ALL_SESSION_TRANSFERCOMPLETE; + return counterSend_EVT_ALL_SESSION_TRANSFERCOMPLETE.get(); } /** * @return Returns the counterSend_EVT_CHANGE_SESSION_ID. */ public long getCounterSend_EVT_CHANGE_SESSION_ID() { - return counterSend_EVT_CHANGE_SESSION_ID; + return counterSend_EVT_CHANGE_SESSION_ID.get(); } /** * @return Returns the counterReceive_EVT_ALL_SESSION_DATA. */ public long getCounterReceive_EVT_ALL_SESSION_DATA() { - return counterReceive_EVT_ALL_SESSION_DATA; + return counterReceive_EVT_ALL_SESSION_DATA.get(); } /** * @return Returns the counterReceive_EVT_GET_ALL_SESSIONS. */ public long getCounterReceive_EVT_GET_ALL_SESSIONS() { - return counterReceive_EVT_GET_ALL_SESSIONS; + return counterReceive_EVT_GET_ALL_SESSIONS.get(); } /** * @return Returns the counterReceive_EVT_SESSION_ACCESSED. */ public long getCounterReceive_EVT_SESSION_ACCESSED() { - return counterReceive_EVT_SESSION_ACCESSED; + return counterReceive_EVT_SESSION_ACCESSED.get(); } /** * @return Returns the counterReceive_EVT_SESSION_CREATED. */ public long getCounterReceive_EVT_SESSION_CREATED() { - return counterReceive_EVT_SESSION_CREATED; + return counterReceive_EVT_SESSION_CREATED.get(); } /** * @return Returns the counterReceive_EVT_SESSION_DELTA. */ public long getCounterReceive_EVT_SESSION_DELTA() { - return counterReceive_EVT_SESSION_DELTA; + return counterReceive_EVT_SESSION_DELTA.get(); } /** * @return Returns the counterReceive_EVT_SESSION_EXPIRED. */ public long getCounterReceive_EVT_SESSION_EXPIRED() { - return counterReceive_EVT_SESSION_EXPIRED; + return counterReceive_EVT_SESSION_EXPIRED.get(); } @@ -229,35 +229,35 @@ * @return Returns the counterReceive_EVT_ALL_SESSION_TRANSFERCOMPLETE. */ public int getCounterReceive_EVT_ALL_SESSION_TRANSFERCOMPLETE() { - return counterReceive_EVT_ALL_SESSION_TRANSFERCOMPLETE; + return counterReceive_EVT_ALL_SESSION_TRANSFERCOMPLETE.get(); } /** * @return Returns the counterReceive_EVT_CHANGE_SESSION_ID. */ public long getCounterReceive_EVT_CHANGE_SESSION_ID() { - return counterReceive_EVT_CHANGE_SESSION_ID; + return counterReceive_EVT_CHANGE_SESSION_ID.get(); } /** * @return Returns the counterReceive_EVT_ALL_SESSION_NOCONTEXTMANAGER. */ public long getCounterReceive_EVT_ALL_SESSION_NOCONTEXTMANAGER() { - return counterReceive_EVT_ALL_SESSION_NOCONTEXTMANAGER; + return counterReceive_EVT_ALL_SESSION_NOCONTEXTMANAGER.get(); } /** * @return Returns the sessionReplaceCounter. */ public long getSessionReplaceCounter() { - return sessionReplaceCounter; + return sessionReplaceCounter.get(); } /** * @return Returns the counterNoStateTransferred. */ public int getCounterNoStateTransferred() { - return counterNoStateTransferred; + return counterNoStateTransferred.get(); } public int getReceivedQueueSize() { @@ -391,6 +391,19 @@ this.notifyContainerListenersOnReplication = notifyContainerListenersOnReplication; } + /** + * @return the enableStatistics + */ + public boolean getEnableStatistics() { + return this.enableStatistics; + } + + /** + * @param enableStatistics the enableStatistics to set + */ + public void setEnableStatistics(boolean enableStatistics) { + this.enableStatistics = enableStatistics; + } // --------------------------------------------------------- Public Methods @@ -433,7 +446,9 @@ log.trace(sm.getString("deltaManager.sendMessage.newSession", name, sessionId)); } msg.setTimestamp(session.getCreationTime()); - counterSend_EVT_SESSION_CREATED++; + if (enableStatistics) { + counterSend_EVT_SESSION_CREATED.incrementAndGet(); + } send(msg); } } @@ -495,10 +510,12 @@ SessionMessage msg = new SessionMessageImpl(getName(), SessionMessage.EVT_CHANGE_SESSION_ID, data, orgSessionID, orgSessionID + "-" + System.currentTimeMillis()); msg.setTimestamp(System.currentTimeMillis()); - counterSend_EVT_CHANGE_SESSION_ID++; + if (enableStatistics) { + counterSend_EVT_CHANGE_SESSION_ID.incrementAndGet(); + } send(msg); - } catch (IOException e) { - log.error(sm.getString("deltaManager.unableSerializeSessionID", newSessionID), e); + } catch (IOException ioe) { + log.error(sm.getString("deltaManager.unableSerializeSessionID", newSessionID), ioe); } } } @@ -573,7 +590,9 @@ session.resetDeltaRequest(); // FIXME How inform other session id cache like SingleSignOn if (findSession(session.getIdInternal()) != null) { - sessionReplaceCounter++; + if (enableStatistics) { + sessionReplaceCounter.incrementAndGet(); + } // FIXME better is to grap this sessions again ! if (log.isWarnEnabled()) { log.warn(sm.getString("deltaManager.loading.existing.session", session.getIdInternal())); @@ -587,9 +606,9 @@ } catch (ClassNotFoundException e) { log.error(sm.getString("deltaManager.loading.cnfe", e), e); throw e; - } catch (IOException e) { - log.error(sm.getString("deltaManager.loading.ioe", e), e); - throw e; + } catch (IOException ioe) { + log.error(sm.getString("deltaManager.loading.ioe", ioe), ioe); + throw ioe; } } @@ -615,9 +634,9 @@ } // Flush and close the output stream oos.flush(); - } catch (IOException e) { - log.error(sm.getString("deltaManager.unloading.ioe", e), e); - throw e; + } catch (IOException ioe) { + log.error(sm.getString("deltaManager.unloading.ioe", ioe), ioe); + throw ioe; } // send object data as byte[] @@ -684,7 +703,9 @@ // set reference time stateTransferCreateSendTime = beforeSendTime; // request session state - counterSend_EVT_GET_ALL_SESSIONS++; + if (enableStatistics) { + counterSend_EVT_GET_ALL_SESSIONS.incrementAndGet(); + } stateTransferred = false; // FIXME This send call block the deploy thread, when sender waitForAck is enabled try { @@ -764,8 +785,8 @@ do { try { Thread.sleep(100); - } catch (Exception sleep) { - // + } catch (Exception ignore) { + // Ignore } reqNow = System.currentTimeMillis(); isTimeout = ((reqNow - reqStart) > (1000L * getStateTransferTimeout())); @@ -776,7 +797,7 @@ do { try { Thread.sleep(100); - } catch (Exception sleep) { + } catch (Exception ignore) { // Ignore } } while ((!getStateTransferred()) && (!isNoContextManagerReceived())); @@ -784,7 +805,9 @@ } } if (isTimeout) { - counterNoStateTransferred++; + if (enableStatistics) { + counterNoStateTransferred.incrementAndGet(); + } log.error(sm.getString("deltaManager.noSessionState", getName(), new Date(beforeSendTime), Long.valueOf(reqNow - beforeSendTime))); } else if (isNoContextManagerReceived()) { @@ -894,17 +917,21 @@ return null; } if (session.isDirty()) { - counterSend_EVT_SESSION_DELTA++; + if (enableStatistics) { + counterSend_EVT_SESSION_DELTA.incrementAndGet(); + } msg = new SessionMessageImpl(getName(), SessionMessage.EVT_SESSION_DELTA, session.getDiff(), sessionId, sessionId + "-" + System.currentTimeMillis()); } - } catch (IOException x) { - log.error(sm.getString("deltaManager.createMessage.unableCreateDeltaRequest", sessionId), x); + } catch (IOException ioe) { + log.error(sm.getString("deltaManager.createMessage.unableCreateDeltaRequest", sessionId), ioe); return null; } if (msg == null) { if (!expires && !session.isPrimarySession()) { - counterSend_EVT_SESSION_ACCESSED++; + if (enableStatistics) { + counterSend_EVT_SESSION_ACCESSED.incrementAndGet(); + } msg = new SessionMessageImpl(getName(), SessionMessage.EVT_SESSION_ACCESSED, null, sessionId, sessionId + "-" + System.currentTimeMillis()); if (log.isDebugEnabled()) { @@ -923,7 +950,9 @@ if (!expires && (msg == null)) { long replDelta = System.currentTimeMillis() - session.getLastTimeReplicated(); if (session.getMaxInactiveInterval() >= 0 && replDelta > (session.getMaxInactiveInterval() * 1000L)) { - counterSend_EVT_SESSION_ACCESSED++; + if (enableStatistics) { + counterSend_EVT_SESSION_ACCESSED.incrementAndGet(); + } msg = new SessionMessageImpl(getName(), SessionMessage.EVT_SESSION_ACCESSED, null, sessionId, sessionId + "-" + System.currentTimeMillis()); if (log.isDebugEnabled()) { @@ -959,25 +988,25 @@ } } rejectedSessions = 0; - sessionReplaceCounter = 0; - counterNoStateTransferred = 0; + sessionReplaceCounter.set(0); + counterNoStateTransferred.set(0); setMaxActive(getActiveSessions()); - counterReceive_EVT_ALL_SESSION_DATA = 0; - counterReceive_EVT_GET_ALL_SESSIONS = 0; - counterReceive_EVT_SESSION_ACCESSED = 0; - counterReceive_EVT_SESSION_CREATED = 0; - counterReceive_EVT_SESSION_DELTA = 0; - counterReceive_EVT_SESSION_EXPIRED = 0; - counterReceive_EVT_ALL_SESSION_TRANSFERCOMPLETE = 0; - counterReceive_EVT_CHANGE_SESSION_ID = 0; - counterSend_EVT_ALL_SESSION_DATA = 0; - counterSend_EVT_GET_ALL_SESSIONS = 0; - counterSend_EVT_SESSION_ACCESSED = 0; - counterSend_EVT_SESSION_CREATED = 0; - counterSend_EVT_SESSION_DELTA = 0; - counterSend_EVT_SESSION_EXPIRED = 0; - counterSend_EVT_ALL_SESSION_TRANSFERCOMPLETE = 0; - counterSend_EVT_CHANGE_SESSION_ID = 0; + counterReceive_EVT_ALL_SESSION_DATA.set(0); + counterReceive_EVT_GET_ALL_SESSIONS.set(0); + counterReceive_EVT_SESSION_ACCESSED.set(0); + counterReceive_EVT_SESSION_CREATED.set(0); + counterReceive_EVT_SESSION_DELTA.set(0); + counterReceive_EVT_SESSION_EXPIRED.set(0); + counterReceive_EVT_ALL_SESSION_TRANSFERCOMPLETE.set(0); + counterReceive_EVT_CHANGE_SESSION_ID.set(0); + counterSend_EVT_ALL_SESSION_DATA.set(0); + counterSend_EVT_GET_ALL_SESSIONS.set(0); + counterSend_EVT_SESSION_ACCESSED.set(0); + counterSend_EVT_SESSION_CREATED.set(0); + counterSend_EVT_SESSION_DELTA.set(0); + counterSend_EVT_SESSION_EXPIRED.set(0); + counterSend_EVT_ALL_SESSION_TRANSFERCOMPLETE.set(0); + counterSend_EVT_CHANGE_SESSION_ID.set(0); } @@ -990,7 +1019,9 @@ */ protected void sessionExpired(String id) { if (cluster.getMembers().length > 0) { - counterSend_EVT_SESSION_EXPIRED++; + if (enableStatistics) { + counterSend_EVT_SESSION_EXPIRED.incrementAndGet(); + } SessionMessage msg = new SessionMessageImpl(getName(), SessionMessage.EVT_SESSION_EXPIRED, null, id, id + "-EXPIRED-MSG"); msg.setTimestamp(System.currentTimeMillis()); @@ -1093,8 +1124,8 @@ // we didn't recognize the message type, do nothing break; } // switch - } catch (Exception x) { - log.error(sm.getString("deltaManager.receiveMessage.error", getName()), x); + } catch (Exception e) { + log.error(sm.getString("deltaManager.receiveMessage.error", getName()), e); } finally { currentThread.setContextClassLoader(contextLoader); } @@ -1110,7 +1141,9 @@ * @param sender Member which sent the message */ protected void handleALL_SESSION_TRANSFERCOMPLETE(SessionMessage msg, Member sender) { - counterReceive_EVT_ALL_SESSION_TRANSFERCOMPLETE++; + if (enableStatistics) { + counterReceive_EVT_ALL_SESSION_TRANSFERCOMPLETE.incrementAndGet(); + } if (log.isDebugEnabled()) { log.debug(sm.getString("deltaManager.receiveMessage.transfercomplete", getName(), sender.getHost(), Integer.valueOf(sender.getPort()))); @@ -1129,7 +1162,9 @@ * @throws ClassNotFoundException Serialization error */ protected void handleSESSION_DELTA(SessionMessage msg, Member sender) throws IOException, ClassNotFoundException { - counterReceive_EVT_SESSION_DELTA++; + if (enableStatistics) { + counterReceive_EVT_SESSION_DELTA.incrementAndGet(); + } byte[] delta = msg.getSession(); DeltaSession session = (DeltaSession) findSession(msg.getSessionID()); if (session == null) { @@ -1154,7 +1189,9 @@ * @throws IOException Propagated IO error */ protected void handleSESSION_ACCESSED(SessionMessage msg, Member sender) throws IOException { - counterReceive_EVT_SESSION_ACCESSED++; + if (enableStatistics) { + counterReceive_EVT_SESSION_ACCESSED.incrementAndGet(); + } DeltaSession session = (DeltaSession) findSession(msg.getSessionID()); if (session != null) { if (log.isDebugEnabled()) { @@ -1175,7 +1212,9 @@ * @throws IOException Propagated IO error */ protected void handleSESSION_EXPIRED(SessionMessage msg, Member sender) throws IOException { - counterReceive_EVT_SESSION_EXPIRED++; + if (enableStatistics) { + counterReceive_EVT_SESSION_EXPIRED.incrementAndGet(); + } DeltaSession session = (DeltaSession) findSession(msg.getSessionID()); if (session != null) { if (log.isDebugEnabled()) { @@ -1192,7 +1231,9 @@ * @param sender Member which sent the message */ protected void handleSESSION_CREATED(SessionMessage msg, Member sender) { - counterReceive_EVT_SESSION_CREATED++; + if (enableStatistics) { + counterReceive_EVT_SESSION_CREATED.incrementAndGet(); + } if (log.isDebugEnabled()) { log.debug(sm.getString("deltaManager.receiveMessage.createNewSession", getName(), msg.getSessionID())); } @@ -1220,7 +1261,9 @@ */ protected void handleALL_SESSION_DATA(SessionMessage msg, Member sender) throws ClassNotFoundException, IOException { - counterReceive_EVT_ALL_SESSION_DATA++; + if (enableStatistics) { + counterReceive_EVT_ALL_SESSION_DATA.incrementAndGet(); + } if (log.isDebugEnabled()) { log.debug(sm.getString("deltaManager.receiveMessage.allSessionDataBegin", getName())); } @@ -1242,7 +1285,9 @@ * @throws IOException IO error sending messages */ protected void handleGET_ALL_SESSIONS(SessionMessage msg, Member sender) throws IOException { - counterReceive_EVT_GET_ALL_SESSIONS++; + if (enableStatistics) { + counterReceive_EVT_GET_ALL_SESSIONS.incrementAndGet(); + } // get a list of all the session from this manager if (log.isDebugEnabled()) { log.debug(sm.getString("deltaManager.receiveMessage.unloadingBegin", getName())); @@ -1266,7 +1311,7 @@ if (getSendAllSessionsWaitTime() > 0 && remain > 0) { try { Thread.sleep(getSendAllSessionsWaitTime()); - } catch (Exception sleep) { + } catch (Exception ignore) { // Ignore } } @@ -1279,7 +1324,9 @@ if (log.isDebugEnabled()) { log.debug(sm.getString("deltaManager.createMessage.allSessionTransferred", getName())); } - counterSend_EVT_ALL_SESSION_TRANSFERCOMPLETE++; + if (enableStatistics) { + counterSend_EVT_ALL_SESSION_TRANSFERCOMPLETE.incrementAndGet(); + } cluster.send(newmsg, sender); } @@ -1292,7 +1339,9 @@ * @throws IOException IO error with serialization */ protected void handleCHANGE_SESSION_ID(SessionMessage msg, Member sender) throws IOException { - counterReceive_EVT_CHANGE_SESSION_ID++; + if (enableStatistics) { + counterReceive_EVT_CHANGE_SESSION_ID.incrementAndGet(); + } DeltaSession session = (DeltaSession) findSession(msg.getSessionID()); if (session != null) { String newSessionID = deserializeSessionId(msg.getSession()); @@ -1310,7 +1359,9 @@ * @param sender Member which sent the message */ protected void handleALL_SESSION_NOCONTEXTMANAGER(SessionMessage msg, Member sender) { - counterReceive_EVT_ALL_SESSION_NOCONTEXTMANAGER++; + if (enableStatistics) { + counterReceive_EVT_ALL_SESSION_NOCONTEXTMANAGER.incrementAndGet(); + } if (log.isDebugEnabled()) { log.debug(sm.getString("deltaManager.receiveMessage.noContextManager", getName(), sender.getHost(), Integer.valueOf(sender.getPort()))); @@ -1338,7 +1389,9 @@ if (log.isDebugEnabled()) { log.debug(sm.getString("deltaManager.createMessage.allSessionData", getName())); } - counterSend_EVT_ALL_SESSION_DATA++; + if (enableStatistics) { + counterSend_EVT_ALL_SESSION_DATA.incrementAndGet(); + } int sendOptions = Channel.SEND_OPTIONS_SYNCHRONIZED_ACK | Channel.SEND_OPTIONS_USE_ACK; cluster.send(newmsg, sender, sendOptions); } diff -Nru tomcat10-10.1.40/java/org/apache/catalina/ha/session/DeltaRequest.java tomcat10-10.1.52/java/org/apache/catalina/ha/session/DeltaRequest.java --- tomcat10-10.1.40/java/org/apache/catalina/ha/session/DeltaRequest.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/ha/session/DeltaRequest.java 2026-01-23 19:33:36.000000000 +0000 @@ -147,8 +147,8 @@ if (!this.actionPool.isEmpty()) { try { info = actionPool.removeFirst(); - } catch (Exception x) { - log.error(sm.getString("deltaRequest.removeUnable"), x); + } catch (Exception e) { + log.error(sm.getString("deltaRequest.removeUnable"), e); info = new AttributeInfo(type, action, name, value); } info.init(type, action, name, value); @@ -251,8 +251,8 @@ AttributeInfo info = actions.removeFirst(); info.recycle(); actionPool.addLast(info); - } catch (Exception x) { - log.error(sm.getString("deltaRequest.removeUnable"), x); + } catch (Exception e) { + log.error(sm.getString("deltaRequest.removeUnable"), e); } } } @@ -264,8 +264,8 @@ public void setSessionId(String sessionId) { this.sessionId = sessionId; if (sessionId == null) { - Exception e = new Exception(sm.getString("deltaRequest.ssid.null")); - log.error(sm.getString("deltaRequest.ssid.null"), e.fillInStackTrace()); + String msg = sm.getString("deltaRequest.ssid.null"); + log.error(msg, new Exception(msg)); } } @@ -293,8 +293,8 @@ if (!this.actionPool.isEmpty()) { try { info = actionPool.removeFirst(); - } catch (Exception x) { - log.error(sm.getString("deltaRequest.removeUnable"), x); + } catch (Exception e) { + log.error(sm.getString("deltaRequest.removeUnable"), e); info = new AttributeInfo(); } } else { @@ -431,9 +431,8 @@ @Override public String toString() { - return "AttributeInfo[type=" + getType() + ", action=" + getAction() + - ", name=" + getName() + ", value=" + getValue() + - ", addr=" + super.toString() + ']'; + return "AttributeInfo[type=" + getType() + ", action=" + getAction() + ", name=" + getName() + ", value=" + + getValue() + ", addr=" + super.toString() + ']'; } } diff -Nru tomcat10-10.1.40/java/org/apache/catalina/ha/session/JvmRouteBinderValve.java tomcat10-10.1.52/java/org/apache/catalina/ha/session/JvmRouteBinderValve.java --- tomcat10-10.1.40/java/org/apache/catalina/ha/session/JvmRouteBinderValve.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/ha/session/JvmRouteBinderValve.java 2026-01-23 19:33:36.000000000 +0000 @@ -58,8 +58,6 @@ * You can enable this mod_jk turnover mode via JMX before you drop a node to all backup nodes! Set enable true on all * JvmRouteBinderValve backups, disable worker at mod_jk and then drop node and restart it! Then enable mod_jk worker * and disable JvmRouteBinderValves again. This use case means that only requested sessions are migrated. - * - * @author Peter Rossbach */ public class JvmRouteBinderValve extends ValveBase implements ClusterValve { @@ -258,8 +256,8 @@ Session catalinaSession = null; try { catalinaSession = getManager(request).findSession(sessionId); - } catch (IOException e) { - // Hups! + } catch (IOException ignore) { + // Error looking for session using old session ID. Treat it as not found. } String id = sessionId.substring(0, index); String newSessionID = id + "." + localJvmRoute; @@ -270,11 +268,11 @@ } else { try { catalinaSession = getManager(request).findSession(newSessionID); - } catch (IOException e) { - // Hups! + } catch (IOException ignore) { + // Error looking for session using new session ID. Treat it as not found. } if (catalinaSession != null) { - // session is rewrite at other request, rewrite this also + // Session was rewritten in other, concurrent request. Rewrite this request also. changeRequestSessionID(request, sessionId, newSessionID); } else { if (log.isDebugEnabled()) { diff -Nru tomcat10-10.1.40/java/org/apache/catalina/ha/session/LocalStrings_ja.properties tomcat10-10.1.52/java/org/apache/catalina/ha/session/LocalStrings_ja.properties --- tomcat10-10.1.40/java/org/apache/catalina/ha/session/LocalStrings_ja.properties 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/ha/session/LocalStrings_ja.properties 2026-01-23 19:33:36.000000000 +0000 @@ -82,7 +82,7 @@ jvmRoute.changeSession=セッションを [{0}] から [{1}] へ変更しました。 jvmRoute.failover=他の jvmRoute へのフェールオーバーを検出しました。元のルートは [{0}]、新しいルートは [{1}]、セッション ID は [{2}] です。 jvmRoute.foundManager=Cluster Manager [{0}] を [{1}] で発見しました -jvmRoute.missingJvmRouteAttribute=jvmRoute 属性にエンジンが指定されていません。 +jvmRoute.missingJvmRouteAttribute=Engine に jvmRoute 属性が指定されていません! jvmRoute.noCluster=JvmRouterBinderValveは設定されていますが、クラスタリングは使用されていません。 PersistentManagerが使用されている場合、フェールオーバーは引き続き機能します。 jvmRoute.notFoundManager=[{0}]でCluster Managerが見つかりません。 jvmRoute.set.originalsessionid=オリジナルSession idをリクエスト属性[{0}]の値:[{1}]で設定します。 diff -Nru tomcat10-10.1.40/java/org/apache/catalina/ha/session/SessionMessage.java tomcat10-10.1.52/java/org/apache/catalina/ha/session/SessionMessage.java --- tomcat10-10.1.40/java/org/apache/catalina/ha/session/SessionMessage.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/ha/session/SessionMessage.java 2026-01-23 19:33:36.000000000 +0000 @@ -47,8 +47,8 @@ int EVT_SESSION_EXPIRED = 2; /** - * Event type used when a session has been accessed (ie, last access time has been updated). This is used so that the - * replicated sessions will not expire on the network + * Event type used when a session has been accessed (ie, last access time has been updated). This is used so that + * the replicated sessions will not expire on the network */ int EVT_SESSION_ACCESSED = 3; diff -Nru tomcat10-10.1.40/java/org/apache/catalina/ha/session/SessionMessageImpl.java tomcat10-10.1.52/java/org/apache/catalina/ha/session/SessionMessageImpl.java --- tomcat10-10.1.40/java/org/apache/catalina/ha/session/SessionMessageImpl.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/ha/session/SessionMessageImpl.java 2026-01-23 19:33:36.000000000 +0000 @@ -20,9 +20,7 @@ import org.apache.catalina.ha.ClusterMessageBase; /** - * Session cluster message - * - * @author Peter Rossbach + * Session cluster message. */ public class SessionMessageImpl extends ClusterMessageBase implements SessionMessage { diff -Nru tomcat10-10.1.40/java/org/apache/catalina/ha/tcp/Constants.java tomcat10-10.1.52/java/org/apache/catalina/ha/tcp/Constants.java --- tomcat10-10.1.40/java/org/apache/catalina/ha/tcp/Constants.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/ha/tcp/Constants.java 2026-01-23 19:33:36.000000000 +0000 @@ -18,8 +18,6 @@ /** * Manifest constants for the org.apache.catalina.ha.tcp package. - * - * @author Peter Rossbach */ public class Constants { diff -Nru tomcat10-10.1.40/java/org/apache/catalina/ha/tcp/ReplicationValve.java tomcat10-10.1.52/java/org/apache/catalina/ha/tcp/ReplicationValve.java --- tomcat10-10.1.40/java/org/apache/catalina/ha/tcp/ReplicationValve.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/ha/tcp/ReplicationValve.java 2026-01-23 19:33:36.000000000 +0000 @@ -47,21 +47,14 @@ 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. - *

    *

    * This Valve may be attached to any Container, depending on the granularity of the logging you wish to perform. - *

    *

    * primaryIndicator=true, then the request attribute org.apache.catalina.ha.tcp.isPrimarySession. is set true, * when request processing is at sessions primary node. - *

    - * - * @author Craig R. McClanahan - * @author Peter Rossbach */ public class ReplicationValve extends ValveBase implements ClusterValve { @@ -377,9 +370,9 @@ if (isCrossContext) { sendCrossContextSession(); } - } catch (Exception x) { + } catch (Exception e) { // FIXME we have a lot of sends, but the trouble with one node stops the correct replication to other nodes! - log.error(sm.getString("ReplicationValve.send.failure"), x); + log.error(sm.getString("ReplicationValve.send.failure"), e); } finally { if (doStatistics()) { updateStats(totalstart, start, isAsync); @@ -506,8 +499,8 @@ for (String invalidId : invalidIds) { try { send(manager, invalidId); - } catch (Exception x) { - log.error(sm.getString("ReplicationValve.send.invalid.failure", invalidId), x); + } catch (Exception e) { + log.error(sm.getString("ReplicationValve.send.invalid.failure", invalidId), e); } } } @@ -545,8 +538,7 @@ Long.valueOf(totalSendTime.longValue() / nrOfRequests.longValue()), Long.valueOf(nrOfRequests.longValue()), Long.valueOf(nrOfSendRequests.longValue()), Long.valueOf(nrOfCrossContextSendRequests.longValue()), - Long.valueOf(nrOfFilterRequests.longValue()), - Long.valueOf(totalRequestTime.longValue()), + Long.valueOf(nrOfFilterRequests.longValue()), Long.valueOf(totalRequestTime.longValue()), Long.valueOf(totalSendTime.longValue()))); } } diff -Nru tomcat10-10.1.40/java/org/apache/catalina/ha/tcp/SendMessageData.java tomcat10-10.1.52/java/org/apache/catalina/ha/tcp/SendMessageData.java --- tomcat10-10.1.40/java/org/apache/catalina/ha/tcp/SendMessageData.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/ha/tcp/SendMessageData.java 2026-01-23 19:33:36.000000000 +0000 @@ -18,9 +18,6 @@ import org.apache.catalina.tribes.Member; -/** - * @author Peter Rossbach - */ public class SendMessageData { private Object message; diff -Nru tomcat10-10.1.40/java/org/apache/catalina/ha/tcp/SimpleTcpCluster.java tomcat10-10.1.52/java/org/apache/catalina/ha/tcp/SimpleTcpCluster.java --- tomcat10-10.1.40/java/org/apache/catalina/ha/tcp/SimpleTcpCluster.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/ha/tcp/SimpleTcpCluster.java 2026-01-23 19:33:36.000000000 +0000 @@ -59,9 +59,6 @@ /** * A Cluster implementation using simple multicast. Responsible for setting up a cluster and provides callers * with a valid multicast receiver/sender. - * - * @author Remy Maucherat - * @author Peter Rossbach */ public class SimpleTcpCluster extends LifecycleMBeanBase implements CatalinaCluster, MembershipListener, ChannelListener { @@ -345,8 +342,8 @@ try { manager = managerTemplate.cloneFromTemplate(); manager.setName(name); - } catch (Exception x) { - log.error(sm.getString("simpleTcpCluster.clustermanager.cloneFailed"), x); + } catch (Exception e) { + log.error(sm.getString("simpleTcpCluster.clustermanager.cloneFailed"), e); manager = new DeltaManager(); } finally { if (manager != null) { @@ -470,9 +467,9 @@ clusterDeployer.start(); } registerMember(channel.getLocalMember(false)); - } catch (Exception x) { - log.error(sm.getString("simpleTcpCluster.startUnable"), x); - throw new LifecycleException(x); + } catch (Exception e) { + log.error(sm.getString("simpleTcpCluster.startUnable"), e); + throw new LifecycleException(e); } setState(LifecycleState.STARTING); @@ -560,8 +557,8 @@ channel.removeChannelListener(this); channel.removeMembershipListener(this); this.unregisterClusterValve(); - } catch (Exception x) { - log.error(sm.getString("simpleTcpCluster.stopUnable"), x); + } catch (Exception e) { + log.error(sm.getString("simpleTcpCluster.stopUnable"), e); } channel.setUtilityExecutor(null); @@ -612,8 +609,8 @@ log.debug(sm.getString("simpleTcpCluster.noMembers", msg)); } } - } catch (Exception x) { - log.error(sm.getString("simpleTcpCluster.sendFailed"), x); + } catch (Exception e) { + log.error(sm.getString("simpleTcpCluster.sendFailed"), e); } } @@ -631,8 +628,8 @@ // Notify our interested LifecycleListeners fireLifecycleEvent(AFTER_MEMBERREGISTER_EVENT, member); - } catch (Exception x) { - log.error(sm.getString("simpleTcpCluster.member.addFailed"), x); + } catch (Exception e) { + log.error(sm.getString("simpleTcpCluster.member.addFailed"), e); } } @@ -651,8 +648,8 @@ // Notify our interested LifecycleListeners fireLifecycleEvent(AFTER_MEMBERUNREGISTER_EVENT, member); - } catch (Exception x) { - log.error(sm.getString("simpleTcpCluster.member.removeFailed"), x); + } catch (Exception e) { + log.error(sm.getString("simpleTcpCluster.member.removeFailed"), e); } } diff -Nru tomcat10-10.1.40/java/org/apache/catalina/loader/LocalStrings.properties tomcat10-10.1.52/java/org/apache/catalina/loader/LocalStrings.properties --- tomcat10-10.1.40/java/org/apache/catalina/loader/LocalStrings.properties 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/loader/LocalStrings.properties 2026-01-23 19:33:36.000000000 +0000 @@ -50,7 +50,7 @@ webappClassLoader.restrictedPackage=Security violation, attempt to use restricted class [{0}] webappClassLoader.securityException=Security exception trying to find class [{0}] in findClassInternal [{1}] webappClassLoader.stackTrace=The web application [{0}] appears to have started a thread named [{1}] but has failed to stop it. This is very likely to create a memory leak. Stack trace of thread:{2} -webappClassLoader.stackTraceRequestThread=The web application [{0}] is still processing a request that has yet to finish. This is very likely to create a memory leak. You can control the time allowed for requests to finish by using the unloadDelay attribute of the standard Context implementation. Stack trace of request processing thread:[{2}] +webappClassLoader.stackTraceRequestThread=The thread [{1}] of web application [{0}] is still processing a request that has yet to finish. This is very likely to create a memory leak. You can control the time allowed for requests to finish by using the unloadDelay attribute of the standard Context implementation. Stack trace of request processing thread:[{2}] webappClassLoader.stopThreadFail=Failed to terminate thread named [{0}] for web application [{1}] webappClassLoader.stopTimerThreadFail=Failed to terminate TimerThread named [{0}] for web application [{1}] webappClassLoader.stopped=Illegal access: this web application instance has been stopped already. Could not load [{0}]. The following stack trace is thrown for debugging purposes as well as to attempt to terminate the thread which caused the illegal access. diff -Nru tomcat10-10.1.40/java/org/apache/catalina/loader/LocalStrings_fr.properties tomcat10-10.1.52/java/org/apache/catalina/loader/LocalStrings_fr.properties --- tomcat10-10.1.40/java/org/apache/catalina/loader/LocalStrings_fr.properties 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/loader/LocalStrings_fr.properties 2026-01-23 19:33:36.000000000 +0000 @@ -50,7 +50,7 @@ webappClassLoader.restrictedPackage=Violation de sécurité en essayant d''utiliser à une classe à accès restreint [{0}] webappClassLoader.securityException=Exception de sécurité en essayant de trouver la classe [{0}] dans findClassInternal [{1}] webappClassLoader.stackTrace=L''application web [{0}] semble avoir démarré un thread nommé [{1}] mais ne l''a pas arrêté, ce qui va probablement créer une fuite de mémoire ; la trace du thread est : {2} -webappClassLoader.stackTraceRequestThread=Une requête de l''application web [{0}] est toujours en cours, ce qui causera certainement une fuite de mémoire, vous pouvez contrôler le temps alloué en utilisant l''attribut unloadDelay de l''implémentation standard de Context ; trace du fil d’exécution de la requête : [{2}] +webappClassLoader.stackTraceRequestThread=Le thread [{1}] de l''application web [{0}] est toujours en cours, ce qui risque de causer une fuite de mémoire. Vous pouvez contrôler le temps alloué en utilisant l''attribut unloadDelay de l''implémentation standard de Context ; trace de la pile d''exécution de la requête : [{2}] webappClassLoader.stopThreadFail=Impossible de terminer le thread nommé [{0}] pour l''application [{1}] webappClassLoader.stopTimerThreadFail=Echec de l''arrêt du TimerThread nommé [{0}] pour l''application web [{1}] webappClassLoader.stopped=Impossible de charger [{0}], ce chargeur de classes a déjà été arrêté diff -Nru tomcat10-10.1.40/java/org/apache/catalina/loader/LocalStrings_ja.properties tomcat10-10.1.52/java/org/apache/catalina/loader/LocalStrings_ja.properties --- tomcat10-10.1.40/java/org/apache/catalina/loader/LocalStrings_ja.properties 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/loader/LocalStrings_ja.properties 2026-01-23 19:33:36.000000000 +0000 @@ -50,7 +50,7 @@ webappClassLoader.restrictedPackage=セキュリティー違反。制限されたクラス [{0}] を使おうとしました。 webappClassLoader.securityException=indClassInternal [{1}] でクラス [{0}] を検索中のセキュリティ例外です webappClassLoader.stackTrace=Webアプリケーション [{0}] は [{1}] という名前のスレッドを開始したようですが、停止に失敗しました。これはメモリリークを引き起こす可能性が非常に高いです。スレッドのスタックトレース: {2} -webappClassLoader.stackTraceRequestThread=Webアプリケーション[{0}]はまだ完了していないリクエストを処理しています。 これはメモリリークを引き起こす可能性が非常に高いです。 リクエストの終了時間は、StandardContext実装のunloadDelay属性を使用して制御できます。 リクエスト処理スレッドのスタックトレース:[{2}] +webappClassLoader.stackTraceRequestThread=Webアプリケーション[{0}]のスレッド[{1}]はまだ完了していないリクエストを処理しています。 これはメモリリークを引き起こす可能性が非常に高いです。 リクエストの終了時間は、StandardContext実装のunloadDelay属性を使用して制御できます。 リクエスト処理スレッドのスタックトレース:[{2}] webappClassLoader.stopThreadFail=Web アプリケーション [{1}] のスレッド [{0}] は終了できません。 webappClassLoader.stopTimerThreadFail=Webアプリケーション [{1}] の [{0}] という名前のTimerThreadを終了できませんでした webappClassLoader.stopped=不正なアクセス: このWebアプリケーションのインスタンスは既に停止されています Could not load [{0}]. 不正なアクセスを引き起こしたスレッドを終了させ、投げられたエラーによりデバッグ用に次のスタックトレースが生成されましたが,機能に影響はありません diff -Nru tomcat10-10.1.40/java/org/apache/catalina/loader/LocalStrings_ko.properties tomcat10-10.1.52/java/org/apache/catalina/loader/LocalStrings_ko.properties --- tomcat10-10.1.40/java/org/apache/catalina/loader/LocalStrings_ko.properties 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/loader/LocalStrings_ko.properties 2026-01-23 19:33:36.000000000 +0000 @@ -50,7 +50,7 @@ webappClassLoader.restrictedPackage=보안 위반 행위: 제한된 클래스 [{0}]을(를) 사용하려 시도했습니다. webappClassLoader.securityException=findClassInternal에서, 클래스 [{0}]을(를) 찾으려 시도 중 보안 예외 발생: [{1}] webappClassLoader.stackTrace=웹 애플리케이션 [{0}]이(가) [{1}](이)라는 이름의 쓰레드를 시작시킨 것으로 보이지만, 해당 쓰레드를 중지시키지 못했습니다. 이는 메모리 누수를 유발할 가능성이 큽니다. 해당 쓰레드의 스택 트레이스:{2} -webappClassLoader.stackTraceRequestThread=웹 애플리케이션 [{0}]이(가) 여전히 완료되지 않은 요청을 처리하고 있습니다. 이는 메모리 누수를 유발할 가능성이 높습니다. 표준 컨텍스트 구현의 unloadDelay 속성을 이용하여, 요청 완료 허용 시간을 통제할 수 있습니다. 요청 처리 쓰레드의 스택 트레이스:[{2}] +webappClassLoader.stackTraceRequestThread=웹 애플리케이션 [{0}]의 쓰레드 [{1}]가 여전히 완료되지 않은 요청을 처리하고 있습니다. 이는 메모리 누수를 유발할 가능성이 높습니다. 표준 컨텍스트 구현의 unloadDelay 속성을 이용하여, 요청 완료 허용 시간을 통제할 수 있습니다. 요청 처리 쓰레드의 스택 트레이스:[{2}] webappClassLoader.stopThreadFail=웹 애플리케이션 [{1}]을 위한, [{0}](이)라는 이름의 쓰레드를 종료시키지 못했습니다. webappClassLoader.stopTimerThreadFail=웹 애플리케이션 [{1}]을(를) 위한, [{0}](이)라는 이름의 TimerThread를 종료시키지 못했습니다. webappClassLoader.stopped=불허되는 접근: 이 웹 애플리케이션 인스턴스는 이미 중지되었습니다. [{0}]을(를) 로드할 수 없습니다. 디버그 목적 및 불허되는 접근을 발생시킨 해당 쓰레드를 종료시키기 위한 시도로서, 다음 스택 트레이스가 생성됩니다. diff -Nru tomcat10-10.1.40/java/org/apache/catalina/loader/LocalStrings_zh_CN.properties tomcat10-10.1.52/java/org/apache/catalina/loader/LocalStrings_zh_CN.properties --- tomcat10-10.1.40/java/org/apache/catalina/loader/LocalStrings_zh_CN.properties 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/loader/LocalStrings_zh_CN.properties 2026-01-23 19:33:36.000000000 +0000 @@ -50,7 +50,7 @@ webappClassLoader.restrictedPackage=安全冲突,尝试使用受限类[{0}] webappClassLoader.securityException=尝试在findClassInternal[{1}]中查找类[{0}]时出现安全异常 webappClassLoader.stackTrace=Web应用程序[{0}]似乎启动了一个名为[{1}]的线程,但未能停止它。这很可能会造成内存泄漏。线程的堆栈跟踪:[{2}] -webappClassLoader.stackTraceRequestThread=web应用程序[{0}]仍在处理一个尚未完成的请求。这很可能会造成内存泄漏。您可以使用标准上下文实现的unloadDelay属性来控制请求完成所允许的时间。请求处理线程的堆栈跟踪:[{2}] +webappClassLoader.stackTraceRequestThread=web应用程序[{0}]中的线程[{1}]仍在处理一个尚未完成的请求。这很可能会造成内存泄漏。您可以使用标准上下文实现的unloadDelay属性来控制请求完成所允许的时间。请求处理线程的堆栈跟踪:[{2}] webappClassLoader.stopThreadFail=为web应用程序[{1}]终止线程[{0}]失败 webappClassLoader.stopTimerThreadFail=无法终止名为[{0}]的TimerThread,web应用程序:[{1}] webappClassLoader.stopped=非法访问:此Web应用程序实例已停止。无法加载[{0}]。为了调试以及终止导致非法访问的线程,将抛出以下堆栈跟踪。 diff -Nru tomcat10-10.1.40/java/org/apache/catalina/loader/ResourceEntry.java tomcat10-10.1.52/java/org/apache/catalina/loader/ResourceEntry.java --- tomcat10-10.1.40/java/org/apache/catalina/loader/ResourceEntry.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/loader/ResourceEntry.java 2026-01-23 19:33:36.000000000 +0000 @@ -18,8 +18,6 @@ /** * Resource entry. - * - * @author Remy Maucherat */ public class ResourceEntry { diff -Nru tomcat10-10.1.40/java/org/apache/catalina/loader/WebappClassLoaderBase.java tomcat10-10.1.52/java/org/apache/catalina/loader/WebappClassLoaderBase.java --- tomcat10-10.1.40/java/org/apache/catalina/loader/WebappClassLoaderBase.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/loader/WebappClassLoaderBase.java 2026-01-23 19:33:36.000000000 +0000 @@ -114,9 +114,6 @@ * IMPLEMENTATION NOTE - As of 8.0, this class loader implements {@link InstrumentableClassLoader}, * permitting web application classes to instrument other classes in the same web application. It does not permit * instrumentation of system or container classes or classes in other web apps. - * - * @author Remy Maucherat - * @author Craig R. McClanahan */ public abstract class WebappClassLoaderBase extends URLClassLoader implements Lifecycle, InstrumentableClassLoader, WebappProperties, PermissionCheck { @@ -1104,13 +1101,13 @@ while ((numRead = stream.read(buf)) >= 0) { baos.write(buf, 0, numRead); } - } catch (IOException e) { - log.error(sm.getString("webappClassLoader.transformError", name), e); + } catch (IOException ioe) { + log.error(sm.getString("webappClassLoader.transformError", name), ioe); return null; } finally { try { stream.close(); - } catch (IOException e) { + } catch (IOException ignore) { // Ignore } } @@ -1138,7 +1135,7 @@ stream = url.openStream(); } } - } catch (IOException e) { + } catch (IOException ioe) { // Ignore } if (stream != null) { @@ -1396,9 +1393,8 @@ // It is not permitted to load resources once the web application has // been stopped. if (!state.isAvailable()) { - String msg = sm.getString("webappClassLoader.stopped", resource); - IllegalStateException ise = new IllegalStateException(msg); - log.info(msg, ise); + IllegalStateException ise = new IllegalStateException(sm.getString("webappClassLoader.stopped", resource)); + log.info(ise.getMessage(), ise); throw ise; } } @@ -2344,7 +2340,11 @@ if (pkg != null) { boolean sealCheck = true; if (pkg.isSealed()) { - sealCheck = pkg.isSealed(codeBase); + if (codeBase != null) { + sealCheck = pkg.isSealed(codeBase); + } else { + sealCheck = false; + } } else { sealCheck = manifest == null || !isPackageSealed(packageName, manifest); } diff -Nru tomcat10-10.1.40/java/org/apache/catalina/loader/WebappLoader.java tomcat10-10.1.52/java/org/apache/catalina/loader/WebappLoader.java --- tomcat10-10.1.40/java/org/apache/catalina/loader/WebappLoader.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/loader/WebappLoader.java 2026-01-23 19:33:36.000000000 +0000 @@ -22,9 +22,9 @@ import java.io.FilePermission; import java.io.IOException; import java.lang.reflect.Constructor; +import java.net.URISyntaxException; import java.net.URL; import java.net.URLClassLoader; -import java.nio.charset.StandardCharsets; import javax.management.ObjectName; @@ -43,7 +43,6 @@ import org.apache.tomcat.jakartaee.EESpecProfile; import org.apache.tomcat.jakartaee.EESpecProfiles; import org.apache.tomcat.util.ExceptionUtils; -import org.apache.tomcat.util.buf.UDecoder; import org.apache.tomcat.util.compat.JreCompat; import org.apache.tomcat.util.modeler.Registry; import org.apache.tomcat.util.res.StringManager; @@ -56,9 +55,6 @@ * This class loader is configured via the Resources children of its Context prior to calling start(). When * a new class is required, these Resources will be consulted first to locate the class. If it is not present, the * system class loader will be used instead. - * - * @author Craig R. McClanahan - * @author Remy Maucherat */ public class WebappLoader extends LifecycleMBeanBase implements Loader { @@ -322,13 +318,13 @@ MigrationUtil.addJakartaEETransformer(classLoader, getJakartaConverter()); } - // Configure our repositories - setClassPath(); - setPermissions(); classLoader.start(); + // Configure our repositories + setClassPath(); + String contextName = context.getName(); if (!contextName.startsWith("/")) { contextName = "/" + contextName; @@ -507,14 +503,19 @@ URL[] repositories = ((URLClassLoader) loader).getURLs(); for (URL url : repositories) { String repository = url.toString(); - if (repository.startsWith("file://")) { - repository = UDecoder.URLDecode(repository.substring(7), StandardCharsets.UTF_8); - } else if (repository.startsWith("file:")) { - repository = UDecoder.URLDecode(repository.substring(5), StandardCharsets.UTF_8); - } else { + if (repository == null) { continue; } - if (repository == null) { + if (repository.startsWith("file:")) { + // Let the JRE handle all the edge cases for URL to path conversion. + try { + File f = new File(url.toURI()); + repository = f.getAbsolutePath(); + } catch (URISyntaxException | IllegalArgumentException e) { + // Can't convert from URL to URI. Treat as non-file URL and skip. + continue; + } + } else { continue; } if (classpath.length() > 0) { @@ -523,8 +524,7 @@ classpath.append(repository); } } else if (loader == ClassLoader.getSystemClassLoader()) { - // From Java 9 the internal class loaders no longer extend - // URLCLassLoader + // From Java 9 the internal class loaders no longer extend URLCLassLoader String cp = System.getProperty("java.class.path"); if (cp != null && !cp.isEmpty()) { if (classpath.length() > 0) { diff -Nru tomcat10-10.1.40/java/org/apache/catalina/manager/Constants.java tomcat10-10.1.52/java/org/apache/catalina/manager/Constants.java --- tomcat10-10.1.40/java/org/apache/catalina/manager/Constants.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/manager/Constants.java 2026-01-23 19:33:36.000000000 +0000 @@ -36,6 +36,7 @@ HTML_HEADER_SECTION = "\n" + "\n" + + "\n" + "\n"; BODY_HEADER_SECTION = @@ -130,7 +131,7 @@ HTML_TAIL_SECTION = "
    \n" + "
    \n" + - " Copyright © 1999-2025, Apache Software Foundation" + + " Copyright © 1999-2026, Apache Software Foundation" + "
    \n" + "\n" + "\n" + diff -Nru tomcat10-10.1.40/java/org/apache/catalina/manager/HTMLManagerServlet.java tomcat10-10.1.52/java/org/apache/catalina/manager/HTMLManagerServlet.java --- tomcat10-10.1.40/java/org/apache/catalina/manager/HTMLManagerServlet.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/manager/HTMLManagerServlet.java 2026-01-23 19:33:36.000000000 +0000 @@ -62,10 +62,6 @@ * However if you use a software that parses the output of ManagerServlet you won't be able to upgrade to * this Servlet since the output are not in the same format ar from ManagerServlet * - * @author Bip Thelin - * @author Malcolm Edgar - * @author Glenn L. Nielsen - * * @see ManagerServlet */ public class HTMLManagerServlet extends ManagerServlet { @@ -270,6 +266,7 @@ * @param cn Name of the application to be deployed * @param war URL of the web application archive to be deployed * @param smClient internationalized strings + * * @return message String */ protected String deployInternal(String config, ContextName cn, String war, StringManager smClient) { @@ -290,6 +287,7 @@ * @param response The response * @param message a message to display * @param smClient internationalized strings + * * @throws IOException an IO error occurred */ protected void list(HttpServletRequest request, HttpServletResponse response, String message, @@ -568,7 +566,9 @@ * * @param cn Name of the application to be restarted * @param smClient StringManager for the client's locale + * * @return message String + * * @see ManagerServlet#reload(PrintWriter, ContextName, StringManager) */ protected String reload(ContextName cn, StringManager smClient) { @@ -586,7 +586,9 @@ * * @param cn Name of the application to be undeployed * @param smClient StringManager for the client's locale + * * @return message String + * * @see ManagerServlet#undeploy(PrintWriter, ContextName, StringManager) */ protected String undeploy(ContextName cn, StringManager smClient) { @@ -605,7 +607,9 @@ * @param cn Name of the application to list session information * @param idle Expire all sessions with idle time ≥ idle for this context * @param smClient StringManager for the client's locale + * * @return message String + * * @see ManagerServlet#sessions(PrintWriter, ContextName, int, StringManager) */ protected String sessions(ContextName cn, int idle, StringManager smClient) { @@ -623,7 +627,9 @@ * * @param cn Name of the application to be started * @param smClient StringManager for the client's locale + * * @return message String + * * @see ManagerServlet#start(PrintWriter, ContextName, StringManager) */ protected String start(ContextName cn, StringManager smClient) { @@ -641,7 +647,9 @@ * * @param cn Name of the application to be stopped * @param smClient StringManager for the client's locale + * * @return message String + * * @see ManagerServlet#stop(PrintWriter, ContextName, StringManager) */ protected String stop(ContextName cn, StringManager smClient) { @@ -658,7 +666,9 @@ * Find potential memory leaks caused by web application reload. * * @param smClient StringManager for the client's locale + * * @return message String + * * @see ManagerServlet#findleaks(boolean, PrintWriter, StringManager) */ protected String findleaks(StringManager smClient) { @@ -718,7 +728,7 @@ @Override public String getServletInfo() { - return "HTMLManagerServlet, Copyright (c) 1999-2025, The Apache Software Foundation"; + return "HTMLManagerServlet, Copyright (c) 1999-2026, The Apache Software Foundation"; } @Override @@ -740,6 +750,7 @@ * @param cn Name of the application from which to expire sessions * @param req The Servlet request * @param smClient StringManager for the client's locale + * * @return message string */ protected String expireSessions(ContextName cn, HttpServletRequest req, StringManager smClient) { @@ -762,6 +773,7 @@ * @param req The Servlet request * @param resp The Servlet response * @param smClient StringManager for the client's locale + * * @throws ServletException Propagated Servlet error * @throws IOException An IO error occurred */ @@ -847,6 +859,7 @@ * @param req The Servlet request * @param resp The Servlet response * @param smClient StringManager for the client's locale + * * @throws ServletException Propagated Servlet error * @throws IOException An IO error occurred */ @@ -896,6 +909,7 @@ * @param cn Name of the application for which the sessions will be listed * @param sessionId the session id * @param smClient StringManager for the client's locale + * * @throws ServletException Propagated Servlet error * @throws IOException An IO error occurred */ @@ -918,6 +932,7 @@ * @param cn Name of the application for which sessions are to be invalidated * @param sessionIds the session ids of the sessions * @param smClient StringManager for the client's locale + * * @return number of invalidated sessions */ protected int invalidateSessions(ContextName cn, String[] sessionIds, StringManager smClient) { @@ -956,6 +971,7 @@ * @param sessionId the session id * @param attributeName the attribute name * @param smClient StringManager for the client's locale + * * @return true if there was an attribute removed, false otherwise */ protected boolean removeSessionAttribute(ContextName cn, String sessionId, String attributeName, diff -Nru tomcat10-10.1.40/java/org/apache/catalina/manager/JMXProxyServlet.java tomcat10-10.1.52/java/org/apache/catalina/manager/JMXProxyServlet.java --- tomcat10-10.1.40/java/org/apache/catalina/manager/JMXProxyServlet.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/manager/JMXProxyServlet.java 2026-01-23 19:33:36.000000000 +0000 @@ -43,8 +43,6 @@ /** * This servlet will dump JMX attributes in a simple format and implement proxy services for modeler. - * - * @author Costin Manolache */ public class JMXProxyServlet extends HttpServlet { @@ -148,9 +146,9 @@ writer.print(" = "); writer.println(MBeanDumper.escape(valueStr)); - } catch (Exception ex) { - writer.println("Error - " + ex.toString()); - ex.printStackTrace(writer); + } catch (Exception e) { + writer.println("Error - " + e.toString()); + e.printStackTrace(writer); } } @@ -159,9 +157,9 @@ try { setAttributeInternal(onameStr, att, val); writer.println("OK - Attribute set"); - } catch (Exception ex) { - writer.println("Error - " + ex.toString()); - ex.printStackTrace(writer); + } catch (Exception e) { + writer.println("Error - " + e.toString()); + e.printStackTrace(writer); } } @@ -173,9 +171,9 @@ names = mBeanServer.queryNames(new ObjectName(qry), null); writer.println("OK - Number of results: " + names.size()); writer.println(); - } catch (Exception ex) { - writer.println("Error - " + ex.toString()); - ex.printStackTrace(writer); + } catch (Exception e) { + writer.println("Error - " + e.toString()); + e.printStackTrace(writer); return; } @@ -205,9 +203,9 @@ } else { writer.println("OK - Operation " + op + " without return value"); } - } catch (Exception ex) { - writer.println("Error - " + ex.toString()); - ex.printStackTrace(writer); + } catch (Exception e) { + writer.println("Error - " + e.toString()); + e.printStackTrace(writer); } } diff -Nru tomcat10-10.1.40/java/org/apache/catalina/manager/JspHelper.java tomcat10-10.1.52/java/org/apache/catalina/manager/JspHelper.java --- tomcat10-10.1.40/java/org/apache/catalina/manager/JspHelper.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/manager/JspHelper.java 2026-01-23 19:33:36.000000000 +0000 @@ -30,8 +30,6 @@ /** * Helper JavaBean for JSPs, because JSTL 1.1/EL 2.0 is too dumb to do what I need (call methods with parameters), or I * am too dumb to use it correctly. :) - * - * @author Cédrik LIME */ public class JspHelper { diff -Nru tomcat10-10.1.40/java/org/apache/catalina/manager/LocalStrings.properties tomcat10-10.1.52/java/org/apache/catalina/manager/LocalStrings.properties --- tomcat10-10.1.40/java/org/apache/catalina/manager/LocalStrings.properties 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/manager/LocalStrings.properties 2026-01-23 19:33:36.000000000 +0000 @@ -125,7 +125,8 @@ managerServlet.alreadyContext=FAIL - Application already exists at path [{0}] managerServlet.certsNotAvailable=Certificate information cannot be obtained from this connector at runtime -managerServlet.copyError=Could not copy configuration file from path [{0}] +managerServlet.certsNotLoaded=Certificates were not loaded for this connector +managerServlet.copyFail=FAIL - Unable to copy [{0}] to [{1}], details of the error may be in the server logs managerServlet.deleteFail=FAIL - Unable to delete [{0}]. The continued presence of this file may cause problems. managerServlet.deployFailed=FAIL - Failed to deploy application at context path [{0}] managerServlet.deployed=OK - Deployed application at context path [{0}] diff -Nru tomcat10-10.1.40/java/org/apache/catalina/manager/LocalStrings_fr.properties tomcat10-10.1.52/java/org/apache/catalina/manager/LocalStrings_fr.properties --- tomcat10-10.1.40/java/org/apache/catalina/manager/LocalStrings_fr.properties 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/manager/LocalStrings_fr.properties 2026-01-23 19:33:36.000000000 +0000 @@ -123,7 +123,8 @@ managerServlet.alreadyContext=FAIL - l''application existe déjà dans le chemin [{0}] managerServlet.certsNotAvailable=L'information sur les certificats ne peut pas être obtenu de ce connecteur au cours de son exécution -managerServlet.copyError=Impossible de copier le fichier de configuration à partir du chemin [{0}] +managerServlet.certsNotLoaded=Les certificats n'ont pas été chargés pour ce connecteur +managerServlet.copyFail=FAIL - Impossible de copier [{0}] vers [{1}], les détails de l''erreur peuvent se trouver dans les logs du serveur managerServlet.deleteFail=FAIL - Impossible de supprimer [{0}], ce qui pourrait causer des problèmes managerServlet.deployFailed=FAIL - Echec au déploiement de l''application pour le chemin de contexte [{0}] managerServlet.deployed=OK - Application déployée pour le chemin de contexte [{0}] diff -Nru tomcat10-10.1.40/java/org/apache/catalina/manager/LocalStrings_ja.properties tomcat10-10.1.52/java/org/apache/catalina/manager/LocalStrings_ja.properties --- tomcat10-10.1.40/java/org/apache/catalina/manager/LocalStrings_ja.properties 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/manager/LocalStrings_ja.properties 2026-01-23 19:33:36.000000000 +0000 @@ -125,7 +125,8 @@ managerServlet.alreadyContext=FAIL - アプリケーションは、既にパス [{0}] に存在します managerServlet.certsNotAvailable=実行時にこのコネクタから証明書情報を取得できません。 -managerServlet.copyError=パス [{0}] から設定ファイルをコピーできません +managerServlet.certsNotLoaded=このコネクタの証明書は読み込まれませんでした +managerServlet.copyFail=FAIL - [{0}] を [{1}] にコピーできません。エラーの詳細はサーバーログに記載されている可能性があります managerServlet.deleteFail=FAIL - [{0}]を削除できません。 このファイルが継続して存在すると、問題が発生する可能性があります。 managerServlet.deployFailed=FAIL - コンテキストパス [{0}] にアプリケーションを配備できません。 managerServlet.deployed=OK - コンテキストパス [{0}] でアプリケーションを配備しました @@ -180,7 +181,7 @@ managerServlet.sessions=OK - コンテキストパス [{0}] のアプリケーションのセッション情報です managerServlet.sessiontimeout=[{0}]分: [{1}]セッション managerServlet.sessiontimeout.expired=[{0}]分: expired [{1}]セッション -managerServlet.sessiontimeout.unlimited=unlimited 分: [{0}]セッション +managerServlet.sessiontimeout.unlimited=無制限の時間: [{0}] セッション managerServlet.sslConnectorCerts=OK - コネクタ/証明書チェーンの情報 managerServlet.sslConnectorCiphers=OK - Connector/ SSL暗号情報 managerServlet.sslConnectorTrustedCerts=OK - コネクタ/信頼された証明書情報 diff -Nru tomcat10-10.1.40/java/org/apache/catalina/manager/LocalStrings_ko.properties tomcat10-10.1.52/java/org/apache/catalina/manager/LocalStrings_ko.properties --- tomcat10-10.1.40/java/org/apache/catalina/manager/LocalStrings_ko.properties 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/manager/LocalStrings_ko.properties 2026-01-23 19:33:36.000000000 +0000 @@ -124,7 +124,6 @@ managerServlet.alreadyContext=실패 - 애플리케이션이 이미 경로 [{0}]에 존재합니다. managerServlet.certsNotAvailable=이 Connector로부터, 인증서 정보를 런타임에 구할 수 없습니다. -managerServlet.copyError=경로 [{0}](으)로부터 설정 파일을 복사할 수 없었습니다. managerServlet.deleteFail=실패 - [{0}]을(를) 삭제할 수 없습니다. 이 파일이 계속해서 존재하면 문제들을 일으킬 수 있습니다. managerServlet.deployFailed=실패 - 컨텍스트 경로 [{0}]에, 애플리케이션을 배치하지 못했습니다. managerServlet.deployed=OK - 컨텍스트 경로 [{0}]에 애플리케이션을 배치했습니다. diff -Nru tomcat10-10.1.40/java/org/apache/catalina/manager/LocalStrings_pt_BR.properties tomcat10-10.1.52/java/org/apache/catalina/manager/LocalStrings_pt_BR.properties --- tomcat10-10.1.40/java/org/apache/catalina/manager/LocalStrings_pt_BR.properties 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/manager/LocalStrings_pt_BR.properties 2026-01-23 19:33:36.000000000 +0000 @@ -20,7 +20,6 @@ htmlManagerServlet.appsSessions=Sessões htmlManagerServlet.serverIPAddress=Endereço IP -managerServlet.copyError=Não foi possível copiar o arquivo de configuração do caminho [{0}] managerServlet.deployed=OK - Instalada aplicação no path de contexto [{0}] managerServlet.mkdirFail=FALHA - Incapaz de criar o diretório [{0}] -managerServlet.resourcesAll=Recursos de todos os tipos, listados. +managerServlet.resourcesAll=OK - Recursos de todos os tipos, listados. diff -Nru tomcat10-10.1.40/java/org/apache/catalina/manager/LocalStrings_ru.properties tomcat10-10.1.52/java/org/apache/catalina/manager/LocalStrings_ru.properties --- tomcat10-10.1.40/java/org/apache/catalina/manager/LocalStrings_ru.properties 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/manager/LocalStrings_ru.properties 2026-01-23 19:33:36.000000000 +0000 @@ -53,7 +53,7 @@ htmlManagerServlet.connectorStateThreadCount=Текущее число потоков: htmlManagerServlet.deployButton=Развернуть htmlManagerServlet.deployConfig=Путь XML файла конфигурации контекста: -htmlManagerServlet.deployPath=Путь: +htmlManagerServlet.deployPath=Путь к контексту: htmlManagerServlet.deployServer=Развернуть серверный WAR файл htmlManagerServlet.deployTitle=Развернуть htmlManagerServlet.deployUpload=WAR файл для развёртывания diff -Nru tomcat10-10.1.40/java/org/apache/catalina/manager/LocalStrings_zh_CN.properties tomcat10-10.1.52/java/org/apache/catalina/manager/LocalStrings_zh_CN.properties --- tomcat10-10.1.40/java/org/apache/catalina/manager/LocalStrings_zh_CN.properties 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/manager/LocalStrings_zh_CN.properties 2026-01-23 19:33:36.000000000 +0000 @@ -123,7 +123,6 @@ managerServlet.alreadyContext=失败 - 应用程序已存在于路径 [{0}] managerServlet.certsNotAvailable=在运行期,无法从连接器中获取认证信息 -managerServlet.copyError=无法从路径[{0}]拷贝配置文件 managerServlet.deleteFail=失败 - 不能删除[{0}]。这个文件一直存在会出现问题。 managerServlet.deployFailed=FAIL - 在上下文路径[{0}]下部署应用失败 managerServlet.deployed=OK - 以应用path [{0}] 部署应用 diff -Nru tomcat10-10.1.40/java/org/apache/catalina/manager/ManagerServlet.java tomcat10-10.1.52/java/org/apache/catalina/manager/ManagerServlet.java --- tomcat10-10.1.40/java/org/apache/catalina/manager/ManagerServlet.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/manager/ManagerServlet.java 2026-01-23 19:33:36.000000000 +0000 @@ -145,9 +145,6 @@ *
  • debug - The debugging detail level that controls the amount of information that is logged by this servlet. * Default is zero. * - * - * @author Craig R. McClanahan - * @author Remy Maucherat */ public class ManagerServlet extends HttpServlet implements ContainerServlet { @@ -373,8 +370,7 @@ } String config = request.getParameter("config"); String tag = request.getParameter("tag"); - boolean update = request.getParameter("update") != null - && request.getParameter("update").equals("true"); + boolean update = request.getParameter("update") != null && request.getParameter("update").equals("true"); // Prepare our output writer to generate the response message response.setContentType("text/plain;charset=" + Constants.CHARSET); @@ -735,7 +731,9 @@ return; } if (!ExpandWar.copy(new File(config), new File(configBase, baseName + ".xml"))) { - throw new Exception(sm.getString("managerServlet.copyError", config)); + writer.println(smClient.getString("managerServlet.copyFail", new File(config), + new File(configBase, baseName + ".xml"))); + return; } } // Upload WAR @@ -753,7 +751,10 @@ } if (tag != null) { // Copy WAR to the host's appBase - ExpandWar.copy(uploadedWar, deployedWar); + if (!ExpandWar.copy(uploadedWar, deployedWar)) { + writer.println(smClient.getString("managerServlet.copyFail", uploadedWar, deployedWar)); + return; + } } } finally { removeServiced(name); @@ -807,7 +808,10 @@ writer.println(smClient.getString("managerServlet.deleteFail", deployedWar)); return; } - ExpandWar.copy(localWar, deployedWar); + if (!ExpandWar.copy(localWar, deployedWar)) { + writer.println(smClient.getString("managerServlet.copyFail", localWar, deployedWar)); + return; + } } finally { removeServiced(name); } @@ -901,7 +905,11 @@ writer.println(smClient.getString("managerServlet.deleteFail", localConfigFile)); return; } - ExpandWar.copy(configFile, localConfigFile); + if (!ExpandWar.copy(configFile, localConfigFile)) { + writer.println( + smClient.getString("managerServlet.copyFail", configFile, localConfigFile)); + return; + } } } if (war != null) { @@ -921,7 +929,10 @@ writer.println(smClient.getString("managerServlet.deleteFail", localWarFile)); return; } - ExpandWar.copy(warFile, localWarFile); + if (!ExpandWar.copy(warFile, localWarFile)) { + writer.println(smClient.getString("managerServlet.copyFail", warFile, localWarFile)); + return; + } } } } finally { @@ -1490,11 +1501,11 @@ try (ServletInputStream istream = request.getInputStream(); OutputStream ostream = new FileOutputStream(war)) { IOTools.flow(istream, ostream); - } catch (IOException e) { + } catch (IOException ioe) { if (war.exists() && !war.delete()) { writer.println(smClient.getString("managerServlet.deleteFail", war)); } - throw e; + throw ioe; } } @@ -1556,12 +1567,16 @@ if (alias == null) { alias = SSLUtilBase.DEFAULT_KEY_ALIAS; } - X509Certificate[] certs = sslContext.getCertificateChain(alias); - if (certs == null) { - certList.add(smClient.getString("managerServlet.certsNotAvailable")); + if (sslContext == null) { + certList.add(smClient.getString("managerServlet.certsNotLoaded")); } else { - for (Certificate cert : certs) { - certList.add(cert.toString()); + X509Certificate[] certs = sslContext.getCertificateChain(alias); + if (certs == null) { + certList.add(smClient.getString("managerServlet.certsNotAvailable")); + } else { + for (Certificate cert : certs) { + certList.add(cert.toString()); + } } } result.put(name, certList); @@ -1589,14 +1604,18 @@ String name = connector.toString() + "-" + sslHostConfig.getHostName(); List certList = new ArrayList<>(); SSLContext sslContext = sslHostConfig.getCertificates().iterator().next().getSslContext(); - X509Certificate[] certs = sslContext.getAcceptedIssuers(); - if (certs == null) { - certList.add(smClient.getString("managerServlet.certsNotAvailable")); - } else if (certs.length == 0) { - certList.add(smClient.getString("managerServlet.trustedCertsNotConfigured")); + if (sslContext == null) { + certList.add(smClient.getString("managerServlet.certsNotLoaded")); } else { - for (Certificate cert : certs) { - certList.add(cert.toString()); + X509Certificate[] certs = sslContext.getAcceptedIssuers(); + if (certs == null) { + certList.add(smClient.getString("managerServlet.certsNotAvailable")); + } else if (certs.length == 0) { + certList.add(smClient.getString("managerServlet.trustedCertsNotConfigured")); + } else { + for (Certificate cert : certs) { + certList.add(cert.toString()); + } } } result.put(name, certList); diff -Nru tomcat10-10.1.40/java/org/apache/catalina/manager/StatusManagerServlet.java tomcat10-10.1.52/java/org/apache/catalina/manager/StatusManagerServlet.java --- tomcat10-10.1.40/java/org/apache/catalina/manager/StatusManagerServlet.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/manager/StatusManagerServlet.java 2026-01-23 19:33:36.000000000 +0000 @@ -44,8 +44,6 @@ /** * This servlet will display a complete status of the HTTP/1.1 connector. - * - * @author Remy Maucherat */ public class StatusManagerServlet extends HttpServlet implements NotificationListener { diff -Nru tomcat10-10.1.40/java/org/apache/catalina/manager/StatusTransformer.java tomcat10-10.1.52/java/org/apache/catalina/manager/StatusTransformer.java --- tomcat10-10.1.40/java/org/apache/catalina/manager/StatusTransformer.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/manager/StatusTransformer.java 2026-01-23 19:33:36.000000000 +0000 @@ -40,8 +40,6 @@ /** * This is a refactoring of the servlet to externalize the output into a simple class. Although we could use XSLT, that * is unnecessarily complex. - * - * @author Peter Lin */ public class StatusTransformer { @@ -805,6 +803,8 @@ writer.print(""); writer.print("

    "); + writer.print("State: "); + writer.print(mBeanServer.getAttribute(objectName, "stateName")); Object startTime = mBeanServer.getAttribute(objectName, "startTime"); writer.print(" Start time: " + new Date(((Long) startTime).longValue())); writer.print(" Startup time: "); @@ -831,6 +831,8 @@ } else if (mode == 2) { indent(writer, 2).append('{').println(); appendJSonValue(indent(writer, 3), "name", JSONFilter.escape(JSONFilter.escape(name))).append(','); + appendJSonValue(writer, "state", mBeanServer.getAttribute(objectName, "stateName")); + writer.append(','); appendJSonValue(writer, "startTime", new Date(((Long) mBeanServer.getAttribute(objectName, "startTime")).longValue()).toString()) .append(','); diff -Nru tomcat10-10.1.40/java/org/apache/catalina/manager/host/Constants.java tomcat10-10.1.52/java/org/apache/catalina/manager/host/Constants.java --- tomcat10-10.1.40/java/org/apache/catalina/manager/host/Constants.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/manager/host/Constants.java 2026-01-23 19:33:36.000000000 +0000 @@ -80,7 +80,7 @@ public static final String HTML_TAIL_SECTION = "


    \n" + "
    \n" + - " Copyright © 1999-2025, Apache Software Foundation" + + " Copyright © 1999-2026, Apache Software Foundation" + "
    \n" + "\n" + "\n" + diff -Nru tomcat10-10.1.40/java/org/apache/catalina/manager/host/HTMLHostManagerServlet.java tomcat10-10.1.52/java/org/apache/catalina/manager/host/HTMLHostManagerServlet.java --- tomcat10-10.1.40/java/org/apache/catalina/manager/host/HTMLHostManagerServlet.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/manager/host/HTMLHostManagerServlet.java 2026-01-23 19:33:36.000000000 +0000 @@ -47,11 +47,6 @@ * However if you use a software that parses the output of HostManagerServlet you won't be able to upgrade * to this Servlet since the output are not in the same format as from HostManagerServlet * - * @author Bip Thelin - * @author Malcolm Edgar - * @author Glenn L. Nielsen - * @author Peter Rossbach - * * @see org.apache.catalina.manager.ManagerServlet */ public class HTMLHostManagerServlet extends HostManagerServlet { diff -Nru tomcat10-10.1.40/java/org/apache/catalina/manager/host/HostManagerServlet.java tomcat10-10.1.52/java/org/apache/catalina/manager/host/HostManagerServlet.java --- tomcat10-10.1.40/java/org/apache/catalina/manager/host/HostManagerServlet.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/manager/host/HostManagerServlet.java 2026-01-23 19:33:36.000000000 +0000 @@ -76,9 +76,6 @@ *
  • debug - The debugging detail level that controls the amount of information that is logged by this servlet. * Default is zero. * - * - * @author Craig R. McClanahan - * @author Remy Maucherat */ public class HostManagerServlet extends HttpServlet implements ContainerServlet { @@ -331,7 +328,7 @@ } try { appBaseFile = file.getCanonicalFile(); - } catch (IOException e) { + } catch (IOException ioe) { appBaseFile = file; } if (!appBaseFile.mkdirs() && !appBaseFile.isDirectory()) { @@ -355,7 +352,7 @@ } Path dest = new File(configBaseFile, "manager.xml").toPath(); Files.copy(is, dest); - } catch (IOException e) { + } catch (IOException ioe) { writer.println(smClient.getString("hostManagerServlet.managerXml")); return; } diff -Nru tomcat10-10.1.40/java/org/apache/catalina/manager/host/LocalStrings_ja.properties tomcat10-10.1.52/java/org/apache/catalina/manager/host/LocalStrings_ja.properties --- tomcat10-10.1.40/java/org/apache/catalina/manager/host/LocalStrings_ja.properties 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/manager/host/LocalStrings_ja.properties 2026-01-23 19:33:36.000000000 +0000 @@ -18,7 +18,7 @@ hostManagerServlet.add=add: ホスト [{0}] を追加 hostManagerServlet.addFailed=FAIL - ホスト [{0}] を追加できません。 -hostManagerServlet.addSuccess=OK - ホスト [{0}] を追加しました +hostManagerServlet.addSuccess=OK - ホスト [{0}] を追加しました hostManagerServlet.alreadyHost=FAIL - ホスト名[{0}]のホストが既に存在します hostManagerServlet.alreadyStarted=FAIL - ホスト [{0}] はすでに開始しています。 hostManagerServlet.alreadyStopped=FAIL - Host [{0}] はすでに停止しています。 @@ -42,7 +42,7 @@ hostManagerServlet.postCommand=FAIL - コマンド [{0}] をGETリクエストで使用しようとしましたが、POSTが必要です hostManagerServlet.remove=remove: ホスト [{0}] を削除します。 hostManagerServlet.removeFailed=FAIL - Host [{0}] を削除できません。 -hostManagerServlet.removeSuccess=OK - ホスト [{0}] を削除しました +hostManagerServlet.removeSuccess=OK - ホスト [{0}] を削除しました hostManagerServlet.start=開始:名前[{0}]のホストを起動しています hostManagerServlet.startFailed=FAIL - ホスト [{0}] の起動に失敗しました hostManagerServlet.started=OK - ホスト [{0}] を開始しました diff -Nru tomcat10-10.1.40/java/org/apache/catalina/manager/host/LocalStrings_ru.properties tomcat10-10.1.52/java/org/apache/catalina/manager/host/LocalStrings_ru.properties --- tomcat10-10.1.40/java/org/apache/catalina/manager/host/LocalStrings_ru.properties 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/manager/host/LocalStrings_ru.properties 2026-01-23 19:33:36.000000000 +0000 @@ -39,13 +39,13 @@ hostManagerServlet.persistFailed=Ошибка - Не удалось сохранить конфигурацию hostManagerServlet.persisted=OK - Конфигурация сохранена hostManagerServlet.postCommand=Ошибка - Команда [{0}] была подана при помощи запроса GET, но требуется POST -hostManagerServlet.remove=remove: Удаление сервера [{0}] +hostManagerServlet.remove=remove: Удаление хоста [{0}] hostManagerServlet.removeFailed=Ошибка - Не удалось удалить сервер [{0}] hostManagerServlet.removeSuccess=OK - Сервер удалён [{0}] -hostManagerServlet.start=start: Запуск сервера с именем [{0}] +hostManagerServlet.start=start: Запуск хоста с именем [{0}] hostManagerServlet.startFailed=Ошибка - Не удалось запустить сервер [{0}] hostManagerServlet.started=OK - Сервер [{0}] запущен -hostManagerServlet.stop=stop: Остановка сервера с именем [{0}] +hostManagerServlet.stop=stop: Остановка хоста с именем [{0}] hostManagerServlet.stopFailed=Ошибка - Не удалось остановить сервер [{0}] hostManagerServlet.stopped=OK - Сервер [{0}] остановлен hostManagerServlet.unknownCommand=Ошибка - Неизвестная команда [{0}] diff -Nru tomcat10-10.1.40/java/org/apache/catalina/manager/host/LocalStrings_zh_CN.properties tomcat10-10.1.52/java/org/apache/catalina/manager/host/LocalStrings_zh_CN.properties --- tomcat10-10.1.40/java/org/apache/catalina/manager/host/LocalStrings_zh_CN.properties 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/manager/host/LocalStrings_zh_CN.properties 2026-01-23 19:33:36.000000000 +0000 @@ -18,7 +18,7 @@ hostManagerServlet.add=添加:添加主机[{0}] hostManagerServlet.addFailed=失败 - 添加主机 [{0}] 失败 -hostManagerServlet.addSuccess=确定-添加主机[{0}] +hostManagerServlet.addSuccess=OK - 确定-添加主机[{0}] hostManagerServlet.alreadyHost=失败 - 主机名称[{0}]已经存在 hostManagerServlet.alreadyStarted=失败 - Host[{0}]已经启动。 hostManagerServlet.alreadyStopped=失败 - 主机[{0}]已经停止 @@ -42,12 +42,12 @@ hostManagerServlet.postCommand=失败 - 尝试通过GET请求使用命令[{0}],但是需要使用POST请求 hostManagerServlet.remove=移除:正在移除主机 [{0}] hostManagerServlet.removeFailed=失败 - 无法移除主机 [{0}] -hostManagerServlet.removeSuccess=确定-已删除主机[{0}] +hostManagerServlet.removeSuccess=OK - 已删除主机[{0}] hostManagerServlet.start=启动:启动主机[{0}] hostManagerServlet.startFailed=失败 - 无法启动主机 [{0}] hostManagerServlet.started=OK - 主机 [{0}] 已启动 hostManagerServlet.stop=停止:停止主机[{0}] -hostManagerServlet.stopFailed=失败 - 无法停止主机 [{0}] +hostManagerServlet.stopFailed=OK - 无法停止主机 [{0}] hostManagerServlet.stopped=OK - 主机 [{0}] 已停止 hostManagerServlet.unknownCommand=失败 - 未知命令 [{0}] diff -Nru tomcat10-10.1.40/java/org/apache/catalina/manager/util/SessionUtils.java tomcat10-10.1.52/java/org/apache/catalina/manager/util/SessionUtils.java --- tomcat10-10.1.40/java/org/apache/catalina/manager/util/SessionUtils.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/manager/util/SessionUtils.java 2026-01-23 19:33:36.000000000 +0000 @@ -32,8 +32,6 @@ /** * Utility methods on HttpSessions. - * - * @author Cédrik LIME */ public class SessionUtils { diff -Nru tomcat10-10.1.40/java/org/apache/catalina/mapper/LocalStrings_ru.properties tomcat10-10.1.52/java/org/apache/catalina/mapper/LocalStrings_ru.properties --- tomcat10-10.1.40/java/org/apache/catalina/mapper/LocalStrings_ru.properties 1970-01-01 00:00:00.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/mapper/LocalStrings_ru.properties 2026-01-23 19:33:36.000000000 +0000 @@ -0,0 +1,19 @@ +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# Do not edit this file directly. +# To edit translations see: https://tomcat.apache.org/getinvolved.html#Translations + +mapper.addHostAlias.success=Зарегистрирован псевдоним [{0}] для хоста [{1}] diff -Nru tomcat10-10.1.40/java/org/apache/catalina/mapper/Mapper.java tomcat10-10.1.52/java/org/apache/catalina/mapper/Mapper.java --- tomcat10-10.1.40/java/org/apache/catalina/mapper/Mapper.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/mapper/Mapper.java 2026-01-23 19:33:36.000000000 +0000 @@ -41,8 +41,6 @@ /** * Mapper, which implements the servlet API mapping rules (which are derived from the HTTP rules). - * - * @author Remy Maucherat */ public final class Mapper { @@ -439,7 +437,7 @@ * @param resourceOnly true if this wrapper always expects a physical resource to be present (such as a JSP) */ private void addWrapper(ContextVersion context, String path, Wrapper wrapper, boolean jspWildCard, - boolean resourceOnly) { + boolean resourceOnly) { synchronized (context) { if (path.endsWith("/*")) { diff -Nru tomcat10-10.1.40/java/org/apache/catalina/mapper/MapperListener.java tomcat10-10.1.52/java/org/apache/catalina/mapper/MapperListener.java --- tomcat10-10.1.40/java/org/apache/catalina/mapper/MapperListener.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/mapper/MapperListener.java 2026-01-23 19:33:36.000000000 +0000 @@ -40,9 +40,6 @@ /** * Mapper listener. - * - * @author Remy Maucherat - * @author Costin Manolache */ public class MapperListener extends LifecycleMBeanBase implements ContainerListener, LifecycleListener { diff -Nru tomcat10-10.1.40/java/org/apache/catalina/mapper/MappingData.java tomcat10-10.1.52/java/org/apache/catalina/mapper/MappingData.java --- tomcat10-10.1.40/java/org/apache/catalina/mapper/MappingData.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/mapper/MappingData.java 2026-01-23 19:33:36.000000000 +0000 @@ -25,8 +25,6 @@ /** * Mapping data. - * - * @author Remy Maucherat */ public class MappingData { diff -Nru tomcat10-10.1.40/java/org/apache/catalina/mbeans/ClassNameMBean.java tomcat10-10.1.52/java/org/apache/catalina/mbeans/ClassNameMBean.java --- tomcat10-10.1.40/java/org/apache/catalina/mbeans/ClassNameMBean.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/mbeans/ClassNameMBean.java 2026-01-23 19:33:36.000000000 +0000 @@ -26,8 +26,6 @@ *

    * * @param The type that this bean represents. - * - * @author Craig R. McClanahan */ public class ClassNameMBean extends BaseCatalinaMBean { diff -Nru tomcat10-10.1.40/java/org/apache/catalina/mbeans/ConnectorMBean.java tomcat10-10.1.52/java/org/apache/catalina/mbeans/ConnectorMBean.java --- tomcat10-10.1.40/java/org/apache/catalina/mbeans/ConnectorMBean.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/mbeans/ConnectorMBean.java 2026-01-23 19:33:36.000000000 +0000 @@ -27,12 +27,8 @@ import org.apache.tomcat.util.res.StringManager; /** - *

    * A ModelMBean implementation for the org.apache.coyote.tomcat5.CoyoteConnector * component. - *

    - * - * @author Amy Roh */ public class ConnectorMBean extends ClassNameMBean { diff -Nru tomcat10-10.1.40/java/org/apache/catalina/mbeans/ContextEnvironmentMBean.java tomcat10-10.1.52/java/org/apache/catalina/mbeans/ContextEnvironmentMBean.java --- tomcat10-10.1.40/java/org/apache/catalina/mbeans/ContextEnvironmentMBean.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/mbeans/ContextEnvironmentMBean.java 2026-01-23 19:33:36.000000000 +0000 @@ -25,12 +25,8 @@ import org.apache.tomcat.util.descriptor.web.NamingResources; /** - *

    * A ModelMBean implementation for the * org.apache.tomcat.util.descriptor.web.ContextEnvironment component. - *

    - * - * @author Amy Roh */ public class ContextEnvironmentMBean extends BaseCatalinaMBean { diff -Nru tomcat10-10.1.40/java/org/apache/catalina/mbeans/ContextResourceLinkMBean.java tomcat10-10.1.52/java/org/apache/catalina/mbeans/ContextResourceLinkMBean.java --- tomcat10-10.1.40/java/org/apache/catalina/mbeans/ContextResourceLinkMBean.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/mbeans/ContextResourceLinkMBean.java 2026-01-23 19:33:36.000000000 +0000 @@ -27,12 +27,8 @@ import org.apache.tomcat.util.res.StringManager; /** - *

    * A ModelMBean implementation for the * org.apache.tomcat.util.descriptor.web.ContextResourceLink component. - *

    - * - * @author Amy Roh */ public class ContextResourceLinkMBean extends BaseCatalinaMBean { diff -Nru tomcat10-10.1.40/java/org/apache/catalina/mbeans/ContextResourceMBean.java tomcat10-10.1.52/java/org/apache/catalina/mbeans/ContextResourceMBean.java --- tomcat10-10.1.40/java/org/apache/catalina/mbeans/ContextResourceMBean.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/mbeans/ContextResourceMBean.java 2026-01-23 19:33:36.000000000 +0000 @@ -27,12 +27,8 @@ import org.apache.tomcat.util.res.StringManager; /** - *

    * A ModelMBean implementation for the * org.apache.tomcat.util.descriptor.web.ContextResource component. - *

    - * - * @author Amy Roh */ public class ContextResourceMBean extends BaseCatalinaMBean { diff -Nru tomcat10-10.1.40/java/org/apache/catalina/mbeans/DataSourceUserDatabaseMBean.java tomcat10-10.1.52/java/org/apache/catalina/mbeans/DataSourceUserDatabaseMBean.java --- tomcat10-10.1.40/java/org/apache/catalina/mbeans/DataSourceUserDatabaseMBean.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/mbeans/DataSourceUserDatabaseMBean.java 2026-01-23 19:33:36.000000000 +0000 @@ -33,8 +33,6 @@ * A ModelMBean implementation for the org.apache.catalina.users.DataSourceUserDatabase * component. *

    - * - * @author Craig R. McClanahan */ public class DataSourceUserDatabaseMBean extends BaseModelMBean { diff -Nru tomcat10-10.1.40/java/org/apache/catalina/mbeans/GlobalResourcesLifecycleListener.java tomcat10-10.1.52/java/org/apache/catalina/mbeans/GlobalResourcesLifecycleListener.java --- tomcat10-10.1.40/java/org/apache/catalina/mbeans/GlobalResourcesLifecycleListener.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/mbeans/GlobalResourcesLifecycleListener.java 2026-01-23 19:33:36.000000000 +0000 @@ -45,8 +45,6 @@ *

    * This listener must only be nested within {@link Server} elements. * - * @author Craig R. McClanahan - * * @since 4.1 */ public class GlobalResourcesLifecycleListener implements LifecycleListener { diff -Nru tomcat10-10.1.40/java/org/apache/catalina/mbeans/GroupMBean.java tomcat10-10.1.52/java/org/apache/catalina/mbeans/GroupMBean.java --- tomcat10-10.1.40/java/org/apache/catalina/mbeans/GroupMBean.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/mbeans/GroupMBean.java 2026-01-23 19:33:36.000000000 +0000 @@ -35,8 +35,6 @@ *

    * A ModelMBean implementation for the org.apache.catalina.Group component. *

    - * - * @author Craig R. McClanahan */ public class GroupMBean extends BaseModelMBean { diff -Nru tomcat10-10.1.40/java/org/apache/catalina/mbeans/MBeanFactory.java tomcat10-10.1.52/java/org/apache/catalina/mbeans/MBeanFactory.java --- tomcat10-10.1.40/java/org/apache/catalina/mbeans/MBeanFactory.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/mbeans/MBeanFactory.java 2026-01-23 19:33:36.000000000 +0000 @@ -48,10 +48,6 @@ import org.apache.juli.logging.LogFactory; import org.apache.tomcat.util.res.StringManager; - -/** - * @author Amy Roh - */ public class MBeanFactory { private static final Log log = LogFactory.getLog(MBeanFactory.class); diff -Nru tomcat10-10.1.40/java/org/apache/catalina/mbeans/MBeanUtils.java tomcat10-10.1.52/java/org/apache/catalina/mbeans/MBeanUtils.java --- tomcat10-10.1.40/java/org/apache/catalina/mbeans/MBeanUtils.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/mbeans/MBeanUtils.java 2026-01-23 19:33:36.000000000 +0000 @@ -39,12 +39,8 @@ import org.apache.tomcat.util.modeler.Registry; import org.apache.tomcat.util.res.StringManager; - /** * Public utility methods in support of the server side MBeans implementation. - * - * @author Craig R. McClanahan - * @author Amy Roh */ public class MBeanUtils { @@ -450,7 +446,7 @@ static ObjectName createObjectName(String domain, Group group) throws MalformedObjectNameException { return new ObjectName(domain + ":type=Group,groupname=" + ObjectName.quote(group.getGroupname()) + - ",database=" + group.getUserDatabase().getId()); + ",database=" + group.getUserDatabase().getId()); } @@ -467,8 +463,8 @@ */ static ObjectName createObjectName(String domain, Role role) throws MalformedObjectNameException { - return new ObjectName(domain + ":type=Role,rolename=" + ObjectName.quote(role.getRolename()) + - ",database=" + role.getUserDatabase().getId()); + return new ObjectName(domain + ":type=Role,rolename=" + ObjectName.quote(role.getRolename()) + ",database=" + + role.getUserDatabase().getId()); } @@ -485,8 +481,8 @@ */ static ObjectName createObjectName(String domain, User user) throws MalformedObjectNameException { - return new ObjectName(domain + ":type=User,username=" + ObjectName.quote(user.getUsername()) + - ",database=" + user.getUserDatabase().getId()); + return new ObjectName(domain + ":type=User,username=" + ObjectName.quote(user.getUsername()) + ",database=" + + user.getUserDatabase().getId()); } diff -Nru tomcat10-10.1.40/java/org/apache/catalina/mbeans/MemoryUserDatabaseMBean.java tomcat10-10.1.52/java/org/apache/catalina/mbeans/MemoryUserDatabaseMBean.java --- tomcat10-10.1.40/java/org/apache/catalina/mbeans/MemoryUserDatabaseMBean.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/mbeans/MemoryUserDatabaseMBean.java 2026-01-23 19:33:36.000000000 +0000 @@ -23,8 +23,6 @@ * A ModelMBean implementation for the org.apache.catalina.users.MemoryUserDatabase * component. *

    - * - * @author Craig R. McClanahan */ public class MemoryUserDatabaseMBean extends SparseUserDatabaseMBean { diff -Nru tomcat10-10.1.40/java/org/apache/catalina/mbeans/NamingResourcesMBean.java tomcat10-10.1.52/java/org/apache/catalina/mbeans/NamingResourcesMBean.java --- tomcat10-10.1.40/java/org/apache/catalina/mbeans/NamingResourcesMBean.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/mbeans/NamingResourcesMBean.java 2026-01-23 19:33:36.000000000 +0000 @@ -32,12 +32,8 @@ import org.apache.tomcat.util.res.StringManager; /** - *

    * A ModelMBean implementation for the org.apache.catalina.deploy.NamingResourcesImpl * component. - *

    - * - * @author Amy Roh */ public class NamingResourcesMBean extends BaseModelMBean { diff -Nru tomcat10-10.1.40/java/org/apache/catalina/mbeans/RoleMBean.java tomcat10-10.1.52/java/org/apache/catalina/mbeans/RoleMBean.java --- tomcat10-10.1.40/java/org/apache/catalina/mbeans/RoleMBean.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/mbeans/RoleMBean.java 2026-01-23 19:33:36.000000000 +0000 @@ -24,8 +24,6 @@ *

    * A ModelMBean implementation for the org.apache.catalina.Role component. *

    - * - * @author Craig R. McClanahan */ public class RoleMBean extends BaseModelMBean { diff -Nru tomcat10-10.1.40/java/org/apache/catalina/mbeans/SparseUserDatabaseMBean.java tomcat10-10.1.52/java/org/apache/catalina/mbeans/SparseUserDatabaseMBean.java --- tomcat10-10.1.40/java/org/apache/catalina/mbeans/SparseUserDatabaseMBean.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/mbeans/SparseUserDatabaseMBean.java 2026-01-23 19:33:36.000000000 +0000 @@ -40,8 +40,6 @@ * register the corresponding user and make it available for management). All the MBeans created for users, groups and * roles are then discarded when save is invoked. *

    - * - * @author Craig R. McClanahan */ public class SparseUserDatabaseMBean extends BaseModelMBean { diff -Nru tomcat10-10.1.40/java/org/apache/catalina/mbeans/UserMBean.java tomcat10-10.1.52/java/org/apache/catalina/mbeans/UserMBean.java --- tomcat10-10.1.40/java/org/apache/catalina/mbeans/UserMBean.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/mbeans/UserMBean.java 2026-01-23 19:33:36.000000000 +0000 @@ -35,8 +35,6 @@ *

    * A ModelMBean implementation for the org.apache.catalina.User component. *

    - * - * @author Craig R. McClanahan */ public class UserMBean extends BaseModelMBean { diff -Nru tomcat10-10.1.40/java/org/apache/catalina/realm/CombinedRealm.java tomcat10-10.1.52/java/org/apache/catalina/realm/CombinedRealm.java --- tomcat10-10.1.40/java/org/apache/catalina/realm/CombinedRealm.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/realm/CombinedRealm.java 2026-01-23 19:33:36.000000000 +0000 @@ -359,7 +359,7 @@ // Stack trace will show where this was called from UnsupportedOperationException uoe = new UnsupportedOperationException(sm.getString("combinedRealm.getPassword")); - log.error(sm.getString("combinedRealm.unexpectedMethod"), uoe); + log.error(uoe.getMessage(), uoe); throw uoe; } @@ -369,7 +369,7 @@ // Stack trace will show where this was called from UnsupportedOperationException uoe = new UnsupportedOperationException(sm.getString("combinedRealm.getPrincipal")); - log.error(sm.getString("combinedRealm.unexpectedMethod"), uoe); + log.error(uoe.getMessage(), uoe); throw uoe; } diff -Nru tomcat10-10.1.40/java/org/apache/catalina/realm/DataSourceRealm.java tomcat10-10.1.52/java/org/apache/catalina/realm/DataSourceRealm.java --- tomcat10-10.1.40/java/org/apache/catalina/realm/DataSourceRealm.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/realm/DataSourceRealm.java 2026-01-23 19:33:36.000000000 +0000 @@ -34,11 +34,6 @@ /** * Implementation of Realm that works with any JDBC JNDI DataSource. See the Realm How-To for more details on how * to set up the database and for configuration options. - * - * @author Glenn L. Nielsen - * @author Craig R. McClanahan - * @author Carson McDonald - * @author Ignacio Ortega */ public class DataSourceRealm extends RealmBase { diff -Nru tomcat10-10.1.40/java/org/apache/catalina/realm/GenericPrincipal.java tomcat10-10.1.52/java/org/apache/catalina/realm/GenericPrincipal.java --- tomcat10-10.1.40/java/org/apache/catalina/realm/GenericPrincipal.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/realm/GenericPrincipal.java 2026-01-23 19:33:36.000000000 +0000 @@ -33,8 +33,6 @@ /** * Generic implementation of java.security.Principal that is available for use by Realm * implementations. - * - * @author Craig R. McClanahan */ public class GenericPrincipal implements TomcatPrincipal, Serializable { diff -Nru tomcat10-10.1.40/java/org/apache/catalina/realm/JAASCallbackHandler.java tomcat10-10.1.52/java/org/apache/catalina/realm/JAASCallbackHandler.java --- tomcat10-10.1.40/java/org/apache/catalina/realm/JAASCallbackHandler.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/realm/JAASCallbackHandler.java 2026-01-23 19:33:36.000000000 +0000 @@ -29,22 +29,15 @@ import org.apache.tomcat.util.res.StringManager; /** - *

    * Implementation of the JAAS CallbackHandler interface, used to negotiate delivery of the username and * credentials that were specified to our constructor. No interaction with the user is required (or possible). - *

    *

    * This CallbackHandler will pre-digest the supplied password, if required by the * <Realm> element in server.xml. - *

    *

    * At present, JAASCallbackHandler knows how to handle callbacks of type * javax.security.auth.callback.NameCallback and * javax.security.auth.callback.PasswordCallback. - *

    - * - * @author Craig R. McClanahan - * @author Andrew R. Jaquith */ public class JAASCallbackHandler implements CallbackHandler { diff -Nru tomcat10-10.1.40/java/org/apache/catalina/realm/JAASMemoryLoginModule.java tomcat10-10.1.52/java/org/apache/catalina/realm/JAASMemoryLoginModule.java --- tomcat10-10.1.40/java/org/apache/catalina/realm/JAASMemoryLoginModule.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/realm/JAASMemoryLoginModule.java 2026-01-23 19:33:36.000000000 +0000 @@ -66,8 +66,6 @@ * requirements of the GenericPrincipal constructor. It does not actually perform the functionality * required of a Realm implementation. *

    - * - * @author Craig R. McClanahan */ public class JAASMemoryLoginModule extends MemoryRealm implements LoginModule { // We need to extend MemoryRealm to avoid class cast diff -Nru tomcat10-10.1.40/java/org/apache/catalina/realm/JAASRealm.java tomcat10-10.1.52/java/org/apache/catalina/realm/JAASRealm.java --- tomcat10-10.1.40/java/org/apache/catalina/realm/JAASRealm.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/realm/JAASRealm.java 2026-01-23 19:33:36.000000000 +0000 @@ -115,9 +115,6 @@ * JAASCallbackHandler will digest the password prior to passing it back to the * LoginModule
  • * - * - * @author Craig R. McClanahan - * @author Yoav Shapira */ public class JAASRealm extends RealmBase { @@ -360,9 +357,9 @@ try { Configuration config = getConfig(); loginContext = new LoginContext(appName, null, callbackHandler, config); - } catch (Throwable e) { - ExceptionUtils.handleThrowable(e); - log.error(sm.getString("jaasRealm.unexpectedError"), e); + } catch (Throwable t) { + ExceptionUtils.handleThrowable(t); + log.error(sm.getString("jaasRealm.unexpectedError"), t); // There is configuration issue with JAAS so mark the realm as // unavailable invocationSuccess = false; @@ -395,7 +392,7 @@ } } catch (AccountExpiredException e) { if (log.isDebugEnabled()) { - log.debug(sm.getString("jaasRealm.accountExpired", username)); + log.debug(sm.getString("jaasRealm.accountExpired", username), e); } // JAAS checked LoginExceptions are successful authentication // invocations so mark JAAS realm as available @@ -403,7 +400,7 @@ return null; } catch (CredentialExpiredException e) { if (log.isDebugEnabled()) { - log.debug(sm.getString("jaasRealm.credentialExpired", username)); + log.debug(sm.getString("jaasRealm.credentialExpired", username), e); } // JAAS checked LoginExceptions are successful authentication // invocations so mark JAAS realm as available @@ -411,7 +408,7 @@ return null; } catch (FailedLoginException e) { if (log.isDebugEnabled()) { - log.debug(sm.getString("jaasRealm.failedLogin", username)); + log.debug(sm.getString("jaasRealm.failedLogin", username), e); } // JAAS checked LoginExceptions are successful authentication // invocations so mark JAAS realm as available @@ -423,9 +420,9 @@ // invocations so mark JAAS realm as available invocationSuccess = true; return null; - } catch (Throwable e) { - ExceptionUtils.handleThrowable(e); - log.error(sm.getString("jaasRealm.unexpectedError"), e); + } catch (Throwable t) { + ExceptionUtils.handleThrowable(t); + log.error(sm.getString("jaasRealm.unexpectedError"), t); // JAAS throws exception different from LoginException so mark the // realm as unavailable invocationSuccess = false; diff -Nru tomcat10-10.1.40/java/org/apache/catalina/realm/JNDIRealm.java tomcat10-10.1.52/java/org/apache/catalina/realm/JNDIRealm.java --- tomcat10-10.1.40/java/org/apache/catalina/realm/JNDIRealm.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/realm/JNDIRealm.java 2026-01-23 19:33:36.000000000 +0000 @@ -133,9 +133,6 @@ * descriptor allows applications to refer to roles programmatically by names other than those used in the directory * server itself. * - * - * @author John Holman - * @author Craig R. McClanahan */ public class JNDIRealm extends RealmBase { @@ -1156,9 +1153,9 @@ } catch (NullPointerException | NamingException e) { /* * BZ 61313 NamingException may or may not indicate an error that is recoverable via fail over. - * Therefore, a decision needs to be made whether to fail over or not. Generally, attempting to fail over - * when it is not appropriate is better than not failing over when it is appropriate so the code always - * attempts to fail over for NamingExceptions. + * Therefore, a decision needs to be made whether to fail over or not. Generally, attempting to fail + * over when it is not appropriate is better than not failing over when it is appropriate so the code + * always attempts to fail over for NamingExceptions. */ /* @@ -1832,7 +1829,7 @@ } boolean validated = false; - Hashtable preservedEnvironment = context.getEnvironment(); + Hashtable preservedEnvironment = context.getEnvironment(); // Elicit an LDAP bind operation using the provided user credentials try { @@ -1848,7 +1845,7 @@ validated = true; } catch (AuthenticationException e) { if (containerLog.isTraceEnabled()) { - containerLog.trace(" bind attempt failed"); + containerLog.trace(" bind attempt failed", e); } } finally { // Restore GSSAPI SASL if previously configured @@ -2217,8 +2214,8 @@ if (tls != null) { try { tls.close(); - } catch (IOException e) { - containerLog.error(sm.getString("jndiRealm.tlsClose"), e); + } catch (IOException ioe) { + containerLog.error(sm.getString("jndiRealm.tlsClose"), ioe); } } // Close our opened connection @@ -2570,7 +2567,7 @@ try { Object o = constructInstance(className); if (o instanceof SSLSocketFactory) { - return sslSocketFactory; + return (SSLSocketFactory) o; } else { throw new IllegalArgumentException(sm.getString("jndiRealm.invalidSslSocketFactory", className)); } @@ -2629,8 +2626,10 @@ try { SSLSession negotiate = tls.negotiate(getSSLSocketFactory()); containerLog.debug(sm.getString("jndiRealm.negotiatedTls", negotiate.getProtocol())); - } catch (IOException e) { - throw new NamingException(e.getMessage()); + } catch (IOException ioe) { + NamingException ne = new NamingException(ioe.getMessage()); + ne.initCause(ioe); + throw ne; } } finally { if (result != null) { @@ -2763,8 +2762,8 @@ /** * Given a string containing LDAP patterns for user locations (separated by parentheses in a pseudo-LDAP search - * string format - "(location1)(location2)"), returns an array of those paths. Real LDAP search strings are supported - * as well (though only the "|" "OR" type). + * string format - "(location1)(location2)"), returns an array of those paths. Real LDAP search strings are + * supported as well (though only the "|" "OR" type). * * @param userPatternString - a string LDAP search paths surrounded by parentheses * diff -Nru tomcat10-10.1.40/java/org/apache/catalina/realm/LocalStrings_ru.properties tomcat10-10.1.52/java/org/apache/catalina/realm/LocalStrings_ru.properties --- tomcat10-10.1.40/java/org/apache/catalina/realm/LocalStrings_ru.properties 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/realm/LocalStrings_ru.properties 2026-01-23 19:33:36.000000000 +0000 @@ -17,6 +17,7 @@ # To edit translations see: https://tomcat.apache.org/getinvolved.html#Translations dataSourceRealm.getPassword.exception=Исключение при получении пароля для [{0}] +dataSourceRealm.getRoles.exception=Ошибка получения ролей для [{0}] lockOutRealm.authLockedUser=Заблокированный пользователь [{0}] совершил попытку авторизоваться diff -Nru tomcat10-10.1.40/java/org/apache/catalina/realm/LockOutRealm.java tomcat10-10.1.52/java/org/apache/catalina/realm/LockOutRealm.java --- tomcat10-10.1.40/java/org/apache/catalina/realm/LockOutRealm.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/realm/LockOutRealm.java 2026-01-23 19:33:36.000000000 +0000 @@ -218,7 +218,7 @@ // Check to see if user is locked // Otherwise, user has not, yet, exceeded lock thresholds return lockRecord.getFailures() >= failureCount && - (System.currentTimeMillis() - lockRecord.getLastFailureTime()) / 1000 < lockOutTime; + (System.currentTimeMillis() - lockRecord.getLastFailureTime()) / 1000 < lockOutTime; } diff -Nru tomcat10-10.1.40/java/org/apache/catalina/realm/MemoryRealm.java tomcat10-10.1.52/java/org/apache/catalina/realm/MemoryRealm.java --- tomcat10-10.1.40/java/org/apache/catalina/realm/MemoryRealm.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/realm/MemoryRealm.java 2026-01-23 19:33:36.000000000 +0000 @@ -38,8 +38,6 @@ * IMPLEMENTATION NOTE: It is assumed that the in-memory collection representing our defined users (and * their roles) is initialized at application startup and never modified again. Therefore, no thread synchronization is * performed around accesses to the principals collection. - * - * @author Craig R. McClanahan */ public class MemoryRealm extends RealmBase { diff -Nru tomcat10-10.1.40/java/org/apache/catalina/realm/MemoryRuleSet.java tomcat10-10.1.52/java/org/apache/catalina/realm/MemoryRuleSet.java --- tomcat10-10.1.40/java/org/apache/catalina/realm/MemoryRuleSet.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/realm/MemoryRuleSet.java 2026-01-23 19:33:36.000000000 +0000 @@ -25,8 +25,6 @@ *

    * RuleSet for recognizing the users defined in the XML file processed by MemoryRealm. *

    - * - * @author Craig R. McClanahan */ public class MemoryRuleSet implements RuleSet { diff -Nru tomcat10-10.1.40/java/org/apache/catalina/realm/MessageDigestCredentialHandler.java tomcat10-10.1.52/java/org/apache/catalina/realm/MessageDigestCredentialHandler.java --- tomcat10-10.1.40/java/org/apache/catalina/realm/MessageDigestCredentialHandler.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/realm/MessageDigestCredentialHandler.java 2026-01-23 19:33:36.000000000 +0000 @@ -58,6 +58,7 @@ private Charset encoding = StandardCharsets.UTF_8; private String algorithm = null; + private boolean digestInRfc3112Order = false; public String getEncoding() { @@ -91,6 +92,16 @@ } + public boolean getDigestInRfc3112Order() { + return digestInRfc3112Order; + } + + + public void setDigestInRfc3112Order(boolean digestInRfc3112Order) { + this.digestInRfc3112Order = digestInRfc3112Order; + } + + @Override public boolean matches(String inputCredentials, String storedCredentials) { if (inputCredentials == null || storedCredentials == null) { @@ -162,7 +173,12 @@ if (salt == null) { userDigest = ConcurrentMessageDigest.digest(algorithm, iterations, inputCredentialbytes); } else { - userDigest = ConcurrentMessageDigest.digest(algorithm, iterations, salt, inputCredentialbytes); + if (digestInRfc3112Order) { + // RFC 3112 states that the input order for the digest is credentials then salt + userDigest = ConcurrentMessageDigest.digest(algorithm, iterations, inputCredentialbytes, salt); + } else { + userDigest = ConcurrentMessageDigest.digest(algorithm, iterations, salt, inputCredentialbytes); + } } return HexUtils.toHexString(userDigest); } diff -Nru tomcat10-10.1.40/java/org/apache/catalina/realm/NullRealm.java tomcat10-10.1.52/java/org/apache/catalina/realm/NullRealm.java --- tomcat10-10.1.40/java/org/apache/catalina/realm/NullRealm.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/realm/NullRealm.java 2026-01-23 19:33:36.000000000 +0000 @@ -19,8 +19,8 @@ import java.security.Principal; /** - * Minimal Realm implementation that always returns null when an attempt is made to validate a username and password. - * It is intended to be used as a default Realm implementation when no other Realm is specified. + * Minimal Realm implementation that always returns null when an attempt is made to validate a username and password. It + * is intended to be used as a default Realm implementation when no other Realm is specified. */ public class NullRealm extends RealmBase { diff -Nru tomcat10-10.1.40/java/org/apache/catalina/realm/RealmBase.java tomcat10-10.1.52/java/org/apache/catalina/realm/RealmBase.java --- tomcat10-10.1.40/java/org/apache/catalina/realm/RealmBase.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/realm/RealmBase.java 2026-01-23 19:33:36.000000000 +0000 @@ -69,8 +69,6 @@ /** * Simple implementation of Realm that reads an XML file to configure the valid users, passwords, and roles. The * file format (and default file location) are identical to those currently supported by Tomcat 3.X. - * - * @author Craig R. McClanahan */ public abstract class RealmBase extends LifecycleMBeanBase implements Realm { diff -Nru tomcat10-10.1.40/java/org/apache/catalina/realm/UserDatabaseRealm.java tomcat10-10.1.52/java/org/apache/catalina/realm/UserDatabaseRealm.java --- tomcat10-10.1.40/java/org/apache/catalina/realm/UserDatabaseRealm.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/realm/UserDatabaseRealm.java 2026-01-23 19:33:36.000000000 +0000 @@ -39,8 +39,6 @@ * available through the JNDI resources configured for this instance of Catalina. Set the resourceName * parameter to the JNDI resources name for the configured instance of UserDatabase that we should consult. * - * @author Craig R. McClanahan - * * @since 4.1 */ public class UserDatabaseRealm extends RealmBase { @@ -112,8 +110,7 @@ * Determines whether this Realm is configured to obtain the associated {@link UserDatabase} from the global JNDI * context or a local (web application) JNDI context. * - * @return {@code true} if a local JNDI context will be used, {@code false} if the global JNDI context will be - * used + * @return {@code true} if a local JNDI context will be used, {@code false} if the global JNDI context will be used */ public boolean getLocalJndiResource() { return localJndiResource; @@ -220,13 +217,13 @@ containerLog.error(sm.getString("userDatabaseRealm.noNamingContext")); return null; } - context = getServer().getGlobalNamingContext(); + context = server.getGlobalNamingContext(); } database = (UserDatabase) context.lookup(resourceName); - } catch (Throwable e) { - ExceptionUtils.handleThrowable(e); + } catch (Throwable t) { + ExceptionUtils.handleThrowable(t); if (containerLog != null) { - containerLog.error(sm.getString("userDatabaseRealm.lookup", resourceName), e); + containerLog.error(sm.getString("userDatabaseRealm.lookup", resourceName), t); } database = null; } diff -Nru tomcat10-10.1.40/java/org/apache/catalina/security/SecurityClassLoad.java tomcat10-10.1.52/java/org/apache/catalina/security/SecurityClassLoad.java --- tomcat10-10.1.40/java/org/apache/catalina/security/SecurityClassLoad.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/security/SecurityClassLoad.java 2026-01-23 19:33:36.000000000 +0000 @@ -19,8 +19,6 @@ /** * Static class used to preload java classes when using the Java SecurityManager so that the defineClassInPackage * RuntimePermission does not trigger an AccessControlException. - * - * @author Glenn L. Nielsen */ public final class SecurityClassLoad { diff -Nru tomcat10-10.1.40/java/org/apache/catalina/security/SecurityConfig.java tomcat10-10.1.52/java/org/apache/catalina/security/SecurityConfig.java --- tomcat10-10.1.40/java/org/apache/catalina/security/SecurityConfig.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/security/SecurityConfig.java 2026-01-23 19:33:36.000000000 +0000 @@ -24,8 +24,6 @@ /** * Util class to protect Catalina against package access and insertion. The code are been moved from Catalina.java - * - * @author the Catalina.java authors */ public final class SecurityConfig { diff -Nru tomcat10-10.1.40/java/org/apache/catalina/security/SecurityListener.java tomcat10-10.1.52/java/org/apache/catalina/security/SecurityListener.java --- tomcat10-10.1.40/java/org/apache/catalina/security/SecurityListener.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/security/SecurityListener.java 2026-01-23 19:33:36.000000000 +0000 @@ -221,8 +221,7 @@ if (allowedAgeDays >= 0) { String buildDateString = ServerInfo.getServerBuiltISO(); - if (null == buildDateString || buildDateString.isEmpty() || - !Character.isDigit(buildDateString.charAt(0))) { + if (null == buildDateString || buildDateString.isEmpty() || !Character.isDigit(buildDateString.charAt(0))) { log.warn(sm.getString("SecurityListener.buildDateUnreadable", buildDateString)); } else { try { diff -Nru tomcat10-10.1.40/java/org/apache/catalina/servlets/CGIServlet.java tomcat10-10.1.52/java/org/apache/catalina/servlets/CGIServlet.java --- tomcat10-10.1.40/java/org/apache/catalina/servlets/CGIServlet.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/servlets/CGIServlet.java 2026-01-23 19:33:36.000000000 +0000 @@ -43,16 +43,21 @@ import jakarta.servlet.ServletConfig; import jakarta.servlet.ServletContext; import jakarta.servlet.ServletException; +import jakarta.servlet.UnavailableException; import jakarta.servlet.http.Cookie; import jakarta.servlet.http.HttpServlet; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; import jakarta.servlet.http.HttpSession; +import org.apache.catalina.Globals; +import org.apache.catalina.WebResource; +import org.apache.catalina.WebResourceRoot; import org.apache.catalina.util.IOTools; import org.apache.juli.logging.Log; import org.apache.juli.logging.LogFactory; import org.apache.tomcat.util.compat.JrePlatform; +import org.apache.tomcat.util.http.Method; import org.apache.tomcat.util.res.StringManager; @@ -192,17 +197,12 @@ *
  • Confirm use of ServletInputStream.available() in CGIRunner.run() is not needed *
  • [add more to this TODO list] * - * - * @author Martin T Dengler [root@martindengler.com] - * @author Amy Roh */ public final class CGIServlet extends HttpServlet { private static final Log log = LogFactory.getLog(CGIServlet.class); private static final StringManager sm = StringManager.getManager(CGIServlet.class); - /* some vars below copied from Craig R. McClanahan's InvokerServlet */ - private static final long serialVersionUID = 1L; private static final Set DEFAULT_SUPER_METHODS = new HashSet<>(); @@ -210,9 +210,9 @@ private static final String ALLOW_ANY_PATTERN = ".*"; static { - DEFAULT_SUPER_METHODS.add("HEAD"); - DEFAULT_SUPER_METHODS.add("OPTIONS"); - DEFAULT_SUPER_METHODS.add("TRACE"); + DEFAULT_SUPER_METHODS.add(Method.HEAD); + DEFAULT_SUPER_METHODS.add(Method.OPTIONS); + DEFAULT_SUPER_METHODS.add(Method.TRACE); if (JrePlatform.IS_WINDOWS) { DEFAULT_CMD_LINE_ARGUMENTS_DECODED_PATTERN = Pattern.compile("[\\w\\Q-.\\/:\\E]+"); @@ -243,6 +243,8 @@ private final Set cgiMethods = new HashSet<>(); private boolean cgiMethodsAll = false; + private transient WebResourceRoot resources = null; + /** * The time (in milliseconds) to wait for the reading of stderr to complete before terminating the CGI process. @@ -283,9 +285,6 @@ /** * Sets instance variables. - *

    - * Modified from Craig R. McClanahan's InvokerServlet - *

    * * @param config a ServletConfig object containing the servlet's configuration and initialization * parameters @@ -362,8 +361,8 @@ } } } else { - cgiMethods.add("GET"); - cgiMethods.add("POST"); + cgiMethods.add(Method.GET); + cgiMethods.add(Method.POST); } if (getServletConfig().getInitParameter("cmdLineArgumentsEncoded") != null) { @@ -378,14 +377,18 @@ } else if (value != null) { cmdLineArgumentsDecodedPattern = Pattern.compile(value); } + + // Load the web resources + resources = (WebResourceRoot) getServletContext().getAttribute(Globals.RESOURCES_ATTR); + + if (resources == null) { + throw new UnavailableException(sm.getString("cgiServlet.noResources")); + } } /** * Logs important Servlet API and container information. - *

    - * Based on SnoopAllServlet by Craig R. McClanahan - *

    * * @param req HttpServletRequest object used as source of information */ @@ -541,7 +544,7 @@ CGIRunner cgi = new CGIRunner(cgiEnv.getCommand(), cgiEnv.getEnvironment(), cgiEnv.getWorkingDirectory(), cgiEnv.getParameters()); - if ("POST".equals(req.getMethod())) { + if (Method.POST.equals(req.getMethod())) { cgi.setInput(req.getInputStream()); } cgi.setResponse(res); @@ -564,7 +567,7 @@ @Override protected void doOptions(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException { // Note: This method will never be called if cgiMethods is "*" so that - // case does nto need to be handled here. + // case does not need to be handled here. Set allowedMethods = new HashSet<>(); allowedMethods.addAll(cgiMethods); allowedMethods.addAll(DEFAULT_SUPER_METHODS); @@ -621,9 +624,6 @@ /** pathInfo for the current request */ private String pathInfo = null; - /** real file system directory of the enclosing servlet's web app */ - private String webAppRootDir = null; - /** tempdir for context - used to expand scripts in unexpanded wars */ private File tmpDir = null; @@ -677,7 +677,6 @@ */ protected void setupFromContext(ServletContext context) { this.context = context; - this.webAppRootDir = context.getRealPath("/"); this.tmpDir = (File) context.getAttribute(ServletContext.TEMPDIR); } @@ -715,8 +714,8 @@ // does not contain an unencoded "=" this is an indexed query. // The parsed query string becomes the command line parameters // for the cgi command. - if (enableCmdLineArguments && (req.getMethod().equals("GET") || req.getMethod().equals("POST") || - req.getMethod().equals("HEAD"))) { + if (enableCmdLineArguments && (Method.GET.equals(req.getMethod()) || Method.POST.equals(req.getMethod()) || + Method.HEAD.equals(req.getMethod()))) { String qs; if (isIncluded) { qs = (String) req.getAttribute(RequestDispatcher.INCLUDE_QUERY_STRING); @@ -781,10 +780,9 @@ * cgiPathPrefix is defined by setting this servlet's cgiPathPrefix init parameter *

    * - * @param pathInfo String from HttpServletRequest.getPathInfo() - * @param webAppRootDir String from context.getRealPath("/") * @param contextPath String as from HttpServletRequest.getContextPath() * @param servletPath String as from HttpServletRequest.getServletPath() + * @param pathInfo String from HttpServletRequest.getPathInfo() * @param cgiPathPrefix subdirectory of webAppRootDir below which the web app's CGIs may be stored; can be null. * The CGI search path will start at webAppRootDir + File.separator + cgiPathPrefix (or * webAppRootDir alone if cgiPathPrefix is null). cgiPathPrefix is defined by setting @@ -801,59 +799,104 @@ * found * */ - protected String[] findCGI(String pathInfo, String webAppRootDir, String contextPath, String servletPath, - String cgiPathPrefix) { - String path; - String name; - String scriptname; - - if (webAppRootDir.lastIndexOf(File.separator) == (webAppRootDir.length() - 1)) { - // strip the trailing "/" from the webAppRootDir - webAppRootDir = webAppRootDir.substring(0, (webAppRootDir.length() - 1)); - } + protected String[] findCGI(String contextPath, String servletPath, String pathInfo, String cgiPathPrefix) { - if (cgiPathPrefix != null) { - webAppRootDir = webAppRootDir + File.separator + cgiPathPrefix; - } + StringBuilder cgiPath = new StringBuilder(); + StringBuilder urlPath = new StringBuilder(); - if (log.isTraceEnabled()) { - log.trace(sm.getString("cgiServlet.find.path", pathInfo, webAppRootDir)); - } + WebResource cgiScript = null; - File currentLocation = new File(webAppRootDir); - StringTokenizer dirWalker = new StringTokenizer(pathInfo, "/"); - if (log.isTraceEnabled()) { - log.trace(sm.getString("cgiServlet.find.location", currentLocation.getAbsolutePath())); + if (cgiPathPrefix == null || cgiPathPrefix.isEmpty()) { + cgiPath.append(servletPath); + } else { + cgiPath.append('/'); + cgiPath.append(cgiPathPrefix); } - StringBuilder cginameBuilder = new StringBuilder(); - while (!currentLocation.isFile() && dirWalker.hasMoreElements()) { - String nextElement = (String) dirWalker.nextElement(); - currentLocation = new File(currentLocation, nextElement); - cginameBuilder.append('/').append(nextElement); + urlPath.append(servletPath); + + StringTokenizer pathWalker = new StringTokenizer(pathInfo, "/"); + + while (pathWalker.hasMoreElements() && (cgiScript == null || !cgiScript.isFile())) { + String urlSegment = pathWalker.nextToken(); + cgiPath.append('/'); + cgiPath.append(urlSegment); + urlPath.append('/'); + urlPath.append(urlSegment); if (log.isTraceEnabled()) { - log.trace(sm.getString("cgiServlet.find.location", currentLocation.getAbsolutePath())); + log.trace(sm.getString("cgiServlet.find.location", cgiPath.toString())); } + cgiScript = resources.getResource(cgiPath.toString()); } - String cginame = cginameBuilder.toString(); - if (!currentLocation.isFile()) { + + // No script was found + if (cgiScript == null || !cgiScript.isFile()) { return new String[] { null, null, null, null }; } - path = currentLocation.getAbsolutePath(); - name = currentLocation.getName(); + // Set-up return values + String path = null; + String scriptName = null; + String cgiName = null; + String name = null; - if (servletPath.startsWith(cginame)) { - scriptname = contextPath + cginame; - } else { - scriptname = contextPath + servletPath + cginame; + path = cgiScript.getCanonicalPath(); + if (path == null) { + /* + * The script doesn't exist directly on the file system. It might be located in an archive or similar. + * Such scripts are extracted to the web application's temporary file location. + */ + File tmpCgiFile = new File(tmpDir + cgiPath.toString()); + if (!tmpCgiFile.exists()) { + + // Create directories + File parent = tmpCgiFile.getParentFile(); + if (!parent.mkdirs() && !parent.isDirectory()) { + log.warn(sm.getString("cgiServlet.expandCreateDirFail", parent.getAbsolutePath())); + return new String[] { null, null, null, null }; + } + + try (InputStream is = cgiScript.getInputStream()) { + synchronized (expandFileLock) { + // Check if file was created by concurrent request + if (!tmpCgiFile.exists()) { + try { + Files.copy(is, tmpCgiFile.toPath()); + } catch (IOException ioe) { + log.warn(sm.getString("cgiServlet.expandFail", cgiScript.getURL(), + tmpCgiFile.getAbsolutePath()), ioe); + if (tmpCgiFile.exists()) { + if (!tmpCgiFile.delete()) { + log.warn(sm.getString("cgiServlet.expandDeleteFail", + tmpCgiFile.getAbsolutePath())); + } + } + return new String[] { null, null, null, null }; + } + if (log.isDebugEnabled()) { + log.debug(sm.getString("cgiServlet.expandOk", cgiScript.getURL(), + tmpCgiFile.getAbsolutePath())); + } + } + } + } catch (IOException ioe) { + log.warn(sm.getString("cgiServlet.expandCloseFail", cgiScript.getURL()), ioe); + } + } + path = tmpCgiFile.getAbsolutePath(); } + scriptName = urlPath.toString(); + cgiName = scriptName.substring(servletPath.length()); + name = scriptName.substring(scriptName.lastIndexOf('/') + 1); + if (log.isTraceEnabled()) { - log.trace(sm.getString("cgiServlet.find.found", name, path, scriptname, cginame)); + log.trace(sm.getString("cgiServlet.find.found", name, path, scriptName, cgiName)); } - return new String[] { path, scriptname, cginame, name }; + + return new String[] { path, scriptName, cgiName, name }; } + /** * Constructs the CGI environment to be supplied to the invoked CGI script; relies heavily on Servlet API * methods and findCGI @@ -888,13 +931,7 @@ sPathInfoOrig = this.pathInfo; sPathInfoOrig = sPathInfoOrig == null ? "" : sPathInfoOrig; - if (webAppRootDir == null) { - // The app has not been deployed in exploded form - webAppRootDir = tmpDir.toString(); - expandCGIScript(); - } - - sCGINames = findCGI(sPathInfoOrig, webAppRootDir, contextPath, servletPath, cgiPathPrefix); + sCGINames = findCGI(contextPath, servletPath, sPathInfoOrig, cgiPathPrefix); sCGIFullPath = sCGINames[0]; sCGIScriptName = sCGINames[1]; @@ -1021,93 +1058,6 @@ } /** - * Extracts requested resource from web app archive to context work directory to enable CGI script to be - * executed. - */ - protected void expandCGIScript() { - StringBuilder srcPath = new StringBuilder(); - StringBuilder destPath = new StringBuilder(); - InputStream is = null; - - // paths depend on mapping - if (cgiPathPrefix == null) { - srcPath.append(pathInfo); - is = context.getResourceAsStream(srcPath.toString()); - destPath.append(tmpDir); - destPath.append(pathInfo); - } else { - // essentially same search algorithm as findCGI() - srcPath.append(cgiPathPrefix); - StringTokenizer pathWalker = new StringTokenizer(pathInfo, "/"); - // start with first element - while (pathWalker.hasMoreElements() && (is == null)) { - srcPath.append('/'); - srcPath.append(pathWalker.nextElement()); - is = context.getResourceAsStream(srcPath.toString()); - } - destPath.append(tmpDir); - destPath.append('/'); - destPath.append(srcPath); - } - - if (is == null) { - // didn't find anything, give up now - log.warn(sm.getString("cgiServlet.expandNotFound", srcPath)); - return; - } - - try { - File f = new File(destPath.toString()); - if (f.exists()) { - // Don't need to expand if it already exists - return; - } - - // create directories - File dir = f.getParentFile(); - if (!dir.mkdirs() && !dir.isDirectory()) { - log.warn(sm.getString("cgiServlet.expandCreateDirFail", dir.getAbsolutePath())); - return; - } - - try { - synchronized (expandFileLock) { - // make sure file doesn't exist - if (f.exists()) { - return; - } - - // create file - if (!f.createNewFile()) { - return; - } - - Files.copy(is, f.toPath()); - - if (log.isDebugEnabled()) { - log.debug(sm.getString("cgiServlet.expandOk", srcPath, destPath)); - } - } - } catch (IOException ioe) { - log.warn(sm.getString("cgiServlet.expandFail", srcPath, destPath), ioe); - // delete in case file is corrupted - if (f.exists()) { - if (!f.delete()) { - log.warn(sm.getString("cgiServlet.expandDeleteFail", f.getAbsolutePath())); - } - } - } - } finally { - try { - is.close(); - } catch (IOException e) { - log.warn(sm.getString("cgiServlet.expandCloseFail", srcPath), e); - } - } - } - - - /** * Returns important CGI environment information in a multi-line text format. * * @return CGI environment info @@ -1402,9 +1352,9 @@ *
  • Allowed characters in path segments: This implementation does not allow non-terminal NULL segments * in the path -- IOExceptions may be thrown; *
  • "." and ".." path segments: This implementation does not allow - * "." and ".." in the path, and such characters will result in an IOException - * being thrown (this should never happen since Tomcat normalises the requestURI before determining the - * contextPath, servletPath and pathInfo); + * "." and ".." in the path, and such characters will result in an IOException being + * thrown (this should never happen since Tomcat normalises the requestURI before determining the contextPath, + * servletPath and pathInfo); *
  • Implementation limitations: This implementation does not impose any limitations except as * documented above. This implementation may be limited by the servlet container used to house this * implementation. In particular, all the primary CGI variable values are derived either directly or indirectly @@ -1435,14 +1385,10 @@ throw new IOException(sm.getString("cgiServlet.invalidCommand", command)); } - /* - * original content/structure of this section taken from - * http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4216884 with major modifications by Martin Dengler - */ Runtime rt; BufferedReader cgiHeaderReader = null; InputStream cgiOutput = null; - BufferedReader commandsStdErr ; + BufferedReader commandsStdErr; Thread errReaderThread = null; BufferedOutputStream commandsStdIn; Process proc = null; @@ -1552,9 +1498,9 @@ } } // replacement for Process.waitFor() - } catch (IOException e) { - log.warn(sm.getString("cgiServlet.runFail"), e); - throw e; + } catch (IOException ioe) { + log.warn(sm.getString("cgiServlet.runFail"), ioe); + throw ioe; } finally { // Close the header reader if (cgiHeaderReader != null) { @@ -1577,7 +1523,7 @@ try { errReaderThread.join(stderrTimeout); } catch (InterruptedException e) { - log.warn(sm.getString("cgiServlet.runReaderInterrupt")); + log.warn(sm.getString("cgiServlet.runReaderInterrupt"), e); } } if (proc != null) { @@ -1655,13 +1601,13 @@ log.warn(sm.getString("cgiServlet.runStdErr", line)); lineCount++; } - } catch (IOException e) { - log.warn(sm.getString("cgiServlet.runStdErrFail"), e); + } catch (IOException ioe) { + log.warn(sm.getString("cgiServlet.runStdErrFail"), ioe); } finally { try { rdr.close(); - } catch (IOException e) { - log.warn(sm.getString("cgiServlet.runStdErrFail"), e); + } catch (IOException ioe) { + log.warn(sm.getString("cgiServlet.runStdErrFail"), ioe); } } if (lineCount > 0) { diff -Nru tomcat10-10.1.40/java/org/apache/catalina/servlets/DefaultServlet.java tomcat10-10.1.52/java/org/apache/catalina/servlets/DefaultServlet.java --- tomcat10-10.1.40/java/org/apache/catalina/servlets/DefaultServlet.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/servlets/DefaultServlet.java 2026-01-23 19:33:36.000000000 +0000 @@ -79,6 +79,7 @@ import org.apache.catalina.webresources.CachedResource; import org.apache.tomcat.util.buf.B2CConverter; import org.apache.tomcat.util.http.FastHttpDateFormat; +import org.apache.tomcat.util.http.Method; import org.apache.tomcat.util.http.ResponseUtil; import org.apache.tomcat.util.http.parser.ContentRange; import org.apache.tomcat.util.http.parser.EntityTag; @@ -136,9 +137,6 @@ * Then a request to /context/static/images/tomcat.jpg will succeed while a request to * /context/images/tomcat2.jpg will fail. *

    - * - * @author Craig R. McClanahan - * @author Remy Maucherat */ public class DefaultServlet extends HttpServlet { @@ -687,8 +685,8 @@ } } else { try { - resp.sendError(resourceInputStream != null ? - HttpServletResponse.SC_CONFLICT : HttpServletResponse.SC_BAD_REQUEST); + resp.sendError(resourceInputStream != null ? HttpServletResponse.SC_CONFLICT : + HttpServletResponse.SC_BAD_REQUEST); } catch (IllegalStateException e) { // Already committed, ignore } @@ -697,7 +695,7 @@ if (resourceInputStream != null) { try { resourceInputStream.close(); - } catch (IOException ioe) { + } catch (IOException ignore) { // Ignore } } @@ -756,17 +754,18 @@ int numBytesRead; byte[] transferBuffer = new byte[BUFFER_SIZE]; try (BufferedInputStream requestBufInStream = new BufferedInputStream(req.getInputStream(), BUFFER_SIZE)) { + long rangeBytes = range.getEnd() - range.getStart() + 1L; while ((numBytesRead = requestBufInStream.read(transferBuffer)) != -1) { received += numBytesRead; - if (received > range.getEnd() - range.getStart()) { + if (received > rangeBytes) { throw new IllegalStateException(sm.getString("defaultServlet.wrongByteCountForRange", - String.valueOf(received), String.valueOf(range.getEnd() - range.getStart()))); + String.valueOf(received), String.valueOf(rangeBytes))); } randAccessContentFile.write(transferBuffer, 0, numBytesRead); } - if (received < range.getEnd() - range.getStart()) { + if (received < rangeBytes) { throw new IllegalStateException(sm.getString("defaultServlet.wrongByteCountForRange", - String.valueOf(received), String.valueOf(range.getEnd() - range.getStart()))); + String.valueOf(received), String.valueOf(rangeBytes))); } } @@ -1096,7 +1095,7 @@ response.setContentType(contentType); } } - if (resource.isFile() && contentLength >= 0 && (!serveContent || ostream != null)) { + if (resource.isFile() && contentLength >= 0 && (!serveContent || ostream != null || writer != null)) { if (debug > 0) { log("DefaultServlet.serveFile: contentLength=" + contentLength); } @@ -1110,8 +1109,8 @@ if (serveContent) { try { response.setBufferSize(output); - } catch (IllegalStateException e) { - // Silent catch + } catch (IllegalStateException ignore) { + // Content has already been written - this must be an include. Ignore the error and continue. } InputStream renderResult = null; if (ostream == null) { @@ -1224,8 +1223,8 @@ if (serveContent) { try { response.setBufferSize(output); - } catch (IllegalStateException e) { - // Silent catch + } catch (IllegalStateException ignore) { + // Content has already been written - this must be an include. Ignore the error and continue. } if (ostream != null) { if (!checkSendfile(request, response, resource, contentLength, range)) { @@ -1242,7 +1241,7 @@ try { response.setBufferSize(output); } catch (IllegalStateException e) { - // Silent catch + // Content has already been written - this must be an include. Ignore the error and continue. } if (ostream != null) { copy(resource, contentLength, ostream, ranges, contentType); @@ -1572,7 +1571,7 @@ return FULL; } - if (!"GET".equals(request.getMethod()) || !isRangeRequestsSupported()) { + if (!Method.GET.equals(request.getMethod()) || !isRangeRequestsSupported()) { // RFC 9110 - Section 14.2: GET is the only method for which range handling is defined. // Otherwise MUST ignore a Range header field return FULL; @@ -2038,15 +2037,15 @@ } IOException e = copyRange(reader, new PrintWriter(buffer)); if (debug > 10) { - log("readme '" + readmeFile + "' output error: " + e.getMessage()); + log("readme '" + readmeFile + "' output error: " + ((e != null) ? e.getMessage() : "")); } - } catch (IOException e) { - log(sm.getString("defaultServlet.readerCloseFailed"), e); + } catch (IOException ioe) { + log(sm.getString("defaultServlet.readerCloseFailed"), ioe); } finally { if (reader != null) { try { reader.close(); - } catch (IOException e) { + } catch (IOException ignore) { // Ignore } } @@ -2312,7 +2311,7 @@ WebResource resource) { String method = request.getMethod(); - if (!"GET".equals(method) && !"HEAD".equals(method)) { + if (!Method.GET.equals(method) && !Method.HEAD.equals(method)) { return true; } @@ -2420,7 +2419,7 @@ // 304 Not Modified. // For every other method, 412 Precondition Failed is sent // back. - if ("GET".equals(request.getMethod()) || "HEAD".equals(request.getMethod())) { + if (Method.GET.equals(request.getMethod()) || Method.HEAD.equals(request.getMethod())) { response.setStatus(HttpServletResponse.SC_NOT_MODIFIED); response.setHeader("ETag", resourceETag); } else { @@ -2510,8 +2509,7 @@ if (headerValue.length() > 2 && (headerValue.charAt(0) == '"' || headerValue.charAt(2) == '"')) { boolean weakETag = headerValue.startsWith("W/\""); - if ((!weakETag && headerValue.charAt(0) != '"') || - headerValue.charAt(headerValue.length() - 1) != '"' || + if ((!weakETag && headerValue.charAt(0) != '"') || headerValue.charAt(headerValue.length() - 1) != '"' || headerValue.indexOf('"', weakETag ? 3 : 1) != headerValue.length() - 1) { // Not a single entity tag response.sendError(HttpServletResponse.SC_BAD_REQUEST); @@ -2524,7 +2522,7 @@ long headerValueTime = -1L; try { headerValueTime = request.getDateHeader("If-Range"); - } catch (IllegalArgumentException e) { + } catch (IllegalArgumentException ignore) { // Ignore } if (headerValueTime >= 0) { @@ -2725,8 +2723,8 @@ break; } ostream.write(buffer, 0, len); - } catch (IOException e) { - exception = e; + } catch (IOException ioe) { + exception = ioe; break; } } @@ -2756,8 +2754,8 @@ break; } writer.write(buffer, 0, len); - } catch (IOException e) { - exception = e; + } catch (IOException ioe) { + exception = ioe; break; } } @@ -2786,8 +2784,8 @@ long skipped; try { skipped = istream.skip(start); - } catch (IOException e) { - return e; + } catch (IOException ioe) { + return ioe; } if (skipped < start) { return new IOException(sm.getString("defaultServlet.skipfail", Long.valueOf(skipped), Long.valueOf(start))); @@ -2808,8 +2806,8 @@ ostream.write(buffer, 0, (int) bytesToRead); bytesToRead = 0; } - } catch (IOException e) { - exception = e; + } catch (IOException ioe) { + exception = ioe; len = -1; } } diff -Nru tomcat10-10.1.40/java/org/apache/catalina/servlets/LocalStrings.properties tomcat10-10.1.52/java/org/apache/catalina/servlets/LocalStrings.properties --- tomcat10-10.1.40/java/org/apache/catalina/servlets/LocalStrings.properties 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/servlets/LocalStrings.properties 2026-01-23 19:33:36.000000000 +0000 @@ -21,7 +21,6 @@ cgiServlet.expandCreateDirFail=Failed to create destination directory [{0}] for script expansion cgiServlet.expandDeleteFail=Failed to delete file at [{0}] after IOException during expansion cgiServlet.expandFail=Failed to expand script at path [{0}] to [{1}] -cgiServlet.expandNotFound=Unable to expand [{0}] as it could not be found cgiServlet.expandOk=Expanded script at path [{0}] to [{1}] cgiServlet.find.found=Found CGI: name [{0}], path [{1}], script name [{2}] and CGI name [{3}] cgiServlet.find.location=Looking for a file at [{0}] @@ -29,6 +28,7 @@ cgiServlet.invalidArgumentDecoded=The decoded command line argument [{0}] did not match the configured cmdLineArgumentsDecoded pattern [{1}] cgiServlet.invalidArgumentEncoded=The encoded command line argument [{0}] did not match the configured cmdLineArgumentsEncoded pattern [{1}] cgiServlet.invalidCommand=Illegal Character in CGI command path ('.' or '..') detected, not running CGI [{0}] +cgiServlet.noResources=No static resources were found cgiServlet.notReady=CGI Servlet is not ready to run cgiServlet.runBadHeader=Bad header line [{0}] cgiServlet.runFail=I/O problems processing CGI diff -Nru tomcat10-10.1.40/java/org/apache/catalina/servlets/LocalStrings_fr.properties tomcat10-10.1.52/java/org/apache/catalina/servlets/LocalStrings_fr.properties --- tomcat10-10.1.40/java/org/apache/catalina/servlets/LocalStrings_fr.properties 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/servlets/LocalStrings_fr.properties 2026-01-23 19:33:36.000000000 +0000 @@ -21,7 +21,6 @@ cgiServlet.expandCreateDirFail=Echec de la création du répertoire de destination [{0}] pour la décompression du script cgiServlet.expandDeleteFail=Impossible d''effacer le fichier [{0}] suite à une IOException pendant la décompression cgiServlet.expandFail=Impossible de faire l''expansion du script au chemin [{0}] vers [{1}] -cgiServlet.expandNotFound=Impossible de décompresser [{0}] car il n''a pas été trouvé cgiServlet.expandOk=Extrait le script du chemin [{0}] vers [{1}] cgiServlet.find.found=Trouvé le CGI : nom [{0}], chemin [{1}], nom de script [{2}] et nom du CGI [{3}] cgiServlet.find.location=Recherche d''un fichier en [{0}] @@ -29,6 +28,7 @@ cgiServlet.invalidArgumentDecoded=Les paramètres de ligne de commande décodés [{0}] ne correspondent pas au modèle cmdLineArgumentsDecoded configuré [{1}] cgiServlet.invalidArgumentEncoded=Les paramètres de ligne de commande encodés [{0}] ne correspondent pas au modèle cmdLineArgumentsEncoded configuré [{1}] cgiServlet.invalidCommand=Un caractère illégal (''.'' or ''..'') a été trouvé dans le chemin de commande CGI, le CGI [{0}] n''est pas exécuté +cgiServlet.noResources=Pas de ressources statiques trouvées cgiServlet.notReady=Le Servlet CGI n'est pas prêt à fonctionner cgiServlet.runBadHeader=Mauvaise ligne d''en-tête [{0}] cgiServlet.runFail=Problèmes d'IO lors de l'exécution du CGI @@ -54,6 +54,7 @@ defaultServlet.resource.size=Taille defaultServlet.skipfail=La lecture a échouée parce que seuls [{0}] octets étaient disponibles alors qu''il était nécessaire d''en sauter [{1}] pour atteindre le début de la plage demandée defaultServlet.unknownBomConfig=La valeur [{0}] inconnue a été donnée pour le paramètre d’initialisation useBomIfPresent +defaultServlet.wrongByteCountForRange=Une quantité invalide d''octets [{0}] a été reçue pour la range dont la longueur est [{1}] defaultServlet.xslError=Erreur de transformation XSL webdavservlet.dataSourceStore.error=Erreur [{0}] lors du traitement des prorpiétés pour le chemin [{1}] diff -Nru tomcat10-10.1.40/java/org/apache/catalina/servlets/LocalStrings_ja.properties tomcat10-10.1.52/java/org/apache/catalina/servlets/LocalStrings_ja.properties --- tomcat10-10.1.40/java/org/apache/catalina/servlets/LocalStrings_ja.properties 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/servlets/LocalStrings_ja.properties 2026-01-23 19:33:36.000000000 +0000 @@ -21,7 +21,6 @@ cgiServlet.expandCreateDirFail=スクリプトの展開先ディレクトリ[{0}]の作成に失敗しました。 cgiServlet.expandDeleteFail=拡張中にIOExceptionの後に [{0}] でファイルを削除できませんでした cgiServlet.expandFail=パス [{0}] のスクリプトを [{1}] に展開できませんでした -cgiServlet.expandNotFound=見つけることができなかったため [{0}] を展開できません cgiServlet.expandOk=パス [{0}] の [{1}] に展開されたスクリプト cgiServlet.find.found=見つかったCGI: 名前 [{0}]、パス [{1}]、スクリプト名 [{2}]、CGI名 [{3}] cgiServlet.find.location=ファイル [{0}] を探しています。 @@ -29,6 +28,7 @@ cgiServlet.invalidArgumentDecoded=デコードされたコマンドライン引数 [{0}] は、構成されたcmdLineArgumentsDecoded パターン [{1}] にマッチしません cgiServlet.invalidArgumentEncoded=エンコードされたコマンドライン引数 [{0}] は、構成されたcmdLineArgumentsEncoded パターン [{1}] にマッチしません cgiServlet.invalidCommand=CGI コマンド パスに不正な文字 (''.'' または ''..'') が検出されました。CGI [{0}] は実行されていません +cgiServlet.noResources=静的リソースが見つかりませんでした cgiServlet.notReady=CGI サーブレットは実行の準備ができていません cgiServlet.runBadHeader=悪いヘッダライン [{0}] cgiServlet.runFail=CGI処理中のIO問題 @@ -54,6 +54,7 @@ defaultServlet.resource.size=サイズ defaultServlet.skipfail=[{1}]バイトをスキップして要求された範囲の先頭に到達する必要がありましたが、[{0}]バイトしか利用できなかったため読み取りに失敗しました。 defaultServlet.unknownBomConfig=useBomIfPresentの初期化パラメーターに提供された認識されない値 [{0}] +defaultServlet.wrongByteCountForRange=長さ [{1}] の範囲に対して無効な [{0}] バイトを受信しました defaultServlet.xslError=XSL変換エラー webdavservlet.dataSourceStore.error=パス [{1}] の無効なプロパティで [{0}] を処理中にエラーが発生しました diff -Nru tomcat10-10.1.40/java/org/apache/catalina/servlets/LocalStrings_ko.properties tomcat10-10.1.52/java/org/apache/catalina/servlets/LocalStrings_ko.properties --- tomcat10-10.1.40/java/org/apache/catalina/servlets/LocalStrings_ko.properties 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/servlets/LocalStrings_ko.properties 2026-01-23 19:33:36.000000000 +0000 @@ -21,7 +21,6 @@ cgiServlet.expandCreateDirFail=스크립트를 압축해제 하기 위한 대상 디렉토리 [{0}]을(를) 생성하지 못했습니다. cgiServlet.expandDeleteFail=압축해제 중 IOException이 발생한 후, [{0}]에 위치한 해당 파일을 삭제하지 못했습니다. cgiServlet.expandFail=경로 [{0}]의 스크립트를 [{1}](으)로 압축해제 하지 못했습니다. -cgiServlet.expandNotFound=[{0}]을(를) 찾을 수 없어서 압축해제 할 수 없습니다. cgiServlet.expandOk=[{0}] 경로에 있는 스트립트가 [{1}](으)로 압축 해제되었습니다. cgiServlet.find.found=CGI 발견: 이름 [{0}], 경로 [{1}], 스크립트 이름 [{2}], CGI 이름 [{3}] cgiServlet.find.location=[{0}]에 위치한 파일을 찾는 중 diff -Nru tomcat10-10.1.40/java/org/apache/catalina/servlets/LocalStrings_ru.properties tomcat10-10.1.52/java/org/apache/catalina/servlets/LocalStrings_ru.properties --- tomcat10-10.1.40/java/org/apache/catalina/servlets/LocalStrings_ru.properties 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/servlets/LocalStrings_ru.properties 2026-01-23 19:33:36.000000000 +0000 @@ -17,6 +17,7 @@ # To edit translations see: https://tomcat.apache.org/getinvolved.html#Translations cgiServlet.expandFail=Невозможно развернуть скрипт [{0}] в [{1}] +cgiServlet.find.location=Поиск файла в [{0}] cgiServlet.runInvalidStatus=Неверный статус [{0}] defaultServlet.skipfail=Чтение завершилось ошибкой, потому что только [{0}] байт было доступно, а требовалось пропустить [{1}] байт, чтобы достигнуть начала требуемоего диапазона diff -Nru tomcat10-10.1.40/java/org/apache/catalina/servlets/LocalStrings_zh_CN.properties tomcat10-10.1.52/java/org/apache/catalina/servlets/LocalStrings_zh_CN.properties --- tomcat10-10.1.40/java/org/apache/catalina/servlets/LocalStrings_zh_CN.properties 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/servlets/LocalStrings_zh_CN.properties 2026-01-23 19:33:36.000000000 +0000 @@ -21,7 +21,6 @@ cgiServlet.expandCreateDirFail=无法为脚本扩展创建目标目录[{0}] cgiServlet.expandDeleteFail=扩展期间,发生IOException异常后删除文件[{0}]失败 cgiServlet.expandFail=在路径[{0}] 到[{1}] 展开脚本失败. -cgiServlet.expandNotFound=无法展开[{0}],因为找不到它。 cgiServlet.expandOk=从路径[{0}]到[{1}]扩展脚本 cgiServlet.find.found=找到CGI:name[{0}]、path[{1}]、script name[{2}]和CGI name[{3}] cgiServlet.find.location=在 [{0}] 查找文件 diff -Nru tomcat10-10.1.40/java/org/apache/catalina/servlets/WebdavServlet.java tomcat10-10.1.52/java/org/apache/catalina/servlets/WebdavServlet.java --- tomcat10-10.1.40/java/org/apache/catalina/servlets/WebdavServlet.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/servlets/WebdavServlet.java 2026-01-23 19:33:36.000000000 +0000 @@ -63,6 +63,7 @@ import org.apache.tomcat.util.IntrospectionUtils; import org.apache.tomcat.util.http.ConcurrentDateFormat; import org.apache.tomcat.util.http.FastHttpDateFormat; +import org.apache.tomcat.util.http.Method; import org.apache.tomcat.util.http.RequestUtil; import org.apache.tomcat.util.http.WebdavIfHeader; import org.w3c.dom.Document; @@ -98,6 +99,9 @@ * functionality. In particular, administrators should be aware that security constraints apply only to the request URL. * Security constraints do not apply to any destination URL associated with the WebDAV operation (such as COPY or MOVE). *

    + * If WebDAV functionality is included in a web application where legitimate users may access it via a browser, it is + * recommended that the application include CORS protection. + *

    * To enable WebDAV for a context add the following to web.xml: * *

    @@ -178,17 +182,6 @@
         private static final long serialVersionUID = 1L;
     
     
    -    // -------------------------------------------------------------- Constants
    -
    -    private static final String METHOD_PROPFIND = "PROPFIND";
    -    private static final String METHOD_PROPPATCH = "PROPPATCH";
    -    private static final String METHOD_MKCOL = "MKCOL";
    -    private static final String METHOD_COPY = "COPY";
    -    private static final String METHOD_MOVE = "MOVE";
    -    private static final String METHOD_LOCK = "LOCK";
    -    private static final String METHOD_UNLOCK = "UNLOCK";
    -
    -
         /**
          * Default lock timeout value.
          */
    @@ -571,19 +564,19 @@
                 log("[" + method + "] " + path);
             }
     
    -        if (method.equals(METHOD_PROPFIND)) {
    +        if (Method.PROPFIND.equals(method)) {
                 doPropfind(req, resp);
    -        } else if (method.equals(METHOD_PROPPATCH)) {
    +        } else if (Method.PROPPATCH.equals(method)) {
                 doProppatch(req, resp);
    -        } else if (method.equals(METHOD_MKCOL)) {
    +        } else if (Method.MKCOL.equals(method)) {
                 doMkcol(req, resp);
    -        } else if (method.equals(METHOD_COPY)) {
    +        } else if (Method.COPY.equals(method)) {
                 doCopy(req, resp);
    -        } else if (method.equals(METHOD_MOVE)) {
    +        } else if (Method.MOVE.equals(method)) {
                 doMove(req, resp);
    -        } else if (method.equals(METHOD_LOCK)) {
    +        } else if (Method.LOCK.equals(method)) {
                 doLock(req, resp);
    -        } else if (method.equals(METHOD_UNLOCK)) {
    +        } else if (Method.UNLOCK.equals(method)) {
                 doUnlock(req, resp);
             } else {
                 // DefaultServlet processing
    @@ -685,6 +678,10 @@
                     if (hrefs.hasNext()) {
                         currentHref = hrefs.next();
                         currentPath = getPathFromHref(currentHref, request);
    +                    if (currentPath == null) {
    +                        // The path was invalid
    +                        return false;
    +                    }
                         currentWebResource = resources.getResource(currentPath);
                     } else {
                         break;
    @@ -842,7 +839,7 @@
             try (InputStream is = req.getInputStream(); ByteArrayOutputStream os = new ByteArrayOutputStream()) {
                 IOTools.flow(is, os);
                 body = os.toByteArray();
    -        } catch (IOException e) {
    +        } catch (IOException ioe) {
                 resp.sendError(WebdavStatus.SC_BAD_REQUEST);
                 return;
             }
    @@ -1043,7 +1040,7 @@
             try (InputStream is = req.getInputStream(); ByteArrayOutputStream os = new ByteArrayOutputStream()) {
                 IOTools.flow(is, os);
                 body = os.toByteArray();
    -        } catch (IOException e) {
    +        } catch (IOException ioe) {
                 resp.sendError(WebdavStatus.SC_BAD_REQUEST);
                 return;
             }
    @@ -1241,7 +1238,11 @@
     
             String path = getRelativePath(req);
     
    -        deleteResource(path, req, resp);
    +        WebResource resource = resources.getResource(path);
    +        if (!checkIfHeaders(req, resp, resource)) {
    +            resp.setStatus(HttpServletResponse.SC_PRECONDITION_FAILED);
    +        }
    +        deleteResource(path, req, resp, true);
         }
     
     
    @@ -1397,7 +1398,7 @@
             try (InputStream is = req.getInputStream(); ByteArrayOutputStream os = new ByteArrayOutputStream()) {
                 IOTools.flow(is, os);
                 body = os.toByteArray();
    -        } catch (IOException e) {
    +        } catch (IOException ioe) {
                 resp.sendError(WebdavStatus.SC_BAD_REQUEST);
                 return;
             }
    @@ -1847,7 +1848,7 @@
             if (!allowSpecialPaths) {
                 String upperCasePath = path.toUpperCase(Locale.ENGLISH);
                 return upperCasePath.startsWith("/WEB-INF/") || upperCasePath.startsWith("/META-INF/") ||
    -                upperCasePath.equals("/WEB-INF") || upperCasePath.equals("/META-INF");
    +                    upperCasePath.equals("/WEB-INF") || upperCasePath.equals("/META-INF");
             }
             return false;
         }
    @@ -1975,7 +1976,7 @@
                         if (parentPath == path || parentLock.depth > 0) {
                             if (parentLock.isExclusive()) {
                                 return !ifHeader.contains(":" + parentLock.token + ">") ||
    -                                (parentLock.principal != null && !parentLock.principal.equals(principal));
    +                                    (parentLock.principal != null && !parentLock.principal.equals(principal));
                             } else {
                                 for (String token : parentLock.sharedTokens) {
                                     LockInfo lock = sharedLocks.get(token);
    @@ -2260,8 +2261,8 @@
                     } else {
                         store.copy(source, dest);
                     }
    -            } catch (IOException e) {
    -                log(sm.getString("webdavservlet.inputstreamclosefail", source), e);
    +            } catch (IOException ioe) {
    +                log(sm.getString("webdavservlet.inputstreamclosefail", source), ioe);
                 }
             } else {
                 errorList.put(source, Integer.valueOf(WebdavStatus.SC_INTERNAL_SERVER_ERROR));
    @@ -2274,27 +2275,6 @@
         /**
          * Delete a resource.
          *
    -     * @param path Path of the resource which is to be deleted
    -     * @param req  Servlet request
    -     * @param resp Servlet response
    -     *
    -     * @return true if the delete is successful
    -     *
    -     * @throws IOException If an IO error occurs
    -     */
    -    private boolean deleteResource(String path, HttpServletRequest req, HttpServletResponse resp) throws IOException {
    -        WebResource resource = resources.getResource(path);
    -        if (!checkIfHeaders(req, resp, resource)) {
    -            resp.setStatus(HttpServletResponse.SC_PRECONDITION_FAILED);
    -            return false;
    -        }
    -        return deleteResource(path, req, resp, true);
    -    }
    -
    -
    -    /**
    -     * Delete a resource.
    -     *
          * @param path      Path of the resource which is to be deleted
          * @param req       Servlet request
          * @param resp      Servlet response
    @@ -2752,8 +2732,8 @@
     
         private static boolean propertyEquals(Node node1, Node node2) {
             return node1.getLocalName().equals(node2.getLocalName()) &&
    -            ((node1.getNamespaceURI() == null && node2.getNamespaceURI() == null) ||
    -                (node1.getNamespaceURI() != null && node1.getNamespaceURI().equals(node2.getNamespaceURI())));
    +                ((node1.getNamespaceURI() == null && node2.getNamespaceURI() == null) ||
    +                        (node1.getNamespaceURI() != null && node1.getNamespaceURI().equals(node2.getNamespaceURI())));
         }
     
     
    @@ -3045,8 +3025,6 @@
     /**
      * Wraps the HttpServletResponse class to abstract the specific protocol used. To support other protocols we would only
      * need to modify this class and the WebDavRetCode classes.
    - *
    - * @author Marc Eaddy
      */
     class WebdavStatus {
     
    diff -Nru tomcat10-10.1.40/java/org/apache/catalina/session/Constants.java tomcat10-10.1.52/java/org/apache/catalina/session/Constants.java
    --- tomcat10-10.1.40/java/org/apache/catalina/session/Constants.java	2025-04-01 18:12:59.000000000 +0000
    +++ tomcat10-10.1.52/java/org/apache/catalina/session/Constants.java	2026-01-23 19:33:36.000000000 +0000
    @@ -23,8 +23,6 @@
     
     /**
      * Manifest constants for the org.apache.catalina.session package.
    - *
    - * @author Craig R. McClanahan
      */
     
     public class Constants {
    diff -Nru tomcat10-10.1.40/java/org/apache/catalina/session/DataSourceStore.java tomcat10-10.1.52/java/org/apache/catalina/session/DataSourceStore.java
    --- tomcat10-10.1.40/java/org/apache/catalina/session/DataSourceStore.java	2025-04-01 18:12:59.000000000 +0000
    +++ tomcat10-10.1.52/java/org/apache/catalina/session/DataSourceStore.java	2026-01-23 19:33:36.000000000 +0000
    @@ -46,8 +46,6 @@
     /**
      * Implementation of the {@link org.apache.catalina.Store Store} interface that stores serialized session objects in a
      * database. Sessions that are saved are still subject to being expired based on inactivity.
    - *
    - * @author Bip Thelin
      */
     public class DataSourceStore extends StoreBase {
     
    @@ -363,7 +361,7 @@
                         }
                     }
                 } catch (SQLException e) {
    -                manager.getContext().getLogger().error(sm.getString("dataSourceStore.SQLException", e));
    +                manager.getContext().getLogger().error(sm.getString("dataSourceStore.SQLException"), e);
                     keys = new String[0];
                     // Close the connection so that it gets reopened next time
                 } finally {
    @@ -397,7 +395,7 @@
                         numberOfTries = 0;
                     }
                 } catch (SQLException e) {
    -                manager.getContext().getLogger().error(sm.getString("dataSourceStore.SQLException", e));
    +                manager.getContext().getLogger().error(sm.getString("dataSourceStore.SQLException"), e);
                 } finally {
                     release(_conn);
                 }
    @@ -444,7 +442,7 @@
                         numberOfTries = 0;
                     }
                 } catch (SQLException e) {
    -                contextLog.error(sm.getString("dataSourceStore.SQLException", e));
    +                contextLog.error(sm.getString("dataSourceStore.SQLException"), e);
                 } finally {
                     context.unbind(Globals.IS_SECURITY_ENABLED, oldThreadContextCL);
                     release(_conn);
    @@ -470,7 +468,7 @@
                     // Break out after the finally block
                     numberOfTries = 0;
                 } catch (SQLException e) {
    -                manager.getContext().getLogger().error(sm.getString("dataSourceStore.SQLException", e));
    +                manager.getContext().getLogger().error(sm.getString("dataSourceStore.SQLException"), e);
                 } finally {
                     release(_conn);
                 }
    @@ -518,7 +516,7 @@
                     // Break out after the finally block
                     numberOfTries = 0;
                 } catch (SQLException e) {
    -                manager.getContext().getLogger().error(sm.getString("dataSourceStore.SQLException", e));
    +                manager.getContext().getLogger().error(sm.getString("dataSourceStore.SQLException"), e);
                 } finally {
                     release(_conn);
                 }
    @@ -564,8 +562,8 @@
                             numberOfTries = 0;
                         }
                     } catch (SQLException e) {
    -                    manager.getContext().getLogger().error(sm.getString("dataSourceStore.SQLException", e));
    -                } catch (IOException e) {
    +                    manager.getContext().getLogger().error(sm.getString("dataSourceStore.SQLException"), e);
    +                } catch (IOException ioe) {
                         // Ignore
                     } finally {
                         release(_conn);
    @@ -601,7 +599,7 @@
                     }
                 }
             } catch (SQLException ex) {
    -            manager.getContext().getLogger().error(sm.getString("dataSourceStore.checkConnectionSQLException", ex));
    +            manager.getContext().getLogger().error(sm.getString("dataSourceStore.checkConnectionSQLException"), ex);
             }
     
             return conn;
    @@ -686,7 +684,7 @@
             try {
                 dbConnection.close();
             } catch (SQLException e) {
    -            manager.getContext().getLogger().error(sm.getString("dataSourceStore.close", e));
    +            manager.getContext().getLogger().error(sm.getString("dataSourceStore.close"), e);
             }
         }
     
    diff -Nru tomcat10-10.1.40/java/org/apache/catalina/session/FileStore.java tomcat10-10.1.52/java/org/apache/catalina/session/FileStore.java
    --- tomcat10-10.1.40/java/org/apache/catalina/session/FileStore.java	2025-04-01 18:12:59.000000000 +0000
    +++ tomcat10-10.1.52/java/org/apache/catalina/session/FileStore.java	2026-01-23 19:33:36.000000000 +0000
    @@ -26,6 +26,7 @@
     import java.io.ObjectOutputStream;
     import java.util.ArrayList;
     import java.util.List;
    +import java.util.concurrent.locks.Lock;
     
     import jakarta.servlet.ServletContext;
     
    @@ -34,13 +35,12 @@
     import org.apache.catalina.Session;
     import org.apache.juli.logging.Log;
     import org.apache.juli.logging.LogFactory;
    +import org.apache.tomcat.util.concurrent.KeyedReentrantReadWriteLock;
     import org.apache.tomcat.util.res.StringManager;
     
     /**
      * Concrete implementation of the Store interface that utilizes a file per saved Session in a configured
      * directory. Sessions that are saved are still subject to being expired based on inactivity.
    - *
    - * @author Craig R. McClanahan
      */
     public final class FileStore extends StoreBase {
     
    @@ -62,7 +62,7 @@
          * The pathname of the directory in which Sessions are stored. This may be an absolute pathname, or a relative path
          * that is resolved against the temporary work directory for this application.
          */
    -    private String directory = ".";
    +    private volatile String directory = ".";
     
     
         /**
    @@ -70,6 +70,7 @@
          */
         private File directoryFile = null;
     
    +    private KeyedReentrantReadWriteLock sessionLocksById = new KeyedReentrantReadWriteLock();
     
         /**
          * Name to register for this Store, used for logging.
    @@ -98,7 +99,7 @@
          *
          * @param path The new directory path
          */
    -    public void setDirectory(String path) {
    +    public synchronized void setDirectory(String path) {
             String oldDirectory = this.directory;
             this.directory = path;
             this.directoryFile = null;
    @@ -183,7 +184,7 @@
         public Session load(String id) throws ClassNotFoundException, IOException {
             // Open an input stream to the specified pathname, if any
             File file = file(id);
    -        if (file == null || !file.exists()) {
    +        if (file == null) {
                 return null;
             }
     
    @@ -195,19 +196,28 @@
             }
     
             ClassLoader oldThreadContextCL = context.bind(Globals.IS_SECURITY_ENABLED, null);
    -
    -        try (FileInputStream fis = new FileInputStream(file.getAbsolutePath());
    -                ObjectInputStream ois = getObjectInputStream(fis)) {
    -
    -            StandardSession session = (StandardSession) manager.createEmptySession();
    -            session.readObjectData(ois);
    -            session.setManager(manager);
    -            return session;
    -        } catch (FileNotFoundException e) {
    -            if (contextLog.isDebugEnabled()) {
    -                contextLog.debug(sm.getString("fileStore.noFile", id, file.getAbsolutePath()));
    +        try {
    +            Lock readLock = sessionLocksById.getLock(id).readLock();
    +            readLock.lock();
    +            try {
    +                if (!file.exists()) {
    +                    return null;
    +                }
    +                try (FileInputStream fis = new FileInputStream(file.getAbsolutePath());
    +                        ObjectInputStream ois = getObjectInputStream(fis)) {
    +                    StandardSession session = (StandardSession) manager.createEmptySession();
    +                    session.readObjectData(ois);
    +                    session.setManager(manager);
    +                    return session;
    +                } catch (FileNotFoundException e) {
    +                    if (contextLog.isDebugEnabled()) {
    +                        contextLog.debug(sm.getString("fileStore.noFile", id, file.getAbsolutePath()), e);
    +                    }
    +                    return null;
    +                }
    +            } finally {
    +                readLock.unlock();
                 }
    -            return null;
             } finally {
                 context.unbind(Globals.IS_SECURITY_ENABLED, oldThreadContextCL);
             }
    @@ -225,8 +235,14 @@
                         .trace(sm.getString(getStoreName() + ".removing", id, file.getAbsolutePath()));
             }
     
    -        if (file.exists() && !file.delete()) {
    -            throw new IOException(sm.getString("fileStore.deleteSessionFailed", file));
    +        Lock writeLock = sessionLocksById.getLock(id).writeLock();
    +        writeLock.lock();
    +        try {
    +            if (file.exists() && !file.delete()) {
    +                throw new IOException(sm.getString("fileStore.deleteSessionFailed", file));
    +            }
    +        } finally {
    +            writeLock.unlock();
             }
         }
     
    @@ -243,9 +259,15 @@
                         .trace(sm.getString(getStoreName() + ".saving", session.getIdInternal(), file.getAbsolutePath()));
             }
     
    -        try (FileOutputStream fos = new FileOutputStream(file.getAbsolutePath());
    -                ObjectOutputStream oos = new ObjectOutputStream(new BufferedOutputStream(fos))) {
    -            ((StandardSession) session).writeObjectData(oos);
    +        Lock writeLock = sessionLocksById.getLock(session.getIdInternal()).writeLock();
    +        writeLock.lock();
    +        try {
    +            try (FileOutputStream fos = new FileOutputStream(file.getAbsolutePath());
    +                    ObjectOutputStream oos = new ObjectOutputStream(new BufferedOutputStream(fos))) {
    +                ((StandardSession) session).writeObjectData(oos);
    +            }
    +        } finally {
    +            writeLock.unlock();
             }
         }
     
    @@ -256,12 +278,12 @@
          * Return a File object representing the pathname to our session persistence directory, if any. The directory will
          * be created if it does not already exist.
          */
    -    private File directory() throws IOException {
    +    private synchronized File directory() throws IOException {
    +        // Synchronised to avoid concurrent attempts to create the directory.
             if (this.directory == null) {
                 return null;
             }
             if (this.directoryFile != null) {
    -            // NOTE: Race condition is harmless, so do not synchronize
                 return this.directoryFile;
             }
             File file = new File(this.directory);
    diff -Nru tomcat10-10.1.40/java/org/apache/catalina/session/LocalStrings.properties tomcat10-10.1.52/java/org/apache/catalina/session/LocalStrings.properties
    --- tomcat10-10.1.40/java/org/apache/catalina/session/LocalStrings.properties	2025-04-01 18:12:59.000000000 +0000
    +++ tomcat10-10.1.52/java/org/apache/catalina/session/LocalStrings.properties	2026-01-23 19:33:36.000000000 +0000
    @@ -16,11 +16,11 @@
     # Do not edit this file directly.
     # To edit translations see: https://tomcat.apache.org/getinvolved.html#Translations
     
    -dataSourceStore.SQLException=SQL Error [{0}]
    +dataSourceStore.SQLException=SQL Error
     dataSourceStore.checkConnectionDBClosed=The database connection is null or was found to be closed. Trying to re-open it.
     dataSourceStore.checkConnectionDBReOpenFail=The re-open on the database failed. The database could be down.
    -dataSourceStore.checkConnectionSQLException=A SQL exception occurred [{0}]
    -dataSourceStore.close=Exception closing database connection [{0}]
    +dataSourceStore.checkConnectionSQLException=A SQL exception occurred checking the connection
    +dataSourceStore.close=Exception closing database connection
     dataSourceStore.commitSQLException=SQLException committing connection before closing
     dataSourceStore.loading=Loading Session [{0}] from database [{1}]
     dataSourceStore.missingDataSource=No data source available
    @@ -54,7 +54,7 @@
     persistentManager.loading=Loading [{0}] persisted sessions
     persistentManager.noStore=No Store configured, persistence disabled
     persistentManager.removeError=Error removing session [{0}] from the store
    -persistentManager.serializeError=Error serializing Session [{0}]: [{1}]
    +persistentManager.serializeError=Error serializing Session [{0}]
     persistentManager.storeClearError=Error clearning all sessions from the store
     persistentManager.storeKeysException=Unable to determine the list of session IDs for sessions in the session store, assuming that the store is empty
     persistentManager.storeLoadError=Error swapping in sessions from the store
    diff -Nru tomcat10-10.1.40/java/org/apache/catalina/session/LocalStrings_es.properties tomcat10-10.1.52/java/org/apache/catalina/session/LocalStrings_es.properties
    --- tomcat10-10.1.40/java/org/apache/catalina/session/LocalStrings_es.properties	2025-04-01 18:12:59.000000000 +0000
    +++ tomcat10-10.1.52/java/org/apache/catalina/session/LocalStrings_es.properties	2026-01-23 19:33:36.000000000 +0000
    @@ -19,8 +19,8 @@
     dataSourceStore.SQLException=Error SQL [{0}]
     dataSourceStore.checkConnectionDBClosed=La conexióna a base de datos es nula o está cerrada. Intentando reabrirla.
     dataSourceStore.checkConnectionDBReOpenFail=Falló la reapertura de la base de datos. Puede que la base de datos esté caída.
    -dataSourceStore.checkConnectionSQLException=Ha tenido lugar una excepción SQL [{0}]
    -dataSourceStore.close=Excepción cerrando conexión a base de datos [{0}]
    +dataSourceStore.checkConnectionSQLException=Ha tenido lugar una excepción SQL
    +dataSourceStore.close=Excepción cerrando conexión a base de datos
     dataSourceStore.loading=Cargando Sesión [{0}] desde base de datos [{1}]
     dataSourceStore.missingDataSourceName=No se proporcionó un nombre JNDI válido
     dataSourceStore.removing=Quitando Sesión [{0}] en base de datos [{1}]
    @@ -38,7 +38,7 @@
     persistentManager.backupMaxIdle=Respaldando sesión [{0}] a Almacén, ociosa durante [{1}] segundos
     persistentManager.deserializeError=Error des-serializando Sesión [{0}]: [{1}]
     persistentManager.loading=Cargando [{0}] sesiones persistidas
    -persistentManager.serializeError=Error serializando Sesión [{0}]: [{1}]
    +persistentManager.serializeError=Error serializando Sesión [{0}]
     persistentManager.storeKeysException=Imposible determinar la lista de IDs de sesiones en la tienda de sesiones, asumiendo que la tienda esta vacia
     persistentManager.storeSizeException=No se puede determinar el numero de sesiones en el almacenamiento de sesiones, asumiendo que el almacenamiento esta vacío
     persistentManager.swapIn=Intercambiando sesión [{0}] a dentro desde Almacén
    diff -Nru tomcat10-10.1.40/java/org/apache/catalina/session/LocalStrings_fr.properties tomcat10-10.1.52/java/org/apache/catalina/session/LocalStrings_fr.properties
    --- tomcat10-10.1.40/java/org/apache/catalina/session/LocalStrings_fr.properties	2025-04-01 18:12:59.000000000 +0000
    +++ tomcat10-10.1.52/java/org/apache/catalina/session/LocalStrings_fr.properties	2026-01-23 19:33:36.000000000 +0000
    @@ -19,8 +19,8 @@
     dataSourceStore.SQLException=Erreur SQL [{0}]
     dataSourceStore.checkConnectionDBClosed=La connexion à la base de données est nulle ou a été trouvée fermée. Tentative de réouverture.
     dataSourceStore.checkConnectionDBReOpenFail=La tentative de réouverture de la base de données a échoué. La base de données est peut-être arrêtée.
    -dataSourceStore.checkConnectionSQLException=Une exception SQL s''est produite [{0}]
    -dataSourceStore.close=Exception lors de la fermeture de la connection vers la base de donnée [{0}]
    +dataSourceStore.checkConnectionSQLException=Une exception SQL s'est produite
    +dataSourceStore.close=Exception lors de la fermeture de la connection vers la base de donnée
     dataSourceStore.commitSQLException=Une SQLException a été retournée lors du commit de la connection avant sa fermeture
     dataSourceStore.loading=Chargement de la Session [{0}] depuis la base de données [{1}]
     dataSourceStore.missingDataSource=Aucune source de données n'est disponible
    @@ -54,7 +54,7 @@
     persistentManager.loading=Chargement de [{0}] sessions persistantes
     persistentManager.noStore=Aucun stockage (Store) n'a été configuré, la persistence est désactivée
     persistentManager.removeError=Erreur en enlevant la session [{0}] du stockage
    -persistentManager.serializeError=Erreur lors de la sérialisation de la session [{0}] : [{1}]
    +persistentManager.serializeError=Erreur lors de la sérialisation de la session [{0}]
     persistentManager.storeClearError=Erreur en supprimant toutes les sessions du stockage
     persistentManager.storeKeysException=Incapacité de déterminer la liste des ID de session, pour les sessions dans le magasin de sessions.  Supposant le magasin vide.
     persistentManager.storeLoadError=Erreur en déplaçant les sessions à partir du stockage
    diff -Nru tomcat10-10.1.40/java/org/apache/catalina/session/LocalStrings_ja.properties tomcat10-10.1.52/java/org/apache/catalina/session/LocalStrings_ja.properties
    --- tomcat10-10.1.40/java/org/apache/catalina/session/LocalStrings_ja.properties	2025-04-01 18:12:59.000000000 +0000
    +++ tomcat10-10.1.52/java/org/apache/catalina/session/LocalStrings_ja.properties	2026-01-23 19:33:36.000000000 +0000
    @@ -19,8 +19,8 @@
     dataSourceStore.SQLException=SQLエラー [{0}]
     dataSourceStore.checkConnectionDBClosed=データベース接続がnullであるか、クローズされているのが見つかりました。再オープンしてください。
     dataSourceStore.checkConnectionDBReOpenFail=データベースの再オープンが失敗しました。データベースがダウンしているかもしれません。
    -dataSourceStore.checkConnectionSQLException=SQL例外が発生しました [{0}]
    -dataSourceStore.close=データベース接続 [{0}] をクローズ中の例外です
    +dataSourceStore.checkConnectionSQLException=SQL例外が発生しました
    +dataSourceStore.close=データベース接続 をクローズ中の例外です
     dataSourceStore.commitSQLException=クローズ前のデータベース接続のコミット中にSQL例外が発生しました
     dataSourceStore.loading=セッション [{0}] をデータベース [{1}] からロードします
     dataSourceStore.missingDataSource=利用可能なデータソースがありません
    @@ -54,7 +54,7 @@
     persistentManager.loading=[{0}] の永続化セッションをロードします
     persistentManager.noStore=ストアが構成されておらず、永続性が無効になっています
     persistentManager.removeError=ストアからセッション[{0}]削除中のエラー
    -persistentManager.serializeError=セッション [{0}] をシリアライズ中のエラーです: [{1}]
    +persistentManager.serializeError=セッション [{0}] をシリアライズ中のエラーです
     persistentManager.storeClearError=ストア上の全セッション消去中のエラー
     persistentManager.storeKeysException=セッションストアからセッションIDのリストを取得できませんでした。セッションストアが空の可能性があります
     persistentManager.storeLoadError=ストアからのセッションスワップイン中のエラー
    diff -Nru tomcat10-10.1.40/java/org/apache/catalina/session/LocalStrings_ko.properties tomcat10-10.1.52/java/org/apache/catalina/session/LocalStrings_ko.properties
    --- tomcat10-10.1.40/java/org/apache/catalina/session/LocalStrings_ko.properties	2025-04-01 18:12:59.000000000 +0000
    +++ tomcat10-10.1.52/java/org/apache/catalina/session/LocalStrings_ko.properties	2026-01-23 19:33:36.000000000 +0000
    @@ -19,8 +19,8 @@
     dataSourceStore.SQLException=SQL 오류 [{0}]
     dataSourceStore.checkConnectionDBClosed=데이터베이스 연결이 널이거나 닫힌 상태입니다. 다시 열려고 시도합니다.
     dataSourceStore.checkConnectionDBReOpenFail=데이터베이스에 대해 다시 연결을 맺지 못했습니다. 데이터베이스가 다운되었을 수 있습니다.
    -dataSourceStore.checkConnectionSQLException=SQL 예외 발생 [{0}]
    -dataSourceStore.close=데이터베이스 연결 [{0}]을(를) 닫는 동안 예외 발생
    +dataSourceStore.checkConnectionSQLException=SQL 예외 발생
    +dataSourceStore.close=데이터베이스 연결을(를) 닫는 동안 예외 발생
     dataSourceStore.commitSQLException=데이터베이스 연결을 닫기 전, 커밋을 시도하는 중 SQLException 발생
     dataSourceStore.loading=데이터베이스 [{1}](으)로부터 세션 [{0}]을(를) 로드합니다.
     dataSourceStore.missingDataSource=DataSource를 사용할 수 없습니다.
    @@ -51,7 +51,7 @@
     persistentManager.isLoadedError=세션 [{0}]이(가) 메모리에 로드되었는지 점검 중 오류 발생
     persistentManager.loading=[{0}]개의 저장된 세션들을 로드합니다.
     persistentManager.removeError=세션 [{0}]을(를) 저장소로부터 제거하는 중 오류 발생
    -persistentManager.serializeError=세션을 직렬화하는 중 오류 발생 [{0}]: [{1}]
    +persistentManager.serializeError=세션을 직렬화하는 중 오류 발생 [{0}]
     persistentManager.storeClearError=저장소로부터 모든 세션들을 해제하는 중 오류 발생
     persistentManager.storeKeysException=세션 저장소에 있는 세션들의 ID 목록을 결정할 수 없습니다. 아마도 세션 저장소가 비어 있는 것 같습니다.
     persistentManager.storeLoadError=저장소로부터 세션들을 메모리로 로드하는 중 오류 발생
    diff -Nru tomcat10-10.1.40/java/org/apache/catalina/session/LocalStrings_zh_CN.properties tomcat10-10.1.52/java/org/apache/catalina/session/LocalStrings_zh_CN.properties
    --- tomcat10-10.1.40/java/org/apache/catalina/session/LocalStrings_zh_CN.properties	2025-04-01 18:12:59.000000000 +0000
    +++ tomcat10-10.1.52/java/org/apache/catalina/session/LocalStrings_zh_CN.properties	2026-01-23 19:33:36.000000000 +0000
    @@ -19,8 +19,8 @@
     dataSourceStore.SQLException=SQL错误[{0}]
     dataSourceStore.checkConnectionDBClosed=数据库连接为空或已关闭。正在尝试重新连接。
     dataSourceStore.checkConnectionDBReOpenFail=重新打开数据库失败,数据库可能已经宕机。
    -dataSourceStore.checkConnectionSQLException=发生 SQL 异常 [{0}]
    -dataSourceStore.close=关闭数据库连接[{0}]时发生异常
    +dataSourceStore.checkConnectionSQLException=发生 SQL 异常
    +dataSourceStore.close=关闭数据库连接时发生异常
     dataSourceStore.commitSQLException=关闭前提交连接的SQLException
     dataSourceStore.loading=正在从数据库[{1}]加载会话[{0}]
     dataSourceStore.missingDataSource=没有可用的数据源
    @@ -51,7 +51,7 @@
     persistentManager.isLoadedError=检查内存中是否加载了会话[{0}]时出错
     persistentManager.loading=正在加载[{0}]持久化会话
     persistentManager.removeError=从存储中删除会话[{0}]时出错
    -persistentManager.serializeError=错误的序列化会话 [{0}]:[{1}]
    +persistentManager.serializeError=错误的序列化会话 [{0}]
     persistentManager.storeClearError=清除存储区中的所有会话时出错
     persistentManager.storeKeysException=不能从 session存储中获取session ID 的列表,假设存储为空
     persistentManager.storeLoadError=从存储区交换会话时出错
    diff -Nru tomcat10-10.1.40/java/org/apache/catalina/session/ManagerBase.java tomcat10-10.1.52/java/org/apache/catalina/session/ManagerBase.java
    --- tomcat10-10.1.40/java/org/apache/catalina/session/ManagerBase.java	2025-04-01 18:12:59.000000000 +0000
    +++ tomcat10-10.1.52/java/org/apache/catalina/session/ManagerBase.java	2026-01-23 19:33:36.000000000 +0000
    @@ -55,8 +55,6 @@
     /**
      * Minimal implementation of the Manager interface that supports no session persistence or distributable
      * capabilities. This class may be subclassed to create more sophisticated Manager implementations.
    - *
    - * @author Craig R. McClanahan
      */
     public abstract class ManagerBase extends LifecycleMBeanBase implements Manager {
     
    diff -Nru tomcat10-10.1.40/java/org/apache/catalina/session/PersistentManager.java tomcat10-10.1.52/java/org/apache/catalina/session/PersistentManager.java
    --- tomcat10-10.1.40/java/org/apache/catalina/session/PersistentManager.java	2025-04-01 18:12:59.000000000 +0000
    +++ tomcat10-10.1.52/java/org/apache/catalina/session/PersistentManager.java	2026-01-23 19:33:36.000000000 +0000
    @@ -26,8 +26,6 @@
      * 
      * If used with a load-balancer, the load-balancer must be configured to use sticky sessions for this manager to operate
      * correctly.
    - *
    - * @author Kief Morris (kief@kief.com)
      */
     public final class PersistentManager extends PersistentManagerBase {
     
    diff -Nru tomcat10-10.1.40/java/org/apache/catalina/session/PersistentManagerBase.java tomcat10-10.1.52/java/org/apache/catalina/session/PersistentManagerBase.java
    --- tomcat10-10.1.40/java/org/apache/catalina/session/PersistentManagerBase.java	2025-04-01 18:12:59.000000000 +0000
    +++ tomcat10-10.1.52/java/org/apache/catalina/session/PersistentManagerBase.java	2026-01-23 19:33:36.000000000 +0000
    @@ -42,8 +42,6 @@
      * 

    * IMPLEMENTATION NOTE: Correct behavior of session storing and reloading depends upon external calls to the * {@link Lifecycle#start()} and {@link Lifecycle#stop()} methods of this class at the correct times. - * - * @author Craig R. McClanahan */ public abstract class PersistentManagerBase extends ManagerBase implements StoreManager { @@ -291,8 +289,8 @@ if (super.findSession(id) != null) { return true; } - } catch (IOException e) { - log.error(sm.getString("persistentManager.isLoadedError", id), e); + } catch (IOException ioe) { + log.error(sm.getString("persistentManager.isLoadedError", id), ioe); } return false; } @@ -377,8 +375,8 @@ } else { store.clear(); } - } catch (IOException e) { - log.error(sm.getString("persistentManager.storeClearError"), e); + } catch (IOException ioe) { + log.error(sm.getString("persistentManager.storeClearError"), ioe); } } @@ -502,8 +500,8 @@ } else { ids = store.keys(); } - } catch (IOException e) { - log.error(sm.getString("persistentManager.storeLoadKeysError"), e); + } catch (IOException ioe) { + log.error(sm.getString("persistentManager.storeLoadKeysError"), ioe); return; } @@ -519,8 +517,8 @@ for (String id : ids) { try { swapIn(id); - } catch (IOException e) { - log.error(sm.getString("persistentManager.storeLoadError"), e); + } catch (IOException ioe) { + log.error(sm.getString("persistentManager.storeLoadError"), ioe); } } @@ -559,8 +557,8 @@ } else { store.remove(id); } - } catch (IOException e) { - log.error(sm.getString("persistentManager.removeError"), e); + } catch (IOException ioe) { + log.error(sm.getString("persistentManager.removeError"), ioe); } } @@ -591,7 +589,7 @@ for (Session session : sessions) { try { swapOut(session); - } catch (IOException e) { + } catch (IOException ignore) { // This is logged in writeSession() } } @@ -607,7 +605,7 @@ // Store session count result += getStore().getSize(); } catch (IOException ioe) { - log.warn(sm.getString("persistentManager.storeSizeException")); + log.warn(sm.getString("persistentManager.storeSizeException"), ioe); } return result; } @@ -620,8 +618,8 @@ try { // Store session ID list sessionIds.addAll(Arrays.asList(getStore().keys())); - } catch (IOException e) { - log.warn(sm.getString("persistentManager.storeKeysException")); + } catch (IOException ioe) { + log.warn(sm.getString("persistentManager.storeKeysException"), ioe); } return sessionIds; } @@ -796,9 +794,9 @@ } else { store.save(session); } - } catch (IOException e) { - log.error(sm.getString("persistentManager.serializeError", session.getIdInternal(), e)); - throw e; + } catch (IOException ioe) { + log.error(sm.getString("persistentManager.serializeError", session.getIdInternal()), ioe); + throw ioe; } } @@ -899,7 +897,7 @@ } try { swapOut(session); - } catch (IOException e) { + } catch (IOException ignore) { // This is logged in writeSession() } } @@ -949,7 +947,7 @@ } try { swapOut(session); - } catch (IOException e) { + } catch (IOException ignore) { // This is logged in writeSession() } toswap--; @@ -994,7 +992,7 @@ try { writeSession(session); - } catch (IOException e) { + } catch (IOException ignore) { // This is logged in writeSession() } session.setNote(PERSISTED_LAST_ACCESSED_TIME, Long.valueOf(lastAccessedTime)); diff -Nru tomcat10-10.1.40/java/org/apache/catalina/session/StandardManager.java tomcat10-10.1.52/java/org/apache/catalina/session/StandardManager.java --- tomcat10-10.1.40/java/org/apache/catalina/session/StandardManager.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/session/StandardManager.java 2026-01-23 19:33:36.000000000 +0000 @@ -51,8 +51,6 @@ *

    * IMPLEMENTATION NOTE: Correct behavior of session storing and reloading depends upon external calls to the * start() and stop() methods of this class at the correct times. - * - * @author Craig R. McClanahan */ public class StandardManager extends ManagerBase { @@ -229,7 +227,7 @@ } } catch (FileNotFoundException e) { if (log.isDebugEnabled()) { - log.debug(sm.getString("standardManager.noFile", file.getAbsolutePath())); + log.debug(sm.getString("standardManager.noFile", file.getAbsolutePath()), e); } return; } diff -Nru tomcat10-10.1.40/java/org/apache/catalina/session/StandardSession.java tomcat10-10.1.52/java/org/apache/catalina/session/StandardSession.java --- tomcat10-10.1.40/java/org/apache/catalina/session/StandardSession.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/session/StandardSession.java 2026-01-23 19:33:36.000000000 +0000 @@ -67,10 +67,6 @@ *

    * IMPLEMENTATION NOTE: If you add fields to this class, you must make sure that you carry them over in the * read/writeObject methods so that this class is properly serialized. - * - * @author Craig R. McClanahan - * @author Sean Legassick - * @author Jon S. Stevens */ public class StandardSession implements HttpSession, Session, Serializable { @@ -342,6 +338,9 @@ @Override public void tellChangedSessionId(String newId, String oldId, boolean notifySessionListeners, boolean notifyContainerListeners) { + // Notify interested session event listeners + fireSessionEvent(SESSION_CHANGED_ID_EVENT, oldId); + Context context = manager.getContext(); // notify ContainerListeners if (notifyContainerListeners) { diff -Nru tomcat10-10.1.40/java/org/apache/catalina/session/StandardSessionFacade.java tomcat10-10.1.52/java/org/apache/catalina/session/StandardSessionFacade.java --- tomcat10-10.1.40/java/org/apache/catalina/session/StandardSessionFacade.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/session/StandardSessionFacade.java 2026-01-23 19:33:36.000000000 +0000 @@ -23,8 +23,6 @@ /** * Facade for the StandardSession object. - * - * @author Remy Maucherat */ public class StandardSessionFacade implements HttpSession { diff -Nru tomcat10-10.1.40/java/org/apache/catalina/session/StoreBase.java tomcat10-10.1.52/java/org/apache/catalina/session/StoreBase.java --- tomcat10-10.1.40/java/org/apache/catalina/session/StoreBase.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/session/StoreBase.java 2026-01-23 19:33:36.000000000 +0000 @@ -35,8 +35,6 @@ /** * Abstract implementation of the {@link Store} interface to support most of the functionality required by a * {@link Store}. - * - * @author Bip Thelin */ public abstract class StoreBase extends LifecycleBase implements Store { @@ -122,8 +120,8 @@ try { keys = expiredKeys(); - } catch (IOException e) { - manager.getContext().getLogger().error(sm.getString("store.keysFail"), e); + } catch (IOException ioe) { + manager.getContext().getLogger().error(sm.getString("store.keysFail"), ioe); return; } if (manager.getContext().getLogger().isTraceEnabled()) { @@ -171,8 +169,8 @@ manager.getContext().getLogger().error(sm.getString("store.expireFail", key), e); try { remove(key); - } catch (IOException e2) { - manager.getContext().getLogger().error(sm.getString("store.removeFail", key), e2); + } catch (IOException ioe) { + manager.getContext().getLogger().error(sm.getString("store.removeFail", key), ioe); } } } diff -Nru tomcat10-10.1.40/java/org/apache/catalina/ssi/ByteArrayServletOutputStream.java tomcat10-10.1.52/java/org/apache/catalina/ssi/ByteArrayServletOutputStream.java --- tomcat10-10.1.40/java/org/apache/catalina/ssi/ByteArrayServletOutputStream.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/ssi/ByteArrayServletOutputStream.java 2026-01-23 19:33:36.000000000 +0000 @@ -25,8 +25,6 @@ /** * Class that extends ServletOutputStream, used as a wrapper from within SsiInclude * - * @author Bip Thelin - * * @see ServletOutputStream and ByteArrayOutputStream */ public class ByteArrayServletOutputStream extends ServletOutputStream { diff -Nru tomcat10-10.1.40/java/org/apache/catalina/ssi/ExpressionParseTree.java tomcat10-10.1.52/java/org/apache/catalina/ssi/ExpressionParseTree.java --- tomcat10-10.1.40/java/org/apache/catalina/ssi/ExpressionParseTree.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/ssi/ExpressionParseTree.java 2026-01-23 19:33:36.000000000 +0000 @@ -29,8 +29,6 @@ /** * Represents a parsed expression. - * - * @author Paul Speed */ public class ExpressionParseTree { private static final StringManager sm = StringManager.getManager(ExpressionParseTree.class); diff -Nru tomcat10-10.1.40/java/org/apache/catalina/ssi/ExpressionTokenizer.java tomcat10-10.1.52/java/org/apache/catalina/ssi/ExpressionTokenizer.java --- tomcat10-10.1.40/java/org/apache/catalina/ssi/ExpressionTokenizer.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/ssi/ExpressionTokenizer.java 2026-01-23 19:33:36.000000000 +0000 @@ -20,8 +20,6 @@ /** * Parses an expression string to return the individual tokens. This is patterned similar to the StreamTokenizer in the * JDK but customized for SSI conditional expression parsing. - * - * @author Paul Speed */ public class ExpressionTokenizer { public static final int TOKEN_STRING = 0; diff -Nru tomcat10-10.1.40/java/org/apache/catalina/ssi/ResponseIncludeWrapper.java tomcat10-10.1.52/java/org/apache/catalina/ssi/ResponseIncludeWrapper.java --- tomcat10-10.1.40/java/org/apache/catalina/ssi/ResponseIncludeWrapper.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/ssi/ResponseIncludeWrapper.java 2026-01-23 19:33:36.000000000 +0000 @@ -28,10 +28,7 @@ import org.apache.tomcat.util.http.FastHttpDateFormat; /** - * An HttpServletResponseWrapper, used from SSIServletExternalResolver - * - * @author Bip Thelin - * @author David Becker + * An HttpServletResponseWrapper, used from SSIServletExternalResolver. */ public class ResponseIncludeWrapper extends HttpServletResponseWrapper { /** diff -Nru tomcat10-10.1.40/java/org/apache/catalina/ssi/SSICommand.java tomcat10-10.1.52/java/org/apache/catalina/ssi/SSICommand.java --- tomcat10-10.1.40/java/org/apache/catalina/ssi/SSICommand.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/ssi/SSICommand.java 2026-01-23 19:33:36.000000000 +0000 @@ -16,15 +16,10 @@ */ package org.apache.catalina.ssi; - import java.io.PrintWriter; /** * The interface that all SSI commands ( SSIEcho, SSIInclude, ...) must implement. - * - * @author Bip Thelin - * @author Dan Sandberg - * @author David Becker */ public interface SSICommand { /** diff -Nru tomcat10-10.1.40/java/org/apache/catalina/ssi/SSIConditional.java tomcat10-10.1.52/java/org/apache/catalina/ssi/SSIConditional.java --- tomcat10-10.1.40/java/org/apache/catalina/ssi/SSIConditional.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/ssi/SSIConditional.java 2026-01-23 19:33:36.000000000 +0000 @@ -22,9 +22,6 @@ /** * SSI command that handles all conditional directives. - * - * @author Paul Speed - * @author David Becker */ public class SSIConditional implements SSICommand { @Override diff -Nru tomcat10-10.1.40/java/org/apache/catalina/ssi/SSIConditionalState.java tomcat10-10.1.52/java/org/apache/catalina/ssi/SSIConditionalState.java --- tomcat10-10.1.40/java/org/apache/catalina/ssi/SSIConditionalState.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/ssi/SSIConditionalState.java 2026-01-23 19:33:36.000000000 +0000 @@ -16,13 +16,9 @@ */ package org.apache.catalina.ssi; - /** * This class is used by SSIMediator and SSIConditional to keep track of state information necessary to process the * nested conditional commands ( if, elif, else, endif ). - * - * @author Dan Sandberg - * @author Paul Speed */ public class SSIConditionalState { /** diff -Nru tomcat10-10.1.40/java/org/apache/catalina/ssi/SSIConfig.java tomcat10-10.1.52/java/org/apache/catalina/ssi/SSIConfig.java --- tomcat10-10.1.40/java/org/apache/catalina/ssi/SSIConfig.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/ssi/SSIConfig.java 2026-01-23 19:33:36.000000000 +0000 @@ -16,18 +16,12 @@ */ package org.apache.catalina.ssi; - import java.io.PrintWriter; import org.apache.tomcat.util.res.StringManager; /** - * Implements the Server-side #exec command - * - * @author Bip Thelin - * @author Paul Speed - * @author Dan Sandberg - * @author David Becker + * Implements the Server-side #exec command. */ public final class SSIConfig implements SSICommand { private static final StringManager sm = StringManager.getManager(SSIConfig.class); diff -Nru tomcat10-10.1.40/java/org/apache/catalina/ssi/SSIEcho.java tomcat10-10.1.52/java/org/apache/catalina/ssi/SSIEcho.java --- tomcat10-10.1.40/java/org/apache/catalina/ssi/SSIEcho.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/ssi/SSIEcho.java 2026-01-23 19:33:36.000000000 +0000 @@ -23,11 +23,6 @@ /** * Return the result associated with the supplied Server Variable. - * - * @author Bip Thelin - * @author Paul Speed - * @author Dan Sandberg - * @author David Becker */ public class SSIEcho implements SSICommand { private static final StringManager sm = StringManager.getManager(SSIEcho.class); diff -Nru tomcat10-10.1.40/java/org/apache/catalina/ssi/SSIExec.java tomcat10-10.1.52/java/org/apache/catalina/ssi/SSIExec.java --- tomcat10-10.1.40/java/org/apache/catalina/ssi/SSIExec.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/ssi/SSIExec.java 2026-01-23 19:33:36.000000000 +0000 @@ -26,13 +26,7 @@ import org.apache.tomcat.util.res.StringManager; /** - * Implements the Server-side #exec command - * - * @author Bip Thelin - * @author Amy Roh - * @author Paul Speed - * @author Dan Sandberg - * @author David Becker + * Implements the Server-side #exec command. */ public class SSIExec implements SSICommand { private static final StringManager sm = StringManager.getManager(SSIExec.class); @@ -74,12 +68,12 @@ } catch (InterruptedException e) { ssiMediator.log(sm.getString("ssiExec.executeFailed", substitutedValue), e); writer.write(configErrMsg); - } catch (IOException e) { + } catch (IOException ioe) { if (!foundProgram) { // Apache doesn't output an error message if it can't find // a program } - ssiMediator.log(sm.getString("ssiExec.executeFailed", substitutedValue), e); + ssiMediator.log(sm.getString("ssiExec.executeFailed", substitutedValue), ioe); } } return lastModified; diff -Nru tomcat10-10.1.40/java/org/apache/catalina/ssi/SSIExternalResolver.java tomcat10-10.1.52/java/org/apache/catalina/ssi/SSIExternalResolver.java --- tomcat10-10.1.40/java/org/apache/catalina/ssi/SSIExternalResolver.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/ssi/SSIExternalResolver.java 2026-01-23 19:33:36.000000000 +0000 @@ -22,9 +22,7 @@ import java.util.Date; /** - * Interface used by SSIMediator to talk to the 'outside world' ( usually a servlet ) - * - * @author Dan Sandberg + * Interface used by SSIMediator to talk to the 'outside world' ( usually a servlet ). */ public interface SSIExternalResolver { /** diff -Nru tomcat10-10.1.40/java/org/apache/catalina/ssi/SSIFilter.java tomcat10-10.1.52/java/org/apache/catalina/ssi/SSIFilter.java --- tomcat10-10.1.40/java/org/apache/catalina/ssi/SSIFilter.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/ssi/SSIFilter.java 2026-01-23 19:33:36.000000000 +0000 @@ -39,8 +39,6 @@ /** * Filter to process SSI requests within a webpage. Mapped to a content types from within web.xml. * - * @author David Becker - * * @see org.apache.catalina.ssi.SSIServlet */ public class SSIFilter extends GenericFilter { diff -Nru tomcat10-10.1.40/java/org/apache/catalina/ssi/SSIFlastmod.java tomcat10-10.1.52/java/org/apache/catalina/ssi/SSIFlastmod.java --- tomcat10-10.1.40/java/org/apache/catalina/ssi/SSIFlastmod.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/ssi/SSIFlastmod.java 2026-01-23 19:33:36.000000000 +0000 @@ -25,12 +25,7 @@ import org.apache.tomcat.util.res.StringManager; /** - * Implements the Server-side #flastmod command - * - * @author Bip Thelin - * @author Paul Speed - * @author Dan Sandberg - * @author David Becker + * Implements the Server-side #flastmod command. */ public final class SSIFlastmod implements SSICommand { private static final StringManager sm = StringManager.getManager(SSIFlastmod.class); @@ -55,8 +50,8 @@ ssiMediator.log(sm.getString("ssiCommand.invalidAttribute", paramName)); writer.write(configErrMsg); } - } catch (IOException e) { - ssiMediator.log(sm.getString("ssiFlastmod.noLastModified", substitutedValue), e); + } catch (IOException ioe) { + ssiMediator.log(sm.getString("ssiFlastmod.noLastModified", substitutedValue), ioe); writer.write(configErrMsg); } } diff -Nru tomcat10-10.1.40/java/org/apache/catalina/ssi/SSIFsize.java tomcat10-10.1.52/java/org/apache/catalina/ssi/SSIFsize.java --- tomcat10-10.1.40/java/org/apache/catalina/ssi/SSIFsize.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/ssi/SSIFsize.java 2026-01-23 19:33:36.000000000 +0000 @@ -24,12 +24,7 @@ import org.apache.tomcat.util.res.StringManager; /** - * Implements the Server-side #fsize command - * - * @author Bip Thelin - * @author Paul Speed - * @author Dan Sandberg - * @author David Becker + * Implements the Server-side #fsize command. */ public final class SSIFsize implements SSICommand { private static final StringManager sm = StringManager.getManager(SSIFsize.class); @@ -57,8 +52,8 @@ ssiMediator.log(sm.getString("ssiCommand.invalidAttribute", paramName)); writer.write(configErrMsg); } - } catch (IOException e) { - ssiMediator.log(sm.getString("ssiFsize.noSize", substitutedValue), e); + } catch (IOException ioe) { + ssiMediator.log(sm.getString("ssiFsize.noSize", substitutedValue), ioe); writer.write(configErrMsg); } } diff -Nru tomcat10-10.1.40/java/org/apache/catalina/ssi/SSIInclude.java tomcat10-10.1.52/java/org/apache/catalina/ssi/SSIInclude.java --- tomcat10-10.1.40/java/org/apache/catalina/ssi/SSIInclude.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/ssi/SSIInclude.java 2026-01-23 19:33:36.000000000 +0000 @@ -23,12 +23,7 @@ import org.apache.tomcat.util.res.StringManager; /** - * Implements the Server-side #include command - * - * @author Bip Thelin - * @author Paul Speed - * @author Dan Sandberg - * @author David Becker + * Implements the Server-side #include command. */ public final class SSIInclude implements SSICommand { private static final StringManager sm = StringManager.getManager(SSIInclude.class); @@ -52,8 +47,8 @@ ssiMediator.log(sm.getString("ssiCommand.invalidAttribute", paramName)); writer.write(configErrMsg); } - } catch (IOException e) { - ssiMediator.log(sm.getString("ssiInclude.includeFailed", substitutedValue), e); + } catch (IOException ioe) { + ssiMediator.log(sm.getString("ssiInclude.includeFailed", substitutedValue), ioe); writer.write(configErrMsg); } } diff -Nru tomcat10-10.1.40/java/org/apache/catalina/ssi/SSIMediator.java tomcat10-10.1.52/java/org/apache/catalina/ssi/SSIMediator.java --- tomcat10-10.1.40/java/org/apache/catalina/ssi/SSIMediator.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/ssi/SSIMediator.java 2026-01-23 19:33:36.000000000 +0000 @@ -32,13 +32,7 @@ import org.apache.tomcat.util.security.Escape; /** - * Allows the different SSICommand implementations to share data/talk to each other - * - * @author Bip Thelin - * @author Amy Roh - * @author Paul Speed - * @author Dan Sandberg - * @author David Becker + * Allows the different SSICommand implementations to share data/talk to each other. */ public class SSIMediator { private static final StringManager sm = StringManager.getManager(SSIMediator.class); diff -Nru tomcat10-10.1.40/java/org/apache/catalina/ssi/SSIPrintenv.java tomcat10-10.1.52/java/org/apache/catalina/ssi/SSIPrintenv.java --- tomcat10-10.1.40/java/org/apache/catalina/ssi/SSIPrintenv.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/ssi/SSIPrintenv.java 2026-01-23 19:33:36.000000000 +0000 @@ -21,10 +21,7 @@ import java.util.Collection; /** - * Implements the Server-side #printenv command - * - * @author Dan Sandberg - * @author David Becker + * Implements the Server-side #printenv command. */ public class SSIPrintenv implements SSICommand { @Override diff -Nru tomcat10-10.1.40/java/org/apache/catalina/ssi/SSIProcessor.java tomcat10-10.1.52/java/org/apache/catalina/ssi/SSIProcessor.java --- tomcat10-10.1.40/java/org/apache/catalina/ssi/SSIProcessor.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/ssi/SSIProcessor.java 2026-01-23 19:33:36.000000000 +0000 @@ -30,9 +30,6 @@ /** * The entry point to SSI processing. This class does the actual parsing, delegating to the SSIMediator, SSICommand, and * SSIExternalResolver as necessary. - * - * @author Dan Sandberg - * @author David Becker */ public class SSIProcessor { /** The start pattern */ diff -Nru tomcat10-10.1.40/java/org/apache/catalina/ssi/SSIServlet.java tomcat10-10.1.52/java/org/apache/catalina/ssi/SSIServlet.java --- tomcat10-10.1.40/java/org/apache/catalina/ssi/SSIServlet.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/ssi/SSIServlet.java 2026-01-23 19:33:36.000000000 +0000 @@ -35,11 +35,6 @@ /** * Servlet to process SSI requests within a webpage. Mapped to a path from within web.xml. - * - * @author Bip Thelin - * @author Amy Roh - * @author Dan Sandberg - * @author David Becker */ public class SSIServlet extends HttpServlet { private static final long serialVersionUID = 1L; diff -Nru tomcat10-10.1.40/java/org/apache/catalina/ssi/SSIServletExternalResolver.java tomcat10-10.1.52/java/org/apache/catalina/ssi/SSIServletExternalResolver.java --- tomcat10-10.1.40/java/org/apache/catalina/ssi/SSIServletExternalResolver.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/ssi/SSIServletExternalResolver.java 2026-01-23 19:33:36.000000000 +0000 @@ -39,14 +39,12 @@ import org.apache.catalina.connector.Request; import org.apache.tomcat.util.buf.B2CConverter; import org.apache.tomcat.util.buf.UDecoder; +import org.apache.tomcat.util.http.Method; import org.apache.tomcat.util.http.RequestUtil; import org.apache.tomcat.util.res.StringManager; /** * An implementation of SSIExternalResolver that is used with servlets. - * - * @author Dan Sandberg - * @author David Becker */ public class SSIServletExternalResolver implements SSIExternalResolver { private static final StringManager sm = StringManager.getManager(SSIServletExternalResolver.class); @@ -308,8 +306,8 @@ } else if (nameParts[1].equals("PROTOCOL")) { retVal = req.getProtocol(); } else if (nameParts[1].equals("SOFTWARE")) { - retVal = context.getServerInfo() + ' ' + System.getProperty("java.vm.name") + - '/' + System.getProperty("java.vm.version") + ' ' + System.getProperty("os.name"); + retVal = context.getServerInfo() + ' ' + System.getProperty("java.vm.name") + '/' + + System.getProperty("java.vm.version") + ' ' + System.getProperty("os.name"); } } else if (name.equalsIgnoreCase("UNIQUE_ID")) { retVal = req.getRequestedSessionId(); @@ -447,7 +445,7 @@ try { URLConnection urlConnection = getURLConnection(path, virtual); lastModified = urlConnection.getLastModified(); - } catch (IOException e) { + } catch (IOException ignore) { // Ignore this. It will always fail for non-file based includes } return lastModified; @@ -460,7 +458,7 @@ try { URLConnection urlConnection = getURLConnection(path, virtual); fileSize = urlConnection.getContentLengthLong(); - } catch (IOException e) { + } catch (IOException ignore) { // Ignore this. It will always fail for non-file based includes } return fileSize; @@ -500,7 +498,7 @@ * Make an assumption that an empty response is a failure. This is a problem if a truly empty file were * included, but not sure how else to tell. */ - if (retVal.isEmpty() && !req.getMethod().equalsIgnoreCase("HEAD")) { + if (retVal.isEmpty() && !Method.HEAD.equals(req.getMethod())) { throw new IOException(sm.getString("ssiServletExternalResolver.noFile", path)); } return retVal; diff -Nru tomcat10-10.1.40/java/org/apache/catalina/ssi/SSISet.java tomcat10-10.1.52/java/org/apache/catalina/ssi/SSISet.java --- tomcat10-10.1.40/java/org/apache/catalina/ssi/SSISet.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/ssi/SSISet.java 2026-01-23 19:33:36.000000000 +0000 @@ -22,11 +22,7 @@ import org.apache.tomcat.util.res.StringManager; /** - * Implements the Server-side #set command - * - * @author Paul Speed - * @author Dan Sandberg - * @author David Becker + * Implements the Server-side #set command. */ public class SSISet implements SSICommand { private static final StringManager sm = StringManager.getManager(SSISet.class); diff -Nru tomcat10-10.1.40/java/org/apache/catalina/ssi/SSIStopProcessingException.java tomcat10-10.1.52/java/org/apache/catalina/ssi/SSIStopProcessingException.java --- tomcat10-10.1.40/java/org/apache/catalina/ssi/SSIStopProcessingException.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/ssi/SSIStopProcessingException.java 2026-01-23 19:33:36.000000000 +0000 @@ -16,13 +16,9 @@ */ package org.apache.catalina.ssi; - /** * Exception used to tell SSIProcessor that it should stop processing SSI commands. This is used to mimic the Apache * behavior in #set with invalid attributes. - * - * @author Paul Speed - * @author Dan Sandberg */ public class SSIStopProcessingException extends Exception { diff -Nru tomcat10-10.1.40/java/org/apache/catalina/startup/Bootstrap.java tomcat10-10.1.52/java/org/apache/catalina/startup/Bootstrap.java --- tomcat10-10.1.40/java/org/apache/catalina/startup/Bootstrap.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/startup/Bootstrap.java 2026-01-23 19:33:36.000000000 +0000 @@ -41,9 +41,6 @@ * regular execution of the container. The purpose of this roundabout approach is to keep the Catalina internal classes * (and any other classes they depend on, such as an XML parser) out of the system class path and therefore not visible * to application level classes. - * - * @author Craig R. McClanahan - * @author Remy Maucherat */ public final class Bootstrap { diff -Nru tomcat10-10.1.40/java/org/apache/catalina/startup/Catalina.java tomcat10-10.1.52/java/org/apache/catalina/startup/Catalina.java --- tomcat10-10.1.40/java/org/apache/catalina/startup/Catalina.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/startup/Catalina.java 2026-01-23 19:33:36.000000000 +0000 @@ -66,9 +66,6 @@ *

  • start - Start an instance of Catalina.
  • *
  • stop - Stop the currently running instance of Catalina.
  • * - * - * @author Craig R. McClanahan - * @author Remy Maucherat */ public class Catalina { @@ -549,7 +546,7 @@ Digester.setGeneratedCodeLoader(loader); } catch (Exception e) { if (log.isDebugEnabled()) { - log.info(sm.getString("catalina.noLoader", loaderClassName), e); + log.debug(sm.getString("catalina.noLoader", loaderClassName), e); } else { log.info(sm.getString("catalina.noLoader", loaderClassName)); } @@ -667,8 +664,8 @@ String.valueOf(s.getPortOffset()))); log.error(sm.getString("catalina.stopError"), ce); System.exit(1); - } catch (IOException e) { - log.error(sm.getString("catalina.stopError"), e); + } catch (IOException ioe) { + log.error(sm.getString("catalina.stopError"), ioe); System.exit(1); } } else { @@ -925,9 +922,9 @@ File loaderLocation = new File(generatedCodeLocation, generatedCodePackage); try (FileWriter writer = new FileWriter(new File(loaderLocation, loaderClassName + ".java"))) { writer.write(code.toString()); - } catch (IOException e) { + } catch (IOException ioe) { // Should not happen - log.debug(sm.getString("catalina.loaderWriteFail"), e); + log.debug(sm.getString("catalina.loaderWriteFail"), ioe); } } diff -Nru tomcat10-10.1.40/java/org/apache/catalina/startup/CatalinaBaseConfigurationSource.java tomcat10-10.1.52/java/org/apache/catalina/startup/CatalinaBaseConfigurationSource.java --- tomcat10-10.1.40/java/org/apache/catalina/startup/CatalinaBaseConfigurationSource.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/startup/CatalinaBaseConfigurationSource.java 2026-01-23 19:33:36.000000000 +0000 @@ -47,7 +47,7 @@ @Override public Resource getServerXml() throws IOException { - IOException ioe = null; + IOException ioException = null; Resource result = null; try { if (serverXmlPath == null || serverXmlPath.equals(Catalina.SERVER_XML)) { @@ -55,8 +55,8 @@ } else { result = getResource(serverXmlPath); } - } catch (IOException e) { - ioe = e; + } catch (IOException ioe) { + ioException = ioe; } if (result == null) { // Compatibility with legacy server-embed.xml location @@ -71,8 +71,8 @@ } } - if (result == null && ioe != null) { - throw ioe; + if (result == null && ioException != null) { + throw ioException; } else { return result; } diff -Nru tomcat10-10.1.40/java/org/apache/catalina/startup/CatalinaProperties.java tomcat10-10.1.52/java/org/apache/catalina/startup/CatalinaProperties.java --- tomcat10-10.1.40/java/org/apache/catalina/startup/CatalinaProperties.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/startup/CatalinaProperties.java 2026-01-23 19:33:36.000000000 +0000 @@ -30,8 +30,6 @@ /** * Utility class to read the bootstrap Catalina configuration. - * - * @author Remy Maucherat */ public class CatalinaProperties { @@ -102,7 +100,7 @@ properties.load(is); } catch (Throwable t) { handleThrowable(t); - log.warn(t); + log.warn(t.getMessage(), t); } finally { try { is.close(); diff -Nru tomcat10-10.1.40/java/org/apache/catalina/startup/ClassLoaderFactory.java tomcat10-10.1.52/java/org/apache/catalina/startup/ClassLoaderFactory.java --- tomcat10-10.1.40/java/org/apache/catalina/startup/ClassLoaderFactory.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/startup/ClassLoaderFactory.java 2026-01-23 19:33:36.000000000 +0000 @@ -45,8 +45,6 @@ * directories will be added to the class loader's repositories.
  • *
  • ClassLoader instance that should become the parent of the new class loader.
  • * - * - * @author Craig R. McClanahan */ public final class ClassLoaderFactory { diff -Nru tomcat10-10.1.40/java/org/apache/catalina/startup/Constants.java tomcat10-10.1.52/java/org/apache/catalina/startup/Constants.java --- tomcat10-10.1.40/java/org/apache/catalina/startup/Constants.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/startup/Constants.java 2026-01-23 19:33:36.000000000 +0000 @@ -20,8 +20,6 @@ * String constants for the startup package.
    * Note that some values include a leading '/' and that some do not. This is intentional based on how the values are * used. - * - * @author Craig R. McClanahan */ public final class Constants { diff -Nru tomcat10-10.1.40/java/org/apache/catalina/startup/ContextConfig.java tomcat10-10.1.52/java/org/apache/catalina/startup/ContextConfig.java --- tomcat10-10.1.40/java/org/apache/catalina/startup/ContextConfig.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/startup/ContextConfig.java 2026-01-23 19:33:36.000000000 +0000 @@ -118,8 +118,6 @@ /** * Startup event listener for a Context that configures the properties of that Context, and the associated * defined servlets. - * - * @author Craig R. McClanahan */ public class ContextConfig implements LifecycleListener { @@ -604,8 +602,8 @@ } } catch (MalformedURLException e) { log.error(sm.getString("contextConfig.badUrl", defaultContextXml), e); - } catch (IOException e) { - // Not found + } catch (IOException ignore) { + // Ignore - Not found } } @@ -646,8 +644,8 @@ } } catch (MalformedURLException e) { log.error(sm.getString("contextConfig.badUrl", hostContextFile), e); - } catch (IOException e) { - // Not found + } catch (IOException ignore) { + // Ignore - Not found } } } @@ -678,7 +676,7 @@ generateClassFooter(digester); try (FileWriter writer = new FileWriter(contextXmlJavaSource)) { writer.write(digester.getGeneratedCode().toString()); - } catch (IOException e) { + } catch (IOException ignore) { // Ignore } digester.endGeneratingCode(); @@ -739,7 +737,8 @@ } } catch (SAXParseException e) { log.error(sm.getString("contextConfig.contextParse", context.getName()), e); - log.error(sm.getString("contextConfig.defaultPosition", "" + e.getLineNumber(), "" + e.getColumnNumber())); + log.error(sm.getString("contextConfig.defaultPosition", Integer.toString(e.getLineNumber()), + Integer.toString(e.getColumnNumber()))); ok = false; } catch (Exception e) { log.error(sm.getString("contextConfig.contextParse", context.getName()), e); @@ -749,8 +748,8 @@ if (stream != null) { stream.close(); } - } catch (IOException e) { - log.error(sm.getString("contextConfig.contextClose"), e); + } catch (IOException ioe) { + log.error(sm.getString("contextConfig.contextClose"), ioe); } } } @@ -946,8 +945,8 @@ try { fixDocBase(); - } catch (IOException e) { - log.error(sm.getString("contextConfig.fixDocBase", context.getName()), e); + } catch (IOException ioe) { + log.error(sm.getString("contextConfig.fixDocBase", context.getName()), ioe); } antiLocking(); @@ -1621,8 +1620,8 @@ if (uc != null) { try { uc.getInputStream().close(); - } catch (IOException e) { - ExceptionUtils.handleThrowable(e); + } catch (IOException ioe) { + ExceptionUtils.handleThrowable(ioe); globalTimeStamp = -1; } } @@ -1642,8 +1641,8 @@ if (uc != null) { try { uc.getInputStream().close(); - } catch (IOException e) { - ExceptionUtils.handleThrowable(e); + } catch (IOException ioe) { + ExceptionUtils.handleThrowable(ioe); hostTimeStamp = -1; } } @@ -1764,8 +1763,8 @@ try { WebappServiceLoader loader = new WebappServiceLoader<>(context); detectedScis = loader.load(ServletContainerInitializer.class); - } catch (IOException e) { - log.error(sm.getString("contextConfig.servletContainerInitializerFail", context.getName()), e); + } catch (IOException ioe) { + log.error(sm.getString("contextConfig.servletContainerInitializerFail", context.getName()), ioe); ok = false; return; } @@ -1778,7 +1777,7 @@ ht = sci.getClass().getAnnotation(HandlesTypes.class); } catch (Exception e) { if (log.isDebugEnabled()) { - log.info(sm.getString("contextConfig.sci.debug", sci.getClass().getName()), e); + log.debug(sm.getString("contextConfig.sci.debug", sci.getClass().getName()), e); } else { log.info(sm.getString("contextConfig.sci.info", sci.getClass().getName())); } @@ -1928,7 +1927,7 @@ if (source == null && stream != null) { try { stream.close(); - } catch (IOException e) { + } catch (IOException ignore) { // Ignore } } @@ -1979,7 +1978,7 @@ String hostWebXml = Container.getConfigPath(context, Constants.HostWebXml); webXmlResource = ConfigFileLoader.getSource().getResource(hostWebXml); } - } catch (IOException e) { + } catch (IOException ignore) { // Ignore if not found return null; } @@ -1999,7 +1998,7 @@ if (source == null && stream != null) { try { stream.close(); - } catch (IOException e) { + } catch (IOException ioe) { // Ignore } } @@ -2198,8 +2197,8 @@ jar.nextEntry(); entryName = jar.getEntryName(); } - } catch (IOException e) { - log.error(sm.getString("contextConfig.jarFile", url), e); + } catch (IOException ioe) { + log.error(sm.getString("contextConfig.jarFile", url), ioe); } } diff -Nru tomcat10-10.1.40/java/org/apache/catalina/startup/ContextRuleSet.java tomcat10-10.1.52/java/org/apache/catalina/startup/ContextRuleSet.java --- tomcat10-10.1.40/java/org/apache/catalina/startup/ContextRuleSet.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/startup/ContextRuleSet.java 2026-01-23 19:33:36.000000000 +0000 @@ -21,8 +21,6 @@ /** * RuleSet for processing the contents of a Context definition element. - * - * @author Craig R. McClanahan */ public class ContextRuleSet implements RuleSet { diff -Nru tomcat10-10.1.40/java/org/apache/catalina/startup/CopyParentClassLoaderRule.java tomcat10-10.1.52/java/org/apache/catalina/startup/CopyParentClassLoaderRule.java --- tomcat10-10.1.40/java/org/apache/catalina/startup/CopyParentClassLoaderRule.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/startup/CopyParentClassLoaderRule.java 2026-01-23 19:33:36.000000000 +0000 @@ -27,8 +27,6 @@ /** * Rule that copies the parentClassLoader property from the next-to-top item on the stack (which must be a * Container) to the top item on the stack (which must also be a Container). - * - * @author Craig R. McClanahan */ public class CopyParentClassLoaderRule extends Rule { diff -Nru tomcat10-10.1.40/java/org/apache/catalina/startup/EngineConfig.java tomcat10-10.1.52/java/org/apache/catalina/startup/EngineConfig.java --- tomcat10-10.1.40/java/org/apache/catalina/startup/EngineConfig.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/startup/EngineConfig.java 2026-01-23 19:33:36.000000000 +0000 @@ -29,8 +29,6 @@ /** * Startup event listener for an Engine that configures the properties of that Engine, and the associated defined * contexts. - * - * @author Craig R. McClanahan */ public class EngineConfig implements LifecycleListener { diff -Nru tomcat10-10.1.40/java/org/apache/catalina/startup/EngineRuleSet.java tomcat10-10.1.52/java/org/apache/catalina/startup/EngineRuleSet.java --- tomcat10-10.1.40/java/org/apache/catalina/startup/EngineRuleSet.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/startup/EngineRuleSet.java 2026-01-23 19:33:36.000000000 +0000 @@ -22,8 +22,6 @@ /** * RuleSet for processing the contents of an Engine definition element. This RuleSet does * NOT include any rules for nested Host elements, which should be added via instances of HostRuleSet. - * - * @author Craig R. McClanahan */ public class EngineRuleSet implements RuleSet { diff -Nru tomcat10-10.1.40/java/org/apache/catalina/startup/ExpandWar.java tomcat10-10.1.52/java/org/apache/catalina/startup/ExpandWar.java --- tomcat10-10.1.40/java/org/apache/catalina/startup/ExpandWar.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/startup/ExpandWar.java 2026-01-23 19:33:36.000000000 +0000 @@ -40,10 +40,6 @@ /** * Expand out a WAR in a Host's appBase. - * - * @author Craig R. McClanahan - * @author Remy Maucherat - * @author Glenn L. Nielsen */ public class ExpandWar { @@ -262,8 +258,8 @@ throw new EOFException(); } } - } catch (IOException e) { - log.error(sm.getString("expandWar.copy", fileSrc, fileDest), e); + } catch (IOException ioe) { + log.error(sm.getString("expandWar.copy", fileSrc, fileDest), ioe); result = false; } } @@ -273,8 +269,8 @@ /** - * Delete the specified directory, including all of its contents and subdirectories recursively. Any failure will - * be logged. + * Delete the specified directory, including all of its contents and subdirectories recursively. Any failure will be + * logged. * * @param dir File object representing the directory to be deleted * @@ -313,8 +309,8 @@ /** - * Delete the specified directory, including all of its contents and subdirectories recursively. Any failure will - * be logged. + * Delete the specified directory, including all of its contents and subdirectories recursively. Any failure will be + * logged. * * @param dir File object representing the directory to be deleted * diff -Nru tomcat10-10.1.40/java/org/apache/catalina/startup/FailedContext.java tomcat10-10.1.52/java/org/apache/catalina/startup/FailedContext.java --- tomcat10-10.1.40/java/org/apache/catalina/startup/FailedContext.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/startup/FailedContext.java 2026-01-23 19:33:36.000000000 +0000 @@ -1431,4 +1431,15 @@ public void setSuspendWrappedResponseAfterForward(boolean suspendWrappedResponseAfterForward) { } + public long getStartTime() { + return -1; + } + + public long getStartupTime() { + return -1; + } + + public long getTldScanTime() { + return -1; + } } \ No newline at end of file diff -Nru tomcat10-10.1.40/java/org/apache/catalina/startup/HomesUserDatabase.java tomcat10-10.1.52/java/org/apache/catalina/startup/HomesUserDatabase.java --- tomcat10-10.1.40/java/org/apache/catalina/startup/HomesUserDatabase.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/startup/HomesUserDatabase.java 2026-01-23 19:33:36.000000000 +0000 @@ -25,8 +25,6 @@ /** * Concrete implementation of the UserDatabase interface considers all directories in a directory whose * pathname is specified to our constructor to be "home" directories for those users. - * - * @author Craig R. McClanahan */ public final class HomesUserDatabase implements UserDatabase { diff -Nru tomcat10-10.1.40/java/org/apache/catalina/startup/HostConfig.java tomcat10-10.1.52/java/org/apache/catalina/startup/HostConfig.java --- tomcat10-10.1.40/java/org/apache/catalina/startup/HostConfig.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/startup/HostConfig.java 2026-01-23 19:33:36.000000000 +0000 @@ -77,9 +77,6 @@ /** * Startup event listener for a Host that configures the properties of that Host, and the associated defined * contexts. - * - * @author Craig R. McClanahan - * @author Remy Maucherat */ public class HostConfig implements LifecycleListener { @@ -389,7 +386,7 @@ } try { return file.getCanonicalFile(); - } catch (IOException e) { + } catch (IOException ioe) { return file; } } @@ -840,14 +837,15 @@ if (entry != null) { xmlInWar = true; } - } catch (IOException e) { - /* Ignore */ + } catch (IOException ignore) { + // Ignore } // If there is an expanded directory then any xml in that directory // should only be used if the directory is not out of date and // unpackWARs is true. Note the code below may apply further limits - boolean useXml = xml.exists() && unpackWARs && (!warTracker.exists() || warTracker.lastModified() == war.lastModified()); + boolean useXml = + xml.exists() && unpackWARs && (!warTracker.exists() || warTracker.lastModified() == war.lastModified()); // If the xml file exists then expandedDir must exist so no need to // test that here @@ -924,8 +922,8 @@ OutputStream ostream = new FileOutputStream(xml)) { IOTools.flow(istream, ostream); } - } catch (IOException e) { - /* Ignore */ + } catch (IOException ignore) { + // Ignore } } } @@ -1549,16 +1547,16 @@ String canonicalLocation; try { canonicalLocation = resource.getParentFile().getCanonicalPath(); - } catch (IOException e) { - log.warn(sm.getString("hostConfig.canonicalizing", resource.getParentFile(), app.name), e); + } catch (IOException ioe) { + log.warn(sm.getString("hostConfig.canonicalizing", resource.getParentFile(), app.name), ioe); return false; } String canonicalAppBase; try { canonicalAppBase = host.getAppBaseFile().getCanonicalPath(); - } catch (IOException e) { - log.warn(sm.getString("hostConfig.canonicalizing", host.getAppBaseFile(), app.name), e); + } catch (IOException ioe) { + log.warn(sm.getString("hostConfig.canonicalizing", host.getAppBaseFile(), app.name), ioe); return false; } @@ -1570,8 +1568,8 @@ String canonicalConfigBase; try { canonicalConfigBase = host.getConfigBaseFile().getCanonicalPath(); - } catch (IOException e) { - log.warn(sm.getString("hostConfig.canonicalizing", host.getConfigBaseFile(), app.name), e); + } catch (IOException ioe) { + log.warn(sm.getString("hostConfig.canonicalizing", host.getConfigBaseFile(), app.name), ioe); return false; } @@ -1955,14 +1953,14 @@ /* - * The purpose of this class is to provide a way for HostConfig to get a Context to delete an expanded WAR after the - * Context stops. This is to resolve this issue described in Bug 57772. The alternative solutions require either - * duplicating a lot of the Context.reload() code in HostConfig or adding a new reload(boolean) method to Context - * that allows the caller to optionally delete any expanded WAR. - * - * The LifecycleListener approach offers greater flexibility and enables the behaviour to be changed / extended / - * removed in future without changing the Context API. - */ + * The purpose of this class is to provide a way for HostConfig to get a Context to delete an expanded WAR after the + * Context stops. This is to resolve this issue described in Bug 57772. The alternative solutions require either + * duplicating a lot of the Context.reload() code in HostConfig or adding a new reload(boolean) method to Context + * that allows the caller to optionally delete any expanded WAR. + * + * The LifecycleListener approach offers greater flexibility and enables the behaviour to be changed / extended / + * removed in future without changing the Context API. + */ private static class ExpandedDirectoryRemovalListener implements LifecycleListener { private final File toDelete; diff -Nru tomcat10-10.1.40/java/org/apache/catalina/startup/HostRuleSet.java tomcat10-10.1.52/java/org/apache/catalina/startup/HostRuleSet.java --- tomcat10-10.1.40/java/org/apache/catalina/startup/HostRuleSet.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/startup/HostRuleSet.java 2026-01-23 19:33:36.000000000 +0000 @@ -22,8 +22,6 @@ /** * RuleSet for processing the contents of a Host definition element. This RuleSet does NOT * include any rules for nested Context which should be added via instances of ContextRuleSet. - * - * @author Craig R. McClanahan */ public class HostRuleSet implements RuleSet { diff -Nru tomcat10-10.1.40/java/org/apache/catalina/startup/ListenerCreateRule.java tomcat10-10.1.52/java/org/apache/catalina/startup/ListenerCreateRule.java --- tomcat10-10.1.40/java/org/apache/catalina/startup/ListenerCreateRule.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/startup/ListenerCreateRule.java 2026-01-23 19:33:36.000000000 +0000 @@ -49,7 +49,7 @@ } catch (Exception e) { String className = getRealClassName(attributes); if (log.isDebugEnabled()) { - log.info(sm.getString("listener.createFailed", className), e); + log.debug(sm.getString("listener.createFailed", className), e); } else { log.info(sm.getString("listener.createFailed", className)); } diff -Nru tomcat10-10.1.40/java/org/apache/catalina/startup/LocalStrings_ja.properties tomcat10-10.1.52/java/org/apache/catalina/startup/LocalStrings_ja.properties --- tomcat10-10.1.40/java/org/apache/catalina/startup/LocalStrings_ja.properties 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/startup/LocalStrings_ja.properties 2026-01-23 19:33:36.000000000 +0000 @@ -153,7 +153,7 @@ hostConfig.migrateError=マイグレーション失敗 hostConfig.reload=リロード中のコンテキスト [{0}] hostConfig.resourceNotAbsolute=[{1}] は完全パスではないためコンテキスト [{0}] からリソースを削除できません -hostConfig.start=HostConfig: 処理を停止します +hostConfig.start=HostConfig: 処理を開始します hostConfig.stop=HostConfig: 処理を停止します hostConfig.undeploy=コンテキストパス [{0}] のWebアプリケーションの配備を解除します hostConfig.undeployVersion=コンテキスト [{0}] について有効なセッションの存在しない古いバージョンの配備を解除します。 diff -Nru tomcat10-10.1.40/java/org/apache/catalina/startup/LocalStrings_ru.properties tomcat10-10.1.52/java/org/apache/catalina/startup/LocalStrings_ru.properties --- tomcat10-10.1.40/java/org/apache/catalina/startup/LocalStrings_ru.properties 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/startup/LocalStrings_ru.properties 2026-01-23 19:33:36.000000000 +0000 @@ -24,8 +24,12 @@ contextConfig.defaultMissing=Не обнаружен глобальный web.xml contextConfig.defaultPosition=Произошло в строке [{0}] столбце [{1}] contextConfig.inputStreamWebResource=Не возможно обработать веб ресурс [{0}] для аннотаций\n +contextConfig.jspFile.error=JSP файл [{0}] должен начинаться с ''/'' +contextConfig.processAnnotationsDir.debug=Сканируется директория в поисках файлов классов с аннотациями [{0}] contextConfig.tomcatWebXmlError=Ошибка обработки /WEB-INF/tomcat-web.xml +expandWar.createFailed=Невозможно создать директорию [{0}] + hostConfig.deployDir=Установка веб приложения в папку [{0}] hostConfig.deployWar.error=Ошибка при развертывании архива с веб-приложением [{0}] hostConfig.docBaseUrlInvalid=Предоставленый docBase не может быть представлен в виде URL diff -Nru tomcat10-10.1.40/java/org/apache/catalina/startup/LocalStrings_zh_CN.properties tomcat10-10.1.52/java/org/apache/catalina/startup/LocalStrings_zh_CN.properties --- tomcat10-10.1.40/java/org/apache/catalina/startup/LocalStrings_zh_CN.properties 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/startup/LocalStrings_zh_CN.properties 2026-01-23 19:33:36.000000000 +0000 @@ -127,7 +127,7 @@ hostConfig.deployDir.finished=Web应用程序目录[{0}]的部署已在[{1}]毫秒内完成 hostConfig.deployDir.threaded.error=等待目录的多线程部署完成时出错 hostConfig.deployWar=正在部署web应用程序存档文件[{0}] -hostConfig.deployWar.error=部署 Web 应用程序 archive [{0}] 时出错 +hostConfig.deployWar.error=部署 Web 应用程序存档 [{0}] 时出错 hostConfig.deployWar.finished=web应用程序存档文件[{0}]的部署已在[{1}]ms内完成 hostConfig.deployWar.hiddenDir=将忽略目录[{0}],因为WAR [{1}]优先,unpackWAR为false hostConfig.deployWar.threaded.error=等待WAR文件的多线程部署完成时出错 @@ -163,7 +163,7 @@ tomcat.noContextClass=无法为主机[{1}]和url[{2}]实例化上下文类[{0}] tomcat.noContextXml=不能找到web 应用的context.xml [{0}] -userConfig.database=加载用户数据库异常 +userConfig.database=用户数据库加载异常 userConfig.deploy=正在为用户[{0}]部署web应用程序 userConfig.deploy.threaded.error=等待用户目录的多线程部署完成时出错 userConfig.deploying=正在部署用户 web 应用程序 diff -Nru tomcat10-10.1.40/java/org/apache/catalina/startup/MimeTypeMappings.properties tomcat10-10.1.52/java/org/apache/catalina/startup/MimeTypeMappings.properties --- tomcat10-10.1.40/java/org/apache/catalina/startup/MimeTypeMappings.properties 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/startup/MimeTypeMappings.properties 2026-01-23 19:33:36.000000000 +0000 @@ -62,6 +62,7 @@ atx=application/vnd.antix.game-component au=audio/basic avi=video/x-msvideo +avif=image/avif avx=video/x-rad-screenplay aw=application/applixware axa=audio/annodex @@ -388,6 +389,7 @@ json=application/json jsonml=application/jsonml+json jspf=text/plain +jxl=image/jxl kar=audio/midi karbon=application/vnd.kde.karbon kfo=application/vnd.kde.kformula @@ -430,6 +432,8 @@ m1v=video/mpeg m21=application/mp21 m2a=audio/mpeg +m2t=video/mp2t +m2ts=video/mp2t m2v=video/mpeg m3a=audio/mpeg m3u=audio/x-mpegurl @@ -522,7 +526,7 @@ msi=application/x-msdownload msl=application/vnd.mobius.msl msty=application/vnd.muvee.style -mts=model/vnd.mts +mts=video/mp2t mus=application/vnd.musician musicxml=application/vnd.recordare.musicxml+xml mvb=application/x-msmediaview @@ -777,6 +781,8 @@ spq=application/scvp-vp-request spx=audio/ogg sql=application/x-sql +sqlite=application/vnd.sqlite3 +sqlite3=application/vnd.sqlite3 src=application/x-wais-source srt=application/x-subrip sru=application/sru+xml @@ -839,6 +845,7 @@ tr=text/troff tra=application/vnd.trueapp trm=application/x-msterminal +ts=video/mp2t tsd=application/timestamped-data tsv=text/tab-separated-values ttc=font/collection diff -Nru tomcat10-10.1.40/java/org/apache/catalina/startup/NamingRuleSet.java tomcat10-10.1.52/java/org/apache/catalina/startup/NamingRuleSet.java --- tomcat10-10.1.40/java/org/apache/catalina/startup/NamingRuleSet.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/startup/NamingRuleSet.java 2026-01-23 19:33:36.000000000 +0000 @@ -21,9 +21,6 @@ /** * RuleSet for processing the JNDI Enterprise Naming Context resource declaration elements. - * - * @author Craig R. McClanahan - * @author Remy Maucherat */ public class NamingRuleSet implements RuleSet { diff -Nru tomcat10-10.1.40/java/org/apache/catalina/startup/PasswdUserDatabase.java tomcat10-10.1.52/java/org/apache/catalina/startup/PasswdUserDatabase.java --- tomcat10-10.1.40/java/org/apache/catalina/startup/PasswdUserDatabase.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/startup/PasswdUserDatabase.java 2026-01-23 19:33:36.000000000 +0000 @@ -30,8 +30,6 @@ /** * Concrete implementation of the UserDatabase interface that processes the /etc/passwd file * on a Unix system. - * - * @author Craig R. McClanahan */ public final class PasswdUserDatabase implements UserDatabase { diff -Nru tomcat10-10.1.40/java/org/apache/catalina/startup/Tomcat.java tomcat10-10.1.52/java/org/apache/catalina/startup/Tomcat.java --- tomcat10-10.1.40/java/org/apache/catalina/startup/Tomcat.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/startup/Tomcat.java 2026-01-23 19:33:36.000000000 +0000 @@ -132,8 +132,6 @@ * * @see TestTomcat - * - * @author Costin Manolache */ public class Tomcat { @@ -812,7 +810,7 @@ } try { baseFile = baseFile.getCanonicalFile(); - } catch (IOException e) { + } catch (IOException ioe) { baseFile = baseFile.getAbsoluteFile(); } server.setCatalinaBase(baseFile); @@ -829,7 +827,7 @@ } try { homeFile = homeFile.getCanonicalFile(); - } catch (IOException e) { + } catch (IOException ioe) { homeFile = homeFile.getAbsoluteFile(); } server.setCatalinaHome(homeFile); @@ -877,10 +875,10 @@ /** - * By default, when calling addWebapp() to create a Context, the settings from the default web.xml are added to - * the context. Calling this method with a false value prior to calling addWebapp() allows to opt out - * of the default settings. In that event you will need to add the configurations yourself, either programmatically - * or by using web.xml deployment descriptors. + * By default, when calling addWebapp() to create a Context, the settings from the default web.xml are added to the + * context. Calling this method with a false value prior to calling addWebapp() allows to opt out of + * the default settings. In that event you will need to add the configurations yourself, either programmatically or + * by using web.xml deployment descriptors. * * @param addDefaultWebXmlToWebapp false will prevent the class from automatically adding the default * settings when calling addWebapp(). true will add the default @@ -993,7 +991,6 @@ *
  • MIME mappings (subset of those in conf/web.xml)
  • *
  • Welcome files
  • * - * TODO: Align the MIME mappings with conf/web.xml - possibly via a common file. * * @param contextPath The path of the context to set the defaults for */ @@ -1035,11 +1032,15 @@ ctx.addWelcomeFile("index.html"); ctx.addWelcomeFile("index.htm"); ctx.addWelcomeFile("index.jsp"); + // Any application configured welcome files should override the defaults. + if (ctx instanceof StandardContext) { + ((StandardContext) ctx).setReplaceWelcomeFiles(true); + } } /** - * Add the default MIME type mappings to the provide Context. + * Add the default MIME type mappings to the provided Context. * * @param context The web application to which the default MIME type mappings should be added. */ @@ -1050,8 +1051,8 @@ for (Map.Entry entry : defaultMimeMappings.entrySet()) { context.addMimeMapping((String) entry.getKey(), (String) entry.getValue()); } - } catch (IOException e) { - throw new IllegalStateException(sm.getString("tomcat.defaultMimeTypeMappingsFail"), e); + } catch (IOException ioe) { + throw new IllegalStateException(sm.getString("tomcat.defaultMimeTypeMappingsFail"), ioe); } } @@ -1183,9 +1184,9 @@ if (entry != null) { result = UriUtil.buildJarUrl(docBase, Constants.ApplicationContextXml); } - } catch (IOException e) { + } catch (IOException ioe) { Logger.getLogger(getLoggerName(getHost(), contextName)).log(Level.WARNING, - sm.getString("tomcat.noContextXml", docBase), e); + sm.getString("tomcat.noContextXml", docBase), ioe); } return result; } @@ -1194,7 +1195,7 @@ // Graal native images don't load any configuration except the VM default if (JreCompat.isGraalAvailable()) { try (InputStream is = new FileInputStream( - System.getProperty("java.util.logging.config.file", "conf/logging.properties"))) { + System.getProperty("java.util.logging.config.file", "conf/logging.properties"))) { LogManager.getLogManager().readConfiguration(is); } catch (SecurityException | IOException e) { // Ignore, the VM default will be used diff -Nru tomcat10-10.1.40/java/org/apache/catalina/startup/Tool.java tomcat10-10.1.52/java/org/apache/catalina/startup/Tool.java --- tomcat10-10.1.40/java/org/apache/catalina/startup/Tool.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/startup/Tool.java 2026-01-23 19:33:36.000000000 +0000 @@ -60,8 +60,6 @@ *
  • ${arguments} - Command line arguments to be passed to the application's main() * method.
  • * - * - * @author Craig R. McClanahan */ public final class Tool { diff -Nru tomcat10-10.1.40/java/org/apache/catalina/startup/UserConfig.java tomcat10-10.1.52/java/org/apache/catalina/startup/UserConfig.java --- tomcat10-10.1.40/java/org/apache/catalina/startup/UserConfig.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/startup/UserConfig.java 2026-01-23 19:33:36.000000000 +0000 @@ -40,8 +40,6 @@ * a web application in a directory with the specified name in their home directories. The context path of each deployed * application will be set to ~xxxxx, where xxxxx is the username of the owning user for that web * application - * - * @author Craig R. McClanahan */ public final class UserConfig implements LifecycleListener { diff -Nru tomcat10-10.1.40/java/org/apache/catalina/startup/UserDatabase.java tomcat10-10.1.52/java/org/apache/catalina/startup/UserDatabase.java --- tomcat10-10.1.40/java/org/apache/catalina/startup/UserDatabase.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/startup/UserDatabase.java 2026-01-23 19:33:36.000000000 +0000 @@ -22,8 +22,6 @@ /** * Abstraction of the set of users defined by the operating system on the current server platform. - * - * @author Craig R. McClanahan */ public interface UserDatabase { diff -Nru tomcat10-10.1.40/java/org/apache/catalina/storeconfig/ConnectorStoreAppender.java tomcat10-10.1.52/java/org/apache/catalina/storeconfig/ConnectorStoreAppender.java --- tomcat10-10.1.40/java/org/apache/catalina/storeconfig/ConnectorStoreAppender.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/storeconfig/ConnectorStoreAppender.java 2026-01-23 19:33:36.000000000 +0000 @@ -254,7 +254,7 @@ File file = new File(System.getProperty(Globals.CATALINA_BASE_PROP)); try { file = file.getCanonicalFile(); - } catch (IOException e) { + } catch (IOException ioe) { // Ignore } return file; @@ -269,7 +269,7 @@ } try { jkHomeBase = file.getCanonicalFile(); - } catch (IOException e) { + } catch (IOException ioe) { jkHomeBase = file; } return jkHomeBase; diff -Nru tomcat10-10.1.40/java/org/apache/catalina/storeconfig/LoaderSF.java tomcat10-10.1.52/java/org/apache/catalina/storeconfig/LoaderSF.java --- tomcat10-10.1.40/java/org/apache/catalina/storeconfig/LoaderSF.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/storeconfig/LoaderSF.java 2026-01-23 19:33:36.000000000 +0000 @@ -44,9 +44,7 @@ } } else { if (log.isWarnEnabled()) { - if (log.isWarnEnabled()) { - log.warn(sm.getString("factory.storeNoDescriptor", aElement.getClass())); - } + log.warn(sm.getString("factory.storeNoDescriptor", aElement.getClass())); } } } @@ -65,6 +63,6 @@ } WebappLoader wloader = (WebappLoader) loader; return (!wloader.getDelegate()) && - wloader.getLoaderClass().equals("org.apache.catalina.loader.WebappClassLoader"); + wloader.getLoaderClass().equals("org.apache.catalina.loader.WebappClassLoader"); } } diff -Nru tomcat10-10.1.40/java/org/apache/catalina/storeconfig/OpenSSLConfSF.java tomcat10-10.1.52/java/org/apache/catalina/storeconfig/OpenSSLConfSF.java --- tomcat10-10.1.40/java/org/apache/catalina/storeconfig/OpenSSLConfSF.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/storeconfig/OpenSSLConfSF.java 2026-01-23 19:33:36.000000000 +0000 @@ -17,6 +17,7 @@ package org.apache.catalina.storeconfig; import java.io.PrintWriter; +import java.util.Set; import org.apache.tomcat.util.net.openssl.OpenSSLConf; import org.apache.tomcat.util.net.openssl.OpenSSLConfCmd; @@ -26,6 +27,8 @@ */ public class OpenSSLConfSF extends StoreFactoryBase { + private static final Set INTERNAL_COMMANDS = Set.of(OpenSSLConfCmd.NO_OCSP_CHECK); + /** * Store nested OpenSSLConfCmd elements. *

    @@ -37,9 +40,13 @@ if (aOpenSSLConf instanceof OpenSSLConf) { OpenSSLConf openSslConf = (OpenSSLConf) aOpenSSLConf; // Store nested elements - OpenSSLConfCmd[] openSSLConfCmds = openSslConf.getCommands().toArray(new OpenSSLConfCmd[0]); - storeElementArray(aWriter, indent + 2, openSSLConfCmds); + for (OpenSSLConfCmd openSSLConfCmd : openSslConf.getCommands()) { + // Don't store the internal commands that are created from other SslHostConfig attributes. + if (INTERNAL_COMMANDS.contains(openSSLConfCmd.getName())) { + continue; + } + storeElement(aWriter, indent + 2, openSSLConfCmd); + } } } - } diff -Nru tomcat10-10.1.40/java/org/apache/catalina/storeconfig/StandardContextSF.java tomcat10-10.1.52/java/org/apache/catalina/storeconfig/StandardContextSF.java --- tomcat10-10.1.40/java/org/apache/catalina/storeconfig/StandardContextSF.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/storeconfig/StandardContextSF.java 2026-01-23 19:33:36.000000000 +0000 @@ -288,8 +288,8 @@ file = new File(file, host.getName()); try { file = file.getCanonicalFile(); - } catch (IOException e) { - log.error(sm.getString("standardContextSF.canonicalPathError"), e); + } catch (IOException ioe) { + log.error(sm.getString("standardContextSF.canonicalPathError"), ioe); } } return file; diff -Nru tomcat10-10.1.40/java/org/apache/catalina/storeconfig/StoreAppender.java tomcat10-10.1.52/java/org/apache/catalina/storeconfig/StoreAppender.java --- tomcat10-10.1.40/java/org/apache/catalina/storeconfig/StoreAppender.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/storeconfig/StoreAppender.java 2026-01-23 19:33:36.000000000 +0000 @@ -35,9 +35,9 @@ /** * The set of classes that represent persistable properties. */ - private static final Class[] persistables = { String.class, Integer.class, Integer.TYPE, Boolean.class, Boolean.TYPE, - Byte.class, Byte.TYPE, Character.class, Character.TYPE, Double.class, Double.TYPE, Float.class, Float.TYPE, - Long.class, Long.TYPE, Short.class, Short.TYPE, InetAddress.class }; + private static final Class[] persistables = { String.class, Integer.class, Integer.TYPE, Boolean.class, + Boolean.TYPE, Byte.class, Byte.TYPE, Character.class, Character.TYPE, Double.class, Double.TYPE, + Float.class, Float.TYPE, Long.class, Long.TYPE, Short.class, Short.TYPE, InetAddress.class }; private int pos = 0; diff -Nru tomcat10-10.1.40/java/org/apache/catalina/storeconfig/StoreConfigLifecycleListener.java tomcat10-10.1.52/java/org/apache/catalina/storeconfig/StoreConfigLifecycleListener.java --- tomcat10-10.1.40/java/org/apache/catalina/storeconfig/StoreConfigLifecycleListener.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/storeconfig/StoreConfigLifecycleListener.java 2026-01-23 19:33:36.000000000 +0000 @@ -97,8 +97,8 @@ // Note: Hard-coded domain used since this object is per Server/JVM oname = new ObjectName("Catalina:type=StoreConfig"); registry.registerComponent(storeConfig, oname, "StoreConfig"); - } catch (Exception ex) { - log.error(sm.getString("storeConfigListener.registerError"), ex); + } catch (Exception e) { + log.error(sm.getString("storeConfigListener.registerError"), e); } } diff -Nru tomcat10-10.1.40/java/org/apache/catalina/storeconfig/StoreContextAppender.java tomcat10-10.1.52/java/org/apache/catalina/storeconfig/StoreContextAppender.java --- tomcat10-10.1.40/java/org/apache/catalina/storeconfig/StoreContextAppender.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/storeconfig/StoreContextAppender.java 2026-01-23 19:33:36.000000000 +0000 @@ -92,7 +92,7 @@ } try { appBase = file.getCanonicalFile(); - } catch (IOException e) { + } catch (IOException ioe) { appBase = file; } return appBase; @@ -111,7 +111,7 @@ } try { docBase = file.getCanonicalFile(); - } catch (IOException e) { + } catch (IOException ioe) { docBase = file; } return docBase; diff -Nru tomcat10-10.1.40/java/org/apache/catalina/storeconfig/StoreFactoryBase.java tomcat10-10.1.52/java/org/apache/catalina/storeconfig/StoreFactoryBase.java --- tomcat10-10.1.40/java/org/apache/catalina/storeconfig/StoreFactoryBase.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/storeconfig/StoreFactoryBase.java 2026-01-23 19:33:36.000000000 +0000 @@ -160,9 +160,9 @@ for (Object element : elements) { try { storeElement(aWriter, indent, element); - } catch (IOException ioe) { - // ignore children report error them self! - // see StandardContext.storeWithBackup() + } catch (IOException ignore) { + // Ignore. Children report error themselves. + // See StandardContext.storeWithBackup() } } } diff -Nru tomcat10-10.1.40/java/org/apache/catalina/storeconfig/StoreLoader.java tomcat10-10.1.52/java/org/apache/catalina/storeconfig/StoreLoader.java --- tomcat10-10.1.40/java/org/apache/catalina/storeconfig/StoreLoader.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/storeconfig/StoreLoader.java 2026-01-23 19:33:36.000000000 +0000 @@ -132,7 +132,7 @@ synchronized (digester) { registry = (StoreRegistry) digester.parse(is); } - } catch (IOException e) { + } catch (IOException ioe) { // Try default classloader location try (InputStream is = StoreLoader.class.getResourceAsStream("/org/apache/catalina/storeconfig/server-registry.xml")) { @@ -143,7 +143,7 @@ registry = (StoreRegistry) digester.parse(is); } } else { - throw e; + throw ioe; } } } diff -Nru tomcat10-10.1.40/java/org/apache/catalina/tribes/Channel.java tomcat10-10.1.52/java/org/apache/catalina/tribes/Channel.java --- tomcat10-10.1.40/java/org/apache/catalina/tribes/Channel.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/tribes/Channel.java 2026-01-23 19:33:36.000000000 +0000 @@ -279,8 +279,8 @@ void start(int svc) throws ChannelException; /** - * Shuts down the channel. This can be called multiple times for individual services to shut down. - * The svc parameter can be the logical or value of any constants + * Shuts down the channel. This can be called multiple times for individual services to shut down. The svc parameter + * can be the logical or value of any constants * * @param svc one of: *

      @@ -515,8 +515,10 @@ return Integer.parseInt(input); } catch (NumberFormatException nfe) { final Log log = LogFactory.getLog(Channel.class); - log.trace(String.format("Failed to parse [%s] as integer, channelSendOptions possibly set by name(s)", - input)); + if (log.isTraceEnabled()) { + log.trace(String.format("Failed to parse [%s] as integer, channelSendOptions possibly set by name(s)", + input), nfe); + } } String[] options = input.split("\\s*,\\s*"); diff -Nru tomcat10-10.1.40/java/org/apache/catalina/tribes/ChannelInterceptor.java tomcat10-10.1.52/java/org/apache/catalina/tribes/ChannelInterceptor.java --- tomcat10-10.1.40/java/org/apache/catalina/tribes/ChannelInterceptor.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/tribes/ChannelInterceptor.java 2026-01-23 19:33:36.000000000 +0000 @@ -182,8 +182,8 @@ void start(int svc) throws ChannelException; /** - * Shuts down the channel. This can be called multiple times for individual services to shut down. - * The svc parameter can be the logical or value of any constants + * Shuts down the channel. This can be called multiple times for individual services to shut down. The svc parameter + * can be the logical or value of any constants * * @param svc one of: *
        diff -Nru tomcat10-10.1.40/java/org/apache/catalina/tribes/group/ChannelCoordinator.java tomcat10-10.1.52/java/org/apache/catalina/tribes/group/ChannelCoordinator.java --- tomcat10-10.1.40/java/org/apache/catalina/tribes/group/ChannelCoordinator.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/tribes/group/ChannelCoordinator.java 2026-01-23 19:33:36.000000000 +0000 @@ -175,8 +175,8 @@ startLevel = (startLevel | svc); } catch (ChannelException cx) { throw cx; - } catch (Exception x) { - throw new ChannelException(x); + } catch (Exception e) { + throw new ChannelException(e); } } @@ -231,8 +231,8 @@ startLevel = (startLevel & (~svc)); setChannel(null); - } catch (Exception x) { - throw new ChannelException(x); + } catch (Exception e) { + throw new ChannelException(e); } } @@ -274,7 +274,10 @@ return membershipService; } - public void setClusterReceiver(ChannelReceiver clusterReceiver) { + public synchronized void setClusterReceiver(ChannelReceiver clusterReceiver) { + if (startLevel != 0) { + throw new IllegalStateException(sm.getString("channelCoordinator.invalidState.notStopped")); + } if (clusterReceiver != null) { this.clusterReceiver = clusterReceiver; this.clusterReceiver.setMessageListener(this); @@ -286,11 +289,17 @@ } } - public void setClusterSender(ChannelSender clusterSender) { + public synchronized void setClusterSender(ChannelSender clusterSender) { + if (startLevel != 0) { + throw new IllegalStateException(sm.getString("channelCoordinator.invalidState.notStopped")); + } this.clusterSender = clusterSender; } - public void setMembershipService(MembershipService membershipService) { + public synchronized void setMembershipService(MembershipService membershipService) { + if (startLevel != 0) { + throw new IllegalStateException(sm.getString("channelCoordinator.invalidState.notStopped")); + } this.membershipService = membershipService; this.membershipService.setMembershipListener(this); } diff -Nru tomcat10-10.1.40/java/org/apache/catalina/tribes/group/GroupChannel.java tomcat10-10.1.52/java/org/apache/catalina/tribes/group/GroupChannel.java --- tomcat10-10.1.40/java/org/apache/catalina/tribes/group/GroupChannel.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/tribes/group/GroupChannel.java 2026-01-23 19:33:36.000000000 +0000 @@ -278,8 +278,8 @@ } else { try { fwd = XByteBuffer.deserialize(msg.getMessage().getBytesDirect(), 0, msg.getMessage().getLength()); - } catch (Exception sx) { - log.error(sm.getString("groupChannel.unable.deserialize", msg), sx); + } catch (Exception e) { + log.error(sm.getString("groupChannel.unable.deserialize", msg), e); return; } } @@ -311,13 +311,13 @@ Logs.MESSAGES.trace("GroupChannel delivered[" + delivered + "] id:" + new UniqueId(msg.getUniqueId())); } - } catch (Exception x) { + } catch (Exception e) { // this could be the channel listener throwing an exception, we should log it // as a warning. if (log.isWarnEnabled()) { - log.warn(sm.getString("groupChannel.receiving.error"), x); + log.warn(sm.getString("groupChannel.receiving.error"), e); } - throw new RemoteProcessException(sm.getString("groupChannel.receiving.error"), x); + throw new RemoteProcessException(sm.getString("groupChannel.receiving.error"), e); } } @@ -337,8 +337,8 @@ } RpcMessage.NoRpcChannelReply reply = new RpcMessage.NoRpcChannelReply(msg.rpcId, msg.uuid); send(new Member[] { destination }, reply, SEND_OPTIONS_ASYNCHRONOUS); - } catch (Exception x) { - log.error(sm.getString("groupChannel.sendFail.noRpcChannelReply"), x); + } catch (Exception e) { + log.error(sm.getString("groupChannel.sendFail.noRpcChannelReply"), e); } } diff -Nru tomcat10-10.1.40/java/org/apache/catalina/tribes/group/LocalStrings.properties tomcat10-10.1.52/java/org/apache/catalina/tribes/group/LocalStrings.properties --- tomcat10-10.1.40/java/org/apache/catalina/tribes/group/LocalStrings.properties 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/tribes/group/LocalStrings.properties 2026-01-23 19:33:36.000000000 +0000 @@ -18,6 +18,7 @@ channelCoordinator.alreadyStarted=Channel already started for level:[{0}] channelCoordinator.invalid.startLevel=Invalid start level, valid levels are:SND_RX_SEQ,SND_TX_SEQ,MBR_TX_SEQ,MBR_RX_SEQ +channelCoordinator.invalidState.notStopped=Configuration may not be changed until the channel has been fully stopped groupChannel.listener.alreadyExist=Listener already exists:[{0}][{1}] groupChannel.noDestination=No destination given diff -Nru tomcat10-10.1.40/java/org/apache/catalina/tribes/group/LocalStrings_fr.properties tomcat10-10.1.52/java/org/apache/catalina/tribes/group/LocalStrings_fr.properties --- tomcat10-10.1.40/java/org/apache/catalina/tribes/group/LocalStrings_fr.properties 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/tribes/group/LocalStrings_fr.properties 2026-01-23 19:33:36.000000000 +0000 @@ -18,6 +18,7 @@ channelCoordinator.alreadyStarted=Canal déjà démarré pour le niveau : [{0}] channelCoordinator.invalid.startLevel=Niveau de départ invalide, les niveaux valides sont : SND_RX_SEQ,SND_TX_SEQ,MBR_TX_SEQ,MBR_RX_SEQ +channelCoordinator.invalidState.notStopped=La configuration ne peut pas être changée avant que ce canal (Channel) ne soit complètement arrêté groupChannel.listener.alreadyExist=L''écouteur existe déjà : [{0}][{1}] groupChannel.noDestination=Aucune destination donnée diff -Nru tomcat10-10.1.40/java/org/apache/catalina/tribes/group/LocalStrings_ja.properties tomcat10-10.1.52/java/org/apache/catalina/tribes/group/LocalStrings_ja.properties --- tomcat10-10.1.40/java/org/apache/catalina/tribes/group/LocalStrings_ja.properties 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/tribes/group/LocalStrings_ja.properties 2026-01-23 19:33:36.000000000 +0000 @@ -18,6 +18,7 @@ channelCoordinator.alreadyStarted=チャンネルは既にレベル:[{0}]で開始されました。 channelCoordinator.invalid.startLevel=無効な開始レベルです。有効なレベルは SND_RX_SEQ、SND_TX_SEQ、MBR_TX_SEQ、MBR_RX_SEQ です +channelCoordinator.invalidState.notStopped=channel が完全に停止するまで設定を変更することはできません groupChannel.listener.alreadyExist=チャンネルリスナー [{0}][{1}] はすでに存在します。 groupChannel.noDestination=宛先が指定されていません。 diff -Nru tomcat10-10.1.40/java/org/apache/catalina/tribes/group/RpcChannel.java tomcat10-10.1.52/java/org/apache/catalina/tribes/group/RpcChannel.java --- tomcat10-10.1.40/java/org/apache/catalina/tribes/group/RpcChannel.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/tribes/group/RpcChannel.java 2026-01-23 19:33:36.000000000 +0000 @@ -100,7 +100,11 @@ RpcMessage rmsg = new RpcMessage(rpcId, key.id, message); channel.send(destination, rmsg, sendOptions); if (rpcOptions != NO_REPLY) { - collector.wait(timeout); + long timeoutExpiry = System.nanoTime() + timeout * 1_000_000; + while (!collector.isComplete() && timeout > 0) { + collector.wait(timeout); + timeout = (timeoutExpiry - System.nanoTime()) / 1_000_000; + } } } } catch (InterruptedException ix) { @@ -175,11 +179,11 @@ replyMessageOptions & ~Channel.SEND_OPTIONS_SYNCHRONIZED_ACK); } finished = true; - } catch (Exception x) { + } catch (Exception e) { if (excallback != null && !asyncReply) { - excallback.replyFailed(rmsg.message, reply, sender, x); + excallback.replyFailed(rmsg.message, reply, sender, e); } else { - log.error(sm.getString("rpcChannel.replyFailed"), x); + log.error(sm.getString("rpcChannel.replyFailed"), e); } } if (finished && excallback != null && !asyncReply) { diff -Nru tomcat10-10.1.40/java/org/apache/catalina/tribes/group/interceptors/FragmentationInterceptor.java tomcat10-10.1.52/java/org/apache/catalina/tribes/group/interceptors/FragmentationInterceptor.java --- tomcat10-10.1.40/java/org/apache/catalina/tribes/group/interceptors/FragmentationInterceptor.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/tribes/group/interceptors/FragmentationInterceptor.java 2026-01-23 19:33:36.000000000 +0000 @@ -148,9 +148,9 @@ removeFragCollection(key); } } - } catch (Exception x) { + } catch (Exception e) { if (log.isErrorEnabled()) { - log.error(sm.getString("fragmentationInterceptor.heartbeat.failed"), x); + log.error(sm.getString("fragmentationInterceptor.heartbeat.failed"), e); } } super.heartbeat(); diff -Nru tomcat10-10.1.40/java/org/apache/catalina/tribes/group/interceptors/GzipInterceptor.java tomcat10-10.1.52/java/org/apache/catalina/tribes/group/interceptors/GzipInterceptor.java --- tomcat10-10.1.40/java/org/apache/catalina/tribes/group/interceptors/GzipInterceptor.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/tribes/group/interceptors/GzipInterceptor.java 2026-01-23 19:33:36.000000000 +0000 @@ -94,9 +94,9 @@ if (statsEnabled && interval > 0 && currentCount % interval == 0) { report(); } - } catch (IOException x) { + } catch (IOException ioe) { log.error(sm.getString("gzipInterceptor.compress.failed")); - throw new ChannelException(x); + throw new ChannelException(ioe); } } @@ -129,8 +129,8 @@ if (statsEnabled && interval > 0 && currentCount % interval == 0) { report(); } - } catch (IOException x) { - log.error(sm.getString("gzipInterceptor.decompress.failed"), x); + } catch (IOException ioe) { + log.error(sm.getString("gzipInterceptor.decompress.failed"), ioe); } } diff -Nru tomcat10-10.1.40/java/org/apache/catalina/tribes/group/interceptors/LocalStrings.properties tomcat10-10.1.52/java/org/apache/catalina/tribes/group/interceptors/LocalStrings.properties --- tomcat10-10.1.40/java/org/apache/catalina/tribes/group/interceptors/LocalStrings.properties 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/tribes/group/interceptors/LocalStrings.properties 2026-01-23 19:33:36.000000000 +0000 @@ -83,7 +83,7 @@ tcpFailureDetector.member.disappeared=Verification complete. Member disappeared[{0}] tcpFailureDetector.memberDisappeared.verify=Received memberDisappeared[{0}] message. Will verify. tcpFailureDetector.performBasicCheck.memberAdded=Member added, even though we weren''t notified:[{0}] -tcpFailureDetector.recievedPacket=Received a failure detector packet [{0}] +tcpFailureDetector.receivedPacket=Received a failure detector packet [{0}] tcpFailureDetector.still.alive=Verification complete. Member still alive[{0}] tcpFailureDetector.suspectMember.alive=Suspect member, confirmed alive.[{0}] tcpFailureDetector.suspectMember.dead=Suspect member, confirmed dead.[{0}] diff -Nru tomcat10-10.1.40/java/org/apache/catalina/tribes/group/interceptors/LocalStrings_fr.properties tomcat10-10.1.52/java/org/apache/catalina/tribes/group/interceptors/LocalStrings_fr.properties --- tomcat10-10.1.40/java/org/apache/catalina/tribes/group/interceptors/LocalStrings_fr.properties 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/tribes/group/interceptors/LocalStrings_fr.properties 2026-01-23 19:33:36.000000000 +0000 @@ -83,7 +83,7 @@ tcpFailureDetector.member.disappeared=La vérfication est complète, le membre a disparu [{0}] tcpFailureDetector.memberDisappeared.verify=Reçu un message memberDisappeared[{0}], qui sera vérifié tcpFailureDetector.performBasicCheck.memberAdded=Le membre a été ajouté bien qu''aucune notification n''ait été reçue : [{0}] -tcpFailureDetector.recievedPacket=Réception d''un paquet de détection d''échec [{0}] +tcpFailureDetector.receivedPacket=Réception d''un paquet de détection d''échec [{0}] tcpFailureDetector.still.alive=Vérification terminée. Le membre [{0}] vit toujours tcpFailureDetector.suspectMember.alive=Membre suspect, confirmé vivant.[{0}] tcpFailureDetector.suspectMember.dead=Un membre suspect a été confirmé mort [{0}] diff -Nru tomcat10-10.1.40/java/org/apache/catalina/tribes/group/interceptors/LocalStrings_ja.properties tomcat10-10.1.52/java/org/apache/catalina/tribes/group/interceptors/LocalStrings_ja.properties --- tomcat10-10.1.40/java/org/apache/catalina/tribes/group/interceptors/LocalStrings_ja.properties 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/tribes/group/interceptors/LocalStrings_ja.properties 2026-01-23 19:33:36.000000000 +0000 @@ -83,7 +83,7 @@ tcpFailureDetector.member.disappeared=メンバ検証が完了しました。メンバーが消えました [{0}] tcpFailureDetector.memberDisappeared.verify=memberDisappeared[{0}]メッセージを受信しました。メンバ検証します。 tcpFailureDetector.performBasicCheck.memberAdded=私たちに通知されなかったにもかかわらず、メンバーが追加されました:[{0}] -tcpFailureDetector.recievedPacket=障害検出パケット [{0}] を受信しました +tcpFailureDetector.receivedPacket=障害検出パケット [{0}] を受信しました tcpFailureDetector.still.alive=故障検出チェックが完了しました。メンバー [{0}] は正常です。 tcpFailureDetector.suspectMember.alive=疑わしいクラスタメンバーの生存を確認しました。[{0}] tcpFailureDetector.suspectMember.dead=疑義メンバが死亡したことが確認されました。[{0}] diff -Nru tomcat10-10.1.40/java/org/apache/catalina/tribes/group/interceptors/LocalStrings_ru.properties tomcat10-10.1.52/java/org/apache/catalina/tribes/group/interceptors/LocalStrings_ru.properties --- tomcat10-10.1.40/java/org/apache/catalina/tribes/group/interceptors/LocalStrings_ru.properties 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/tribes/group/interceptors/LocalStrings_ru.properties 2026-01-23 19:33:36.000000000 +0000 @@ -17,6 +17,7 @@ # To edit translations see: https://tomcat.apache.org/getinvolved.html#Translations domainFilterInterceptor.member.refused=Участнику [{0}] было отказано в присоединении к кластеру +domainFilterInterceptor.message.refused=Сообщение полученое от кластера [{0}] было отклонено. encryptInterceptor.decrypt.error.short-message=Невозможно расшифровать сообщение: слишком мало символов diff -Nru tomcat10-10.1.40/java/org/apache/catalina/tribes/group/interceptors/MessageDispatchInterceptor.java tomcat10-10.1.52/java/org/apache/catalina/tribes/group/interceptors/MessageDispatchInterceptor.java --- tomcat10-10.1.40/java/org/apache/catalina/tribes/group/interceptors/MessageDispatchInterceptor.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/tribes/group/interceptors/MessageDispatchInterceptor.java 2026-01-23 19:33:36.000000000 +0000 @@ -244,18 +244,18 @@ if (handler != null) { handler.handleCompletion(new UniqueId(msg.getUniqueId())); } - } catch (Exception ex) { - log.error(sm.getString("messageDispatchInterceptor.completeMessage.failed"), ex); + } catch (Exception e) { + log.error(sm.getString("messageDispatchInterceptor.completeMessage.failed"), e); } - } catch (Exception x) { + } catch (Exception e) { ChannelException cx; - if (x instanceof ChannelException) { - cx = (ChannelException) x; + if (e instanceof ChannelException) { + cx = (ChannelException) e; } else { - cx = new ChannelException(x); + cx = new ChannelException(e); } if (log.isDebugEnabled()) { - log.debug(sm.getString("messageDispatchInterceptor.AsyncMessage.failed"), x); + log.debug(sm.getString("messageDispatchInterceptor.AsyncMessage.failed"), e); } try { if (handler != null) { diff -Nru tomcat10-10.1.40/java/org/apache/catalina/tribes/group/interceptors/NonBlockingCoordinator.java tomcat10-10.1.52/java/org/apache/catalina/tribes/group/interceptors/NonBlockingCoordinator.java --- tomcat10-10.1.40/java/org/apache/catalina/tribes/group/interceptors/NonBlockingCoordinator.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/tribes/group/interceptors/NonBlockingCoordinator.java 2026-01-23 19:33:36.000000000 +0000 @@ -238,14 +238,24 @@ new CoordinationEvent(CoordinationEvent.EVT_PROCESS_ELECT, this, "Election, sending request")); sendElectionMsg(local, others[0], msg); } else { - try { - coordMsgReceived.set(false); - fireInterceptorEvent(new CoordinationEvent(CoordinationEvent.EVT_WAIT_FOR_MSG, this, - "Election, waiting for request")); - electionMutex.wait(waitForCoordMsgTimeout); - } catch (InterruptedException x) { - Thread.currentThread().interrupt(); - } + coordMsgReceived.set(false); + fireInterceptorEvent(new CoordinationEvent(CoordinationEvent.EVT_WAIT_FOR_MSG, this, + "Election, waiting for request")); + long timeout = waitForCoordMsgTimeout; + long timeoutEndNanos = System.nanoTime() + timeout * 1_000_000; + do { + try { + electionMutex.wait(timeout); + } catch (InterruptedException x) { + Thread.currentThread().interrupt(); + } + timeout = (timeoutEndNanos - System.nanoTime()) / 1_000_000; + /* + * Spurious wake-ups are possible. Keep waiting if a) the condition we were waiting for hasn't + * happened (i.e. notify() was not called) AND b) the timeout has not expired AND c) the thread was + * not interrupted. + */ + } while (suggestedviewId == null && !coordMsgReceived.get() && timeout > 0 && !Thread.interrupted()); String msg; if (suggestedviewId == null && !coordMsgReceived.get()) { if (Thread.interrupted()) { @@ -266,8 +276,8 @@ Arrays.fill(m, others); Member[] mbrs = m.getMembers(); m.reset(); - return new CoordinationMessage(leader, local, mbrs, - new UniqueId(UUIDGenerator.randomUUID(true)), COORD_REQUEST); + return new CoordinationMessage(leader, local, mbrs, new UniqueId(UUIDGenerator.randomUUID(true)), + COORD_REQUEST); } protected void sendElectionMsg(Member local, Member next, CoordinationMessage msg) throws ChannelException { @@ -286,6 +296,7 @@ sendElectionMsg(local, msg.getMembers()[current], msg); sent = true; } catch (ChannelException x) { + // Exception is logged further up stack log.warn(sm.getString("nonBlockingCoordinator.electionMessage.sendfailed", msg.getMembers()[current])); current = Arrays.nextIndex(msg.getMembers()[current], msg.getMembers()); if (current == next) { @@ -322,8 +333,8 @@ return true; } catch (SocketTimeoutException | ConnectException x) { // do nothing, we couldn't connect - } catch (Exception x) { - log.error(sm.getString("nonBlockingCoordinator.memberAlive.failed"), x); + } catch (Exception e) { + log.error(sm.getString("nonBlockingCoordinator.memberAlive.failed"), e); } return false; } @@ -625,8 +636,8 @@ startElection(true); } } - } catch (Exception x) { - log.error(sm.getString("nonBlockingCoordinator.heartbeat.failed"), x); + } catch (Exception e) { + log.error(sm.getString("nonBlockingCoordinator.heartbeat.failed"), e); } finally { super.heartbeat(); } diff -Nru tomcat10-10.1.40/java/org/apache/catalina/tribes/group/interceptors/SimpleCoordinator.java tomcat10-10.1.52/java/org/apache/catalina/tribes/group/interceptors/SimpleCoordinator.java --- tomcat10-10.1.40/java/org/apache/catalina/tribes/group/interceptors/SimpleCoordinator.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/tribes/group/interceptors/SimpleCoordinator.java 2026-01-23 19:33:36.000000000 +0000 @@ -27,8 +27,6 @@ /** * A dinky coordinator, just uses a sorted version of the member array. - * - * @author rnewson */ public class SimpleCoordinator extends ChannelInterceptorBase { diff -Nru tomcat10-10.1.40/java/org/apache/catalina/tribes/group/interceptors/TcpFailureDetector.java tomcat10-10.1.52/java/org/apache/catalina/tribes/group/interceptors/TcpFailureDetector.java --- tomcat10-10.1.40/java/org/apache/catalina/tribes/group/interceptors/TcpFailureDetector.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/tribes/group/interceptors/TcpFailureDetector.java 2026-01-23 19:33:36.000000000 +0000 @@ -111,7 +111,7 @@ if (process) { super.messageReceived(msg); } else if (log.isDebugEnabled()) { - log.debug(sm.getString("tcpFailureDetector.recievedPacket", msg)); + log.debug(sm.getString("tcpFailureDetector.receivedPacket", msg)); } }// messageReceived @@ -250,8 +250,8 @@ performForcedCheck(); } } - } catch (Exception x) { - log.warn(sm.getString("tcpFailureDetector.heartbeat.failed"), x); + } catch (Exception e) { + log.warn(sm.getString("tcpFailureDetector.heartbeat.failed"), e); } } @@ -383,8 +383,8 @@ return true; } catch (SocketTimeoutException | ConnectException | NoRouteToHostException noop) { // do nothing, we couldn't connect - } catch (Exception x) { - log.error(sm.getString("tcpFailureDetector.failureDetection.failed", mbr), x); + } catch (Exception e) { + log.error(sm.getString("tcpFailureDetector.failureDetection.failed", mbr), e); } return false; } diff -Nru tomcat10-10.1.40/java/org/apache/catalina/tribes/group/interceptors/TcpPingInterceptor.java tomcat10-10.1.52/java/org/apache/catalina/tribes/group/interceptors/TcpPingInterceptor.java --- tomcat10-10.1.40/java/org/apache/catalina/tribes/group/interceptors/TcpPingInterceptor.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/tribes/group/interceptors/TcpPingInterceptor.java 2026-01-23 19:33:36.000000000 +0000 @@ -191,8 +191,8 @@ // Ignore. Probably triggered by a call to stop(). // In the highly unlikely event it was a different trigger, // simply ignore it and continue. - } catch (Exception x) { - log.warn(sm.getString("tcpPingInterceptor.pingFailed.pingThread"), x); + } catch (Exception e) { + log.warn(sm.getString("tcpPingInterceptor.pingFailed.pingThread"), e); } } } diff -Nru tomcat10-10.1.40/java/org/apache/catalina/tribes/group/interceptors/TwoPhaseCommitInterceptor.java tomcat10-10.1.52/java/org/apache/catalina/tribes/group/interceptors/TwoPhaseCommitInterceptor.java --- tomcat10-10.1.40/java/org/apache/catalina/tribes/group/interceptors/TwoPhaseCommitInterceptor.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/tribes/group/interceptors/TwoPhaseCommitInterceptor.java 2026-01-23 19:33:36.000000000 +0000 @@ -129,8 +129,8 @@ messages.remove(entry.id); } } - } catch (Exception x) { - log.warn(sm.getString("twoPhaseCommitInterceptor.heartbeat.failed"), x); + } catch (Exception e) { + log.warn(sm.getString("twoPhaseCommitInterceptor.heartbeat.failed"), e); } finally { super.heartbeat(); } diff -Nru tomcat10-10.1.40/java/org/apache/catalina/tribes/io/ChannelData.java tomcat10-10.1.52/java/org/apache/catalina/tribes/io/ChannelData.java --- tomcat10-10.1.40/java/org/apache/catalina/tribes/io/ChannelData.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/tribes/io/ChannelData.java 2026-01-23 19:33:36.000000000 +0000 @@ -29,8 +29,6 @@ * The ChannelData object is used to transfer a message through the channel interceptor stack and * eventually out on a transport to be sent to another node. While the message is being processed by the different * interceptors, the message data can be manipulated as each interceptor seems appropriate. - * - * @author Peter Rossbach */ public class ChannelData implements ChannelMessage { private static final long serialVersionUID = 1L; @@ -337,9 +335,7 @@ @Override public String toString() { - return "ClusterData[src=" + - getAddress() + "; id=" + - bToS(getUniqueId()) + "; sent=" + + return "ClusterData[src=" + getAddress() + "; id=" + bToS(getUniqueId()) + "; sent=" + new Timestamp(this.getTimestamp()).toString() + ']'; } diff -Nru tomcat10-10.1.40/java/org/apache/catalina/tribes/io/LocalStrings_ru.properties tomcat10-10.1.52/java/org/apache/catalina/tribes/io/LocalStrings_ru.properties --- tomcat10-10.1.40/java/org/apache/catalina/tribes/io/LocalStrings_ru.properties 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/tribes/io/LocalStrings_ru.properties 2026-01-23 19:33:36.000000000 +0000 @@ -17,3 +17,5 @@ # To edit translations see: https://tomcat.apache.org/getinvolved.html#Translations replicationStream.conflict=конфликтующие непубличные загрузчики классов + +xByteBuffer.size.larger.buffer=Размер больше чем существующий буфер diff -Nru tomcat10-10.1.40/java/org/apache/catalina/tribes/io/ObjectReader.java tomcat10-10.1.52/java/org/apache/catalina/tribes/io/ObjectReader.java --- tomcat10-10.1.40/java/org/apache/catalina/tribes/io/ObjectReader.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/tribes/io/ObjectReader.java 2026-01-23 19:33:36.000000000 +0000 @@ -66,10 +66,10 @@ public ObjectReader(Socket socket) { try { this.buffer = new XByteBuffer(socket.getReceiveBufferSize(), true); - } catch (IOException x) { + } catch (IOException ioe) { // unable to get buffer size log.warn(sm.getString("objectReader.retrieveFailed.socketReceiverBufferSize", - Integer.toString(Constants.DEFAULT_CLUSTER_MSG_BUFFER_SIZE))); + Integer.toString(Constants.DEFAULT_CLUSTER_MSG_BUFFER_SIZE)), ioe); this.buffer = new XByteBuffer(Constants.DEFAULT_CLUSTER_MSG_BUFFER_SIZE, true); } } diff -Nru tomcat10-10.1.40/java/org/apache/catalina/tribes/io/ReplicationStream.java tomcat10-10.1.52/java/org/apache/catalina/tribes/io/ReplicationStream.java --- tomcat10-10.1.40/java/org/apache/catalina/tribes/io/ReplicationStream.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/tribes/io/ReplicationStream.java 2026-01-23 19:33:36.000000000 +0000 @@ -28,9 +28,6 @@ /** * Custom subclass of ObjectInputStream that loads from the class loader for this web application. This * allows classes defined only with the web application to be found correctly. - * - * @author Craig R. McClanahan - * @author Bip Thelin */ public final class ReplicationStream extends ObjectInputStream { @@ -83,7 +80,7 @@ } else { return findExternalClass(name); } - } catch (Exception x) { + } catch (Exception e) { if (tryRepFirst) { return findExternalClass(name); } else { diff -Nru tomcat10-10.1.40/java/org/apache/catalina/tribes/jmx/LocalStrings_ru.properties tomcat10-10.1.52/java/org/apache/catalina/tribes/jmx/LocalStrings_ru.properties --- tomcat10-10.1.40/java/org/apache/catalina/tribes/jmx/LocalStrings_ru.properties 1970-01-01 00:00:00.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/tribes/jmx/LocalStrings_ru.properties 2026-01-23 19:33:36.000000000 +0000 @@ -0,0 +1,19 @@ +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# Do not edit this file directly. +# To edit translations see: https://tomcat.apache.org/getinvolved.html#Translations + +jmxRegistry.registerJmx.failed=Невозможно зарегистрировать объект [{0}] с именем [{1}] diff -Nru tomcat10-10.1.40/java/org/apache/catalina/tribes/membership/Constants.java tomcat10-10.1.52/java/org/apache/catalina/tribes/membership/Constants.java --- tomcat10-10.1.40/java/org/apache/catalina/tribes/membership/Constants.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/tribes/membership/Constants.java 2026-01-23 19:33:36.000000000 +0000 @@ -20,8 +20,6 @@ /** * Manifest constants for the org.apache.catalina.tribes.membership package. - * - * @author Peter Rossbach */ public class Constants { diff -Nru tomcat10-10.1.40/java/org/apache/catalina/tribes/membership/LocalStrings.properties tomcat10-10.1.52/java/org/apache/catalina/tribes/membership/LocalStrings.properties --- tomcat10-10.1.40/java/org/apache/catalina/tribes/membership/LocalStrings.properties 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/tribes/membership/LocalStrings.properties 2026-01-23 19:33:36.000000000 +0000 @@ -30,6 +30,7 @@ mcastServiceImpl.bind.failed=Binding to multicast address, failed. Binding to port only. mcastServiceImpl.error.receiving=Error receiving mcast package. Sleeping 500ms mcastServiceImpl.error.receivingNoSleep=Error receiving multicast package +mcastServiceImpl.error.stop=Error during stop of membership service mcastServiceImpl.invalid.startLevel=Invalid start level. Only acceptable levels are Channel.MBR_RX_SEQ and Channel.MBR_TX_SEQ mcastServiceImpl.invalid.stopLevel=Invalid stop level. Only acceptable levels are Channel.MBR_RX_SEQ and Channel.MBR_TX_SEQ mcastServiceImpl.invalidMemberPackage=Invalid member multicast package diff -Nru tomcat10-10.1.40/java/org/apache/catalina/tribes/membership/LocalStrings_fr.properties tomcat10-10.1.52/java/org/apache/catalina/tribes/membership/LocalStrings_fr.properties --- tomcat10-10.1.40/java/org/apache/catalina/tribes/membership/LocalStrings_fr.properties 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/tribes/membership/LocalStrings_fr.properties 2026-01-23 19:33:36.000000000 +0000 @@ -30,6 +30,7 @@ mcastServiceImpl.bind.failed=Echec de l'association à l’adresse multicast, association uniquement sur le port mcastServiceImpl.error.receiving=Erreur en recevant un paquet multicast, attente de 500ms mcastServiceImpl.error.receivingNoSleep=Erreur lors de la réception d'un paquet multicast +mcastServiceImpl.error.stop=Erreur lors de l'arrêt du service de gestion des membres mcastServiceImpl.invalid.startLevel=Niveau de départ invalide. Les seuls niveaux acceptables sont Channel.MBR_RX_SEQ et Channel.MBR_TX_SEQ mcastServiceImpl.invalid.stopLevel=Niveau de stop invalide, les seuls niveaux valides sont Channel.MBR_RX_SEQ et Channel.MBR_TX_SEQ mcastServiceImpl.invalidMemberPackage=Membre invalide dans le paquet multicast diff -Nru tomcat10-10.1.40/java/org/apache/catalina/tribes/membership/LocalStrings_ja.properties tomcat10-10.1.52/java/org/apache/catalina/tribes/membership/LocalStrings_ja.properties --- tomcat10-10.1.40/java/org/apache/catalina/tribes/membership/LocalStrings_ja.properties 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/tribes/membership/LocalStrings_ja.properties 2026-01-23 19:33:36.000000000 +0000 @@ -30,6 +30,7 @@ mcastServiceImpl.bind.failed=マルチキャストアドレスへのバインドに失敗しました。ポートのみにバインドします。 mcastServiceImpl.error.receiving=マルチキャストパッケージを受信中にエラーが発生しました。500msスリープします。 mcastServiceImpl.error.receivingNoSleep=マルチキャスト パッケージの受信エラー +mcastServiceImpl.error.stop=membership サービス停止中にエラーが発生しました mcastServiceImpl.invalid.startLevel=不正な開始レベルです。受け付けられるのは Channel.MBR_RX_SEQ と Channel.MBR_TX_SEQ です。 mcastServiceImpl.invalid.stopLevel=無効な停止レベルです。受け入れ可能なレベルはChannel.MBR_RX_SEQとChannel.MBR_TX_SEQのみです。 mcastServiceImpl.invalidMemberPackage=無効なメンバマルチキャストパッケージ diff -Nru tomcat10-10.1.40/java/org/apache/catalina/tribes/membership/McastService.java tomcat10-10.1.52/java/org/apache/catalina/tribes/membership/McastService.java --- tomcat10-10.1.40/java/org/apache/catalina/tribes/membership/McastService.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/tribes/membership/McastService.java 2026-01-23 19:33:36.000000000 +0000 @@ -147,8 +147,8 @@ localMember.setSecurePort(securePort); localMember.setUdpPort(udpPort); localMember.getData(true, true); - } catch (IOException x) { - throw new IllegalArgumentException(x); + } catch (IOException ioe) { + throw new IllegalArgumentException(ioe); } } @@ -320,15 +320,15 @@ if (properties.getProperty("mcastTTL") != null) { try { ttl = Integer.parseInt(properties.getProperty("mcastTTL")); - } catch (Exception x) { - log.error(sm.getString("McastService.parseTTL", properties.getProperty("mcastTTL")), x); + } catch (Exception e) { + log.error(sm.getString("McastService.parseTTL", properties.getProperty("mcastTTL")), e); } } if (properties.getProperty("mcastSoTimeout") != null) { try { soTimeout = Integer.parseInt(properties.getProperty("mcastSoTimeout")); - } catch (Exception x) { - log.error(sm.getString("McastService.parseSoTimeout", properties.getProperty("mcastSoTimeout")), x); + } catch (Exception e) { + log.error(sm.getString("McastService.parseSoTimeout", properties.getProperty("mcastSoTimeout")), e); } } @@ -372,8 +372,8 @@ impl = null; channel = null; } - } catch (Exception x) { - log.error(sm.getString("McastService.stopFail", Integer.valueOf(svc)), x); + } catch (Exception e) { + log.error(sm.getString("McastService.stopFail", Integer.valueOf(svc)), e); } } @@ -411,8 +411,8 @@ DatagramPacket packet = new DatagramPacket(data, 0, data.length); try { impl.send(false, packet); - } catch (Exception x) { - throw new ChannelException(x); + } catch (Exception e) { + throw new ChannelException(e); } } @@ -454,8 +454,8 @@ if (impl != null) { impl.send(false); } - } catch (Exception x) { - log.error(sm.getString("McastService.payload"), x); + } catch (Exception e) { + log.error(sm.getString("McastService.payload"), e); } } } @@ -469,8 +469,8 @@ if (impl != null) { impl.send(false); } - } catch (Exception x) { - log.error(sm.getString("McastService.domain"), x); + } catch (Exception e) { + log.error(sm.getString("McastService.domain"), e); } } } diff -Nru tomcat10-10.1.40/java/org/apache/catalina/tribes/membership/McastServiceImpl.java tomcat10-10.1.52/java/org/apache/catalina/tribes/membership/McastServiceImpl.java --- tomcat10-10.1.40/java/org/apache/catalina/tribes/membership/McastServiceImpl.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/tribes/membership/McastServiceImpl.java 2026-01-23 19:33:36.000000000 +0000 @@ -202,7 +202,11 @@ * On some platforms (e.g. Linux) it is not possible to bind to the multicast address. In this case only * bind to the port. */ - log.info(sm.getString("mcastServiceImpl.bind.failed")); + if (log.isDebugEnabled()) { + log.debug(sm.getString("mcastServiceImpl.bind.failed"), e); + } else { + log.info(sm.getString("mcastServiceImpl.bind.failed")); + } socket = new MulticastSocket(port); } } else { @@ -289,6 +293,7 @@ try { Thread.sleep(memberwait); } catch (InterruptedException ignore) { + // Ignore } if (log.isInfoEnabled()) { log.info(sm.getString("mcastServiceImpl.waitForMembers.done", Integer.toString(level))); @@ -328,13 +333,19 @@ // leave mcast group try { socket.leaveGroup(new InetSocketAddress(address, 0), null); - } catch (Exception ignore) { - // NO-OP + } catch (Exception e) { + // Shutting down. Only log at debug. + if (log.isDebugEnabled()) { + log.debug(sm.getString("mcastServiceImpl.error.stop"), e); + } } try { socket.close(); - } catch (Exception ignore) { - // NO-OP + } catch (Exception e) { + // Shutting down. Only log at debug. + if (log.isDebugEnabled()) { + log.debug(sm.getString("mcastServiceImpl.error.stop"), e); + } } member.setServiceStartTime(-1); } @@ -360,10 +371,11 @@ memberBroadcastsReceived(data); } } - } catch (SocketTimeoutException x) { - // do nothing, this is normal, we don't want to block forever - // since the receive thread is the same thread - // that does membership expiration + } catch (SocketTimeoutException ignore) { + /* + * Do nothing. This is normal. We don't want to block forever since the receive thread is the same thread + * that does membership expiration. + */ } checkExpired(); } @@ -472,8 +484,8 @@ } }; executor.execute(t); - } catch (Exception x) { - log.error(sm.getString("mcastServiceImpl.memberDisappeared.failed"), x); + } catch (Exception e) { + log.error(sm.getString("mcastServiceImpl.memberDisappeared.failed"), e); } } } @@ -565,14 +577,14 @@ if (log.isDebugEnabled()) { log.debug(sm.getString("mcastServiceImpl.invalidMemberPackage"), ax); } - } catch (Exception x) { + } catch (Exception e) { if (errorCounter == 0 && doRunReceiver) { - log.warn(sm.getString("mcastServiceImpl.error.receiving"), x); + log.warn(sm.getString("mcastServiceImpl.error.receiving"), e); } else if (log.isDebugEnabled()) { if (doRunReceiver) { - log.debug(sm.getString("mcastServiceImpl.error.receiving"), x); + log.debug(sm.getString("mcastServiceImpl.error.receiving"), e); } else { - log.warn(sm.getString("mcastServiceImpl.error.receivingNoSleep"), x); + log.debug(sm.getString("mcastServiceImpl.error.receivingNoSleep"), e); } } if (doRunReceiver) { @@ -611,11 +623,11 @@ try { send(true); errorCounter = 0; - } catch (Exception x) { + } catch (Exception e) { if (errorCounter == 0) { - log.warn(sm.getString("mcastServiceImpl.send.failed"), x); + log.warn(sm.getString("mcastServiceImpl.send.failed"), e); } else { - log.debug(sm.getString("mcastServiceImpl.send.failed"), x); + log.debug(sm.getString("mcastServiceImpl.send.failed"), e); } if ((++errorCounter) >= recoveryCounter) { errorCounter = 0; @@ -666,8 +678,8 @@ try { parent.stop(Channel.MBR_RX_SEQ | Channel.MBR_TX_SEQ); return true; - } catch (Exception x) { - log.warn(sm.getString("mcastServiceImpl.recovery.stopFailed"), x); + } catch (Exception e) { + log.warn(sm.getString("mcastServiceImpl.recovery.stopFailed"), e); return false; } } @@ -677,8 +689,8 @@ parent.init(); parent.start(Channel.MBR_RX_SEQ | Channel.MBR_TX_SEQ); return true; - } catch (Exception x) { - log.warn(sm.getString("mcastServiceImpl.recovery.startFailed"), x); + } catch (Exception e) { + log.warn(sm.getString("mcastServiceImpl.recovery.startFailed"), e); return false; } } diff -Nru tomcat10-10.1.40/java/org/apache/catalina/tribes/membership/Membership.java tomcat10-10.1.52/java/org/apache/catalina/tribes/membership/Membership.java --- tomcat10-10.1.40/java/org/apache/catalina/tribes/membership/Membership.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/tribes/membership/Membership.java 2026-01-23 19:33:36.000000000 +0000 @@ -27,8 +27,6 @@ * A membership implementation using simple multicast. This is the representation of a multicast membership. This * class is responsible for maintaining a list of active cluster nodes in the cluster. If a node fails to send out a * heartbeat, the node will be dismissed. - * - * @author Peter Rossbach */ public class Membership implements Cloneable { diff -Nru tomcat10-10.1.40/java/org/apache/catalina/tribes/membership/StaticMember.java tomcat10-10.1.52/java/org/apache/catalina/tribes/membership/StaticMember.java --- tomcat10-10.1.40/java/org/apache/catalina/tribes/membership/StaticMember.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/tribes/membership/StaticMember.java 2026-01-23 19:33:36.000000000 +0000 @@ -46,8 +46,8 @@ } else { try { setHostname(host); - } catch (IOException x) { - throw new RuntimeException(x); + } catch (IOException ioe) { + throw new RuntimeException(ioe); } } diff -Nru tomcat10-10.1.40/java/org/apache/catalina/tribes/membership/StaticMembershipProvider.java tomcat10-10.1.52/java/org/apache/catalina/tribes/membership/StaticMembershipProvider.java --- tomcat10-10.1.40/java/org/apache/catalina/tribes/membership/StaticMembershipProvider.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/tribes/membership/StaticMembershipProvider.java 2026-01-23 19:33:36.000000000 +0000 @@ -374,8 +374,8 @@ @Override public String toString() { - return "MemberMessage[" + "name=" + new String(membershipId) + "; type=" + - getTypeDesc() + "; member=" + member + ']'; + return "MemberMessage[" + "name=" + new String(membershipId) + "; type=" + getTypeDesc() + "; member=" + + member + ']'; } protected String getTypeDesc() { @@ -401,8 +401,8 @@ ping(); } catch (InterruptedException ix) { // Ignore - } catch (Exception x) { - log.warn(sm.getString("staticMembershipProvider.pingThread.failed"), x); + } catch (Exception e) { + log.warn(sm.getString("staticMembershipProvider.pingThread.failed"), e); } } } diff -Nru tomcat10-10.1.40/java/org/apache/catalina/tribes/membership/StaticMembershipService.java tomcat10-10.1.52/java/org/apache/catalina/tribes/membership/StaticMembershipService.java --- tomcat10-10.1.40/java/org/apache/catalina/tribes/membership/StaticMembershipService.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/tribes/membership/StaticMembershipService.java 2026-01-23 19:33:36.000000000 +0000 @@ -115,8 +115,8 @@ localMember.setSecurePort(securePort); localMember.setUdpPort(udpPort); localMember.getData(true, true); - } catch (IOException x) { - throw new IllegalArgumentException(x); + } catch (IOException ioe) { + throw new IllegalArgumentException(ioe); } } diff -Nru tomcat10-10.1.40/java/org/apache/catalina/tribes/membership/cloud/CertificateStreamProvider.java tomcat10-10.1.52/java/org/apache/catalina/tribes/membership/cloud/CertificateStreamProvider.java --- tomcat10-10.1.40/java/org/apache/catalina/tribes/membership/cloud/CertificateStreamProvider.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/tribes/membership/cloud/CertificateStreamProvider.java 2026-01-23 19:33:36.000000000 +0000 @@ -76,9 +76,9 @@ keyManagerFactory.init(keyStore, clientKeyPassword); return keyManagerFactory.getKeyManagers(); - } catch (IOException e) { + } catch (IOException ioe) { log.error(sm.getString("certificateStream.clientCertError", clientCertFile, clientKeyFile)); - throw e; + throw ioe; } } diff -Nru tomcat10-10.1.40/java/org/apache/catalina/tribes/membership/cloud/CloudMembershipService.java tomcat10-10.1.52/java/org/apache/catalina/tribes/membership/cloud/CloudMembershipService.java --- tomcat10-10.1.40/java/org/apache/catalina/tribes/membership/cloud/CloudMembershipService.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/tribes/membership/cloud/CloudMembershipService.java 2026-01-23 19:33:36.000000000 +0000 @@ -200,8 +200,8 @@ localMember.setPayload(payload); localMember.setDomain(domain); localMember.getData(true, true); - } catch (IOException e) { - throw new IllegalArgumentException(e); + } catch (IOException ioe) { + throw new IllegalArgumentException(ioe); } } diff -Nru tomcat10-10.1.40/java/org/apache/catalina/tribes/membership/cloud/DNSMembershipProvider.java tomcat10-10.1.52/java/org/apache/catalina/tribes/membership/cloud/DNSMembershipProvider.java --- tomcat10-10.1.40/java/org/apache/catalina/tribes/membership/cloud/DNSMembershipProvider.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/tribes/membership/cloud/DNSMembershipProvider.java 2026-01-23 19:33:36.000000000 +0000 @@ -165,8 +165,8 @@ MemberImpl member; try { member = new MemberImpl(ip, port, aliveTime); - } catch (IOException e) { - log.error(sm.getString("kubernetesMembershipProvider.memberError"), e); + } catch (IOException ioe) { + log.error(sm.getString("kubernetesMembershipProvider.memberError"), ioe); continue; } member.setUniqueId(id); diff -Nru tomcat10-10.1.40/java/org/apache/catalina/tribes/membership/cloud/KubernetesMembershipProvider.java tomcat10-10.1.52/java/org/apache/catalina/tribes/membership/cloud/KubernetesMembershipProvider.java --- tomcat10-10.1.40/java/org/apache/catalina/tribes/membership/cloud/KubernetesMembershipProvider.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/tribes/membership/cloud/KubernetesMembershipProvider.java 2026-01-23 19:33:36.000000000 +0000 @@ -91,8 +91,8 @@ byte[] bytes = Files.readAllBytes(saTokenPath); streamProvider = new TokenStreamProvider(new String(bytes, StandardCharsets.US_ASCII), caCertFile); saTokenLastModifiedTime = Files.getLastModifiedTime(saTokenPath); - } catch (IOException e) { - log.error(sm.getString("kubernetesMembershipProvider.streamError"), e); + } catch (IOException ioe) { + log.error(sm.getString("kubernetesMembershipProvider.streamError"), ioe); } } else { if (protocol == null) { @@ -155,8 +155,8 @@ try (InputStream stream = streamProvider.openStream(url, headers, connectionTimeout, readTimeout); InputStreamReader reader = new InputStreamReader(stream, StandardCharsets.UTF_8)) { parsePods(reader, members); - } catch (IOException e) { - log.error(sm.getString("kubernetesMembershipProvider.streamError"), e); + } catch (IOException ioe) { + log.error(sm.getString("kubernetesMembershipProvider.streamError"), ioe); } return members.toArray(new Member[0]); @@ -179,10 +179,10 @@ // Use != to protect against clock issues if (!saTokenLastModifiedTime.equals(oldSaTokenLastModifiedTime)) { byte[] bytes = Files.readAllBytes(saTokenPath); - ((TokenStreamProvider)streamProvider).setToken(new String(bytes, StandardCharsets.US_ASCII)); + ((TokenStreamProvider) streamProvider).setToken(new String(bytes, StandardCharsets.US_ASCII)); } - } catch (IOException e) { - log.error(sm.getString("kubernetesMembershipProvider.streamError"), e); + } catch (IOException ioe) { + log.error(sm.getString("kubernetesMembershipProvider.streamError"), ioe); } } @@ -263,10 +263,10 @@ MemberImpl member; try { member = new MemberImpl(podIP, port, aliveTime); - } catch (IOException e) { + } catch (IOException ioe) { // Shouldn't happen: // an exception is thrown if hostname can't be resolved to IP, but we already provide an IP - log.error(sm.getString("kubernetesMembershipProvider.memberError"), e); + log.error(sm.getString("kubernetesMembershipProvider.memberError"), ioe); continue; } byte[] id = md5.digest(uid.getBytes(StandardCharsets.US_ASCII)); diff -Nru tomcat10-10.1.40/java/org/apache/catalina/tribes/membership/cloud/TokenStreamProvider.java tomcat10-10.1.52/java/org/apache/catalina/tribes/membership/cloud/TokenStreamProvider.java --- tomcat10-10.1.40/java/org/apache/catalina/tribes/membership/cloud/TokenStreamProvider.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/tribes/membership/cloud/TokenStreamProvider.java 2026-01-23 19:33:36.000000000 +0000 @@ -59,9 +59,9 @@ } try { return super.openStream(url, headers, connectTimeout, readTimeout); - } catch (IOException e) { + } catch (IOException ioe) { // Add debug information - throw new IOException(sm.getString("tokenStream.failedConnection", url, token), e); + throw new IOException(sm.getString("tokenStream.failedConnection", url, token), ioe); } } } \ No newline at end of file diff -Nru tomcat10-10.1.40/java/org/apache/catalina/tribes/tipis/AbstractReplicatedMap.java tomcat10-10.1.52/java/org/apache/catalina/tribes/tipis/AbstractReplicatedMap.java --- tomcat10-10.1.40/java/org/apache/catalina/tribes/tipis/AbstractReplicatedMap.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/tribes/tipis/AbstractReplicatedMap.java 2026-01-23 19:33:36.000000000 +0000 @@ -170,7 +170,7 @@ * @param terminate - Flag for whether to terminate this map that failed to start. */ public AbstractReplicatedMap(MapOwner owner, Channel channel, long timeout, String mapContextName, - int initialCapacity, float loadFactor, int channelSendOptions, ClassLoader[] cls, boolean terminate) { + int initialCapacity, float loadFactor, int channelSendOptions, ClassLoader[] cls, boolean terminate) { innerMap = new ConcurrentHashMap<>(initialCapacity, loadFactor, 15); init(owner, channel, mapContextName, timeout, channelSendOptions, cls, terminate); @@ -204,7 +204,7 @@ * @param terminate - Flag for whether to terminate this map that failed to start. */ protected void init(MapOwner owner, Channel channel, String mapContextName, long timeout, int channelSendOptions, - ClassLoader[] cls, boolean terminate) { + ClassLoader[] cls, boolean terminate) { long start = System.currentTimeMillis(); if (log.isInfoEnabled()) { log.info(sm.getString("abstractReplicatedMap.init.start", mapContextName)); @@ -238,10 +238,13 @@ // state is transferred, we are ready for messaging broadcast(MapMessage.MSG_START, true); } catch (ChannelException x) { - log.warn(sm.getString("abstractReplicatedMap.unableSend.startMessage")); if (terminate) { + // Exception is logged further up stack + log.warn(sm.getString("abstractReplicatedMap.unableSend.startMessage")); breakdown(); throw new RuntimeException(sm.getString("abstractReplicatedMap.unableStart"), x); + } else { + log.warn(sm.getString("abstractReplicatedMap.unableSend.startMessage"), x); } } this.state = State.INITIALIZED; @@ -369,6 +372,7 @@ try { broadcast(MapMessage.MSG_STOP, false); } catch (Exception ignore) { + // Ignore } // cleanup this.channel.removeChannelListener(this); @@ -475,8 +479,8 @@ msg = new MapMessage(mapContextName, getReplicateMessageType(), true, (Serializable) entry.getKey(), null, rentry.getDiff(), entry.getPrimary(), entry.getBackupNodes()); rentry.resetDiff(); - } catch (IOException x) { - log.error(sm.getString("abstractReplicatedMap.unable.diffObject"), x); + } catch (IOException ioe) { + log.error(sm.getString("abstractReplicatedMap.unable.diffObject"), ioe); } finally { rentry.unlock(); } @@ -715,8 +719,8 @@ diff.lock(); try { diff.applyDiff(mapmsg.getDiffValue(), 0, mapmsg.getDiffValue().length); - } catch (Exception x) { - log.error(sm.getString("abstractReplicatedMap.unableApply.diff", entry.getKey()), x); + } catch (Exception e) { + log.error(sm.getString("abstractReplicatedMap.unableApply.diff", entry.getKey()), e); } finally { diff.unlock(); } @@ -982,8 +986,8 @@ if (this.state.isAvailable()) { ping(accessTimeout); } - } catch (Exception x) { - log.error(sm.getString("abstractReplicatedMap.heartbeat.failed"), x); + } catch (Exception e) { + log.error(sm.getString("abstractReplicatedMap.heartbeat.failed"), e); } } @@ -1257,7 +1261,7 @@ int counter = 0; for (Entry e : innerMap.entrySet()) { if (e != null) { - MapEntry entry = innerMap.get(e.getKey()); + MapEntry entry = innerMap.get(e.getKey()); if (entry != null && entry.isActive() && entry.getValue() != null) { counter++; } @@ -1431,11 +1435,8 @@ @Override public String toString() { - return "MapEntry[key:" + getKey() + "; " + - "value:" + getValue() + "; " + - "primary:" + isPrimary() + "; " + - "backup:" + isBackup() + "; " + - "proxy:" + isProxy() + ";]"; + return "MapEntry[key:" + getKey() + "; " + "value:" + getValue() + "; " + "primary:" + isPrimary() + "; " + + "backup:" + isBackup() + "; " + "proxy:" + isProxy() + ";]"; } } @@ -1473,8 +1474,8 @@ @Override public String toString() { - return "MapMessage[context=" + new String(mapId) + "; type=" + getTypeDesc() + - "; key=" + key + "; value=" + value + ']'; + return "MapMessage[context=" + new String(mapId) + "; type=" + getTypeDesc() + "; key=" + key + "; value=" + + value + ']'; } public String getTypeDesc() { @@ -1511,7 +1512,7 @@ } public MapMessage(byte[] mapId, int msgtype, boolean diff, Serializable key, Serializable value, - byte[] diffvalue, Member primary, Member[] nodes) { + byte[] diffvalue, Member primary, Member[] nodes) { this.mapId = mapId; this.msgtype = msgtype; this.diff = diff; @@ -1540,8 +1541,8 @@ public Serializable getKey() { try { return key(null); - } catch (Exception x) { - throw new RuntimeException(sm.getString("mapMessage.deserialize.error.key"), x); + } catch (Exception e) { + throw new RuntimeException(sm.getString("mapMessage.deserialize.error.key"), e); } } @@ -1564,8 +1565,8 @@ public Serializable getValue() { try { return value(null); - } catch (Exception x) { - throw new RuntimeException(sm.getString("mapMessage.deserialize.error.value"), x); + } catch (Exception e) { + throw new RuntimeException(sm.getString("mapMessage.deserialize.error.value"), e); } } @@ -1611,8 +1612,8 @@ valuedata = XByteBuffer.serialize(value); } this.value = value; - } catch (IOException x) { - throw new RuntimeException(x); + } catch (IOException ioe) { + throw new RuntimeException(ioe); } } @@ -1622,8 +1623,8 @@ keydata = XByteBuffer.serialize(key); } this.key = key; - } catch (IOException x) { - throw new RuntimeException(x); + } catch (IOException ioe) { + throw new RuntimeException(ioe); } } diff -Nru tomcat10-10.1.40/java/org/apache/catalina/tribes/transport/Constants.java tomcat10-10.1.52/java/org/apache/catalina/tribes/transport/Constants.java --- tomcat10-10.1.40/java/org/apache/catalina/tribes/transport/Constants.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/tribes/transport/Constants.java 2026-01-23 19:33:36.000000000 +0000 @@ -20,8 +20,6 @@ /** * Manifest constants for the org.apache.catalina.tribes.transport package. - * - * @author Peter Rossbach */ public class Constants { diff -Nru tomcat10-10.1.40/java/org/apache/catalina/tribes/transport/ReceiverBase.java tomcat10-10.1.52/java/org/apache/catalina/tribes/transport/ReceiverBase.java --- tomcat10-10.1.40/java/org/apache/catalina/tribes/transport/ReceiverBase.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/tribes/transport/ReceiverBase.java 2026-01-23 19:33:36.000000000 +0000 @@ -200,11 +200,11 @@ setPort(port); log.info(sm.getString("receiverBase.socket.bind", addr)); retries = 0; - } catch (IOException x) { + } catch (IOException ioe) { retries--; if (retries <= 0) { log.info(sm.getString("receiverBase.unable.bind", addr)); - throw x; + throw ioe; } port++; } @@ -232,11 +232,11 @@ setUdpPort(portstart); log.info(sm.getString("receiverBase.udp.bind", addr)); return 0; - } catch (IOException x) { + } catch (IOException ioe) { retries--; if (retries <= 0) { log.info(sm.getString("receiverBase.unable.bind.udp", addr)); - throw x; + throw ioe; } portstart++; try { diff -Nru tomcat10-10.1.40/java/org/apache/catalina/tribes/transport/RxTaskPool.java tomcat10-10.1.52/java/org/apache/catalina/tribes/transport/RxTaskPool.java --- tomcat10-10.1.40/java/org/apache/catalina/tribes/transport/RxTaskPool.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/tribes/transport/RxTaskPool.java 2026-01-23 19:33:36.000000000 +0000 @@ -63,8 +63,8 @@ if (!idle.isEmpty()) { try { worker = idle.remove(0); - } catch (java.util.NoSuchElementException x) { - // this means that there are no available workers + } catch (java.util.NoSuchElementException ignore) { + // Should never happen as access to idle is always synchronized on mutex } } else if (used.size() < this.maxTasks && creator != null) { worker = creator.createRxTask(); diff -Nru tomcat10-10.1.40/java/org/apache/catalina/tribes/transport/nio/NioReceiver.java tomcat10-10.1.52/java/org/apache/catalina/tribes/transport/nio/NioReceiver.java --- tomcat10-10.1.40/java/org/apache/catalina/tribes/transport/nio/NioReceiver.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/tribes/transport/nio/NioReceiver.java 2026-01-23 19:33:36.000000000 +0000 @@ -72,12 +72,12 @@ super.start(); try { setPool(new RxTaskPool(getMaxThreads(), getMinThreads(), this)); - } catch (Exception x) { - log.fatal(sm.getString("nioReceiver.threadpool.fail"), x); - if (x instanceof IOException) { - throw (IOException) x; + } catch (Exception e) { + log.fatal(sm.getString("nioReceiver.threadpool.fail"), e); + if (e instanceof IOException) { + throw (IOException) e; } else { - throw new IOException(x.getMessage()); + throw new IOException(e.getMessage()); } } try { @@ -90,12 +90,12 @@ Thread t = new Thread(this, "NioReceiver" + channelName); t.setDaemon(true); t.start(); - } catch (Exception x) { - log.fatal(sm.getString("nioReceiver.start.fail"), x); - if (x instanceof IOException) { - throw (IOException) x; + } catch (Exception e) { + log.fatal(sm.getString("nioReceiver.start.fail"), e); + if (e instanceof IOException) { + throw (IOException) e; } else { - throw new IOException(x.getMessage()); + throw new IOException(e.getMessage()); } } } @@ -128,13 +128,13 @@ // set up the datagram channel if (this.getUdpPort() > 0) { datagramChannel = DatagramChannel.open(); - configureDatagraChannel(); + configureDatagramChannel(); // bind to the address to avoid security checks bindUdp(datagramChannel.socket(), getUdpPort(), getAutoBind()); } } - private void configureDatagraChannel() throws IOException { + private void configureDatagramChannel() throws IOException { datagramChannel.configureBlocking(false); datagramChannel.socket().setSendBufferSize(getUdpTxBufSize()); datagramChannel.socket().setReceiveBufferSize(getUdpRxBufSize()); @@ -167,8 +167,8 @@ log.trace("Processing event in selector:" + r); } r.run(); - } catch (Exception x) { - log.error(sm.getString("nioReceiver.eventsError"), x); + } catch (Exception e) { + log.error(sm.getString("nioReceiver.eventsError"), e); } } } @@ -184,9 +184,9 @@ if (key.channel() instanceof SocketChannel) { try { ((SocketChannel) key.channel()).socket().close(); - } catch (IOException e) { + } catch (IOException ioe) { if (log.isDebugEnabled()) { - log.debug(sm.getString("nioReceiver.closeError"), e); + log.debug(sm.getString("nioReceiver.closeError"), ioe); } } } @@ -201,9 +201,9 @@ } try { key.channel().close(); - } catch (IOException e) { + } catch (IOException ioe) { if (log.isDebugEnabled()) { - log.debug(sm.getString("nioReceiver.closeError"), e); + log.debug(sm.getString("nioReceiver.closeError"), ioe); } } @@ -344,9 +344,9 @@ if (datagramChannel != null) { try { datagramChannel.close(); - } catch (Exception iox) { + } catch (Exception e) { if (log.isDebugEnabled()) { - log.debug(sm.getString("nioReceiver.closeError"), iox); + log.debug(sm.getString("nioReceiver.closeError"), e); } } datagramChannel = null; @@ -377,8 +377,8 @@ log.warn(sm.getString("nioReceiver.stop.threadRunning")); } closeSelector(); - } catch (Exception x) { - log.error(sm.getString("nioReceiver.stop.fail"), x); + } catch (Exception e) { + log.error(sm.getString("nioReceiver.stop.fail"), e); } finally { this.selector.set(null); } @@ -397,9 +397,9 @@ key.attach(null); key.cancel(); } - } catch (IOException e) { + } catch (IOException ioe) { if (log.isWarnEnabled()) { - log.warn(sm.getString("nioReceiver.cleanup.fail"), e); + log.warn(sm.getString("nioReceiver.cleanup.fail"), ioe); } } catch (ClosedSelectorException ignore) { // Ignore @@ -444,8 +444,8 @@ running = true; try { listen(); - } catch (Exception x) { - log.error(sm.getString("nioReceiver.run.fail"), x); + } catch (Exception e) { + log.error(sm.getString("nioReceiver.run.fail"), e); } finally { running = false; } diff -Nru tomcat10-10.1.40/java/org/apache/catalina/tribes/transport/nio/NioReplicationTask.java tomcat10-10.1.52/java/org/apache/catalina/tribes/transport/nio/NioReplicationTask.java --- tomcat10-10.1.40/java/org/apache/catalina/tribes/transport/nio/NioReplicationTask.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/tribes/transport/nio/NioReplicationTask.java 2026-01-23 19:33:36.000000000 +0000 @@ -214,7 +214,8 @@ try { Logs.MESSAGES.trace("NioReplicationThread - Received msg:" + new UniqueId(msg.getUniqueId()) + " at " + new java.sql.Timestamp(System.currentTimeMillis())); - } catch (Throwable t) { + } catch (Throwable ignore) { + // Ignore } } // process the message @@ -228,7 +229,7 @@ } } catch (RemoteProcessException e) { if (log.isDebugEnabled()) { - log.error(sm.getString("nioReplicationTask.process.clusterMsg.failed"), e); + log.debug(sm.getString("nioReplicationTask.process.clusterMsg.failed"), e); } if (ChannelData.sendAckSync(msg.getOptions())) { sendAck(key, (WritableByteChannel) channel, Constants.FAIL_ACK_COMMAND, saddr); @@ -280,8 +281,8 @@ log.trace("CKX Cancelling key:" + key); } - } catch (Exception x) { - log.error(sm.getString("nioReplicationTask.error.register.key", key), x); + } catch (Exception e) { + log.error(sm.getString("nioReplicationTask.error.register.key", key), e); } }; receiver.addEvent(r); @@ -339,8 +340,12 @@ ((channel instanceof SocketChannel) ? ((SocketChannel) channel).socket().getInetAddress() : ((DatagramChannel) channel).socket().getInetAddress())); } - } catch (IOException x) { - log.warn(sm.getString("nioReplicationTask.unable.ack", x.getMessage())); + } catch (IOException ioe) { + if (log.isDebugEnabled()) { + log.debug(sm.getString("nioReplicationTask.unable.ack", ioe.getMessage()), ioe); + } else { + log.warn(sm.getString("nioReplicationTask.unable.ack", ioe.getMessage())); + } } } diff -Nru tomcat10-10.1.40/java/org/apache/catalina/tribes/transport/nio/NioSender.java tomcat10-10.1.52/java/org/apache/catalina/tribes/transport/nio/NioSender.java --- tomcat10-10.1.40/java/org/apache/catalina/tribes/transport/nio/NioSender.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/tribes/transport/nio/NioSender.java 2026-01-23 19:33:36.000000000 +0000 @@ -33,8 +33,8 @@ import org.apache.juli.logging.LogFactory; /** - * This class is NOT thread safe and should never be used with more than one thread at a time This is a state machine, - * handled by the process method States are: + * This class is NOT thread safe and should never be used with more than one thread at a time. This is a state machine, + * handled by the process method. States are: *
          *
        • NOT_CONNECTED -> connect() -> CONNECTED
        • *
        • CONNECTED -> setMessage() -> READY TO WRITE
        • @@ -42,6 +42,7 @@ *
        • READY_TO_READ -> read() -> READY_TO_READ | TRANSFER_COMPLETE
        • *
        • TRANSFER_COMPLETE -> CONNECTED
        • *
        + * Thread-safety / synchronisation is managed by ParallelNioSender */ public class NioSender extends AbstractSender { @@ -220,7 +221,7 @@ } @Override - public synchronized void connect() throws IOException { + public void connect() throws IOException { if (connecting || isConnected()) { return; } @@ -276,13 +277,13 @@ try { try { socketChannel.socket().close(); - } catch (Exception x) { + } catch (Exception e) { // Ignore } // error free close, all the way try { socketChannel.close(); - } catch (Exception x) { + } catch (Exception e) { // Ignore } } finally { @@ -293,23 +294,23 @@ try { try { dataChannel.socket().close(); - } catch (Exception x) { + } catch (Exception e) { // Ignore } // error free close, all the way try { dataChannel.close(); - } catch (Exception x) { + } catch (Exception e) { // Ignore } } finally { dataChannel = null; } } - } catch (Exception x) { - log.error(sm.getString("nioSender.unable.disconnect", x.getMessage())); + } catch (Exception e) { + log.error(sm.getString("nioSender.unable.disconnect", e.getMessage())); if (log.isDebugEnabled()) { - log.debug(sm.getString("nioSender.unable.disconnect", x.getMessage()), x); + log.debug(sm.getString("nioSender.unable.disconnect", e.getMessage()), e); } } } @@ -357,28 +358,26 @@ public void setMessage(byte[] data, int offset, int length) throws IOException { if (data != null) { - synchronized (this) { - current = data; - remaining = length; - ackbuf.clear(); - if (writebuf != null) { - writebuf.clear(); - } else { - writebuf = getBuffer(length); - } - if (writebuf.capacity() < length) { - writebuf = getBuffer(length); - } + current = data; + remaining = length; + ackbuf.clear(); + if (writebuf != null) { + writebuf.clear(); + } else { + writebuf = getBuffer(length); + } + if (writebuf.capacity() < length) { + writebuf = getBuffer(length); + } - // TODO use ByteBuffer.wrap to avoid copying the data. - writebuf.put(data, offset, length); - writebuf.flip(); - if (isConnected()) { - if (isUdpBased()) { - dataChannel.register(getSelector(), SelectionKey.OP_WRITE, this); - } else { - socketChannel.register(getSelector(), SelectionKey.OP_WRITE, this); - } + // TODO use ByteBuffer.wrap to avoid copying the data. + writebuf.put(data, offset, length); + writebuf.flip(); + if (isConnected()) { + if (isUdpBased()) { + dataChannel.register(getSelector(), SelectionKey.OP_WRITE, this); + } else { + socketChannel.register(getSelector(), SelectionKey.OP_WRITE, this); } } } diff -Nru tomcat10-10.1.40/java/org/apache/catalina/tribes/transport/nio/ParallelNioSender.java tomcat10-10.1.52/java/org/apache/catalina/tribes/transport/nio/ParallelNioSender.java --- tomcat10-10.1.40/java/org/apache/catalina/tribes/transport/nio/ParallelNioSender.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/tribes/transport/nio/ParallelNioSender.java 2026-01-23 19:33:36.000000000 +0000 @@ -88,20 +88,20 @@ cx.addFaultyMember(result.getFailed().getFaultyMembers()); } } - } catch (Exception x) { + } catch (Exception e) { if (log.isTraceEnabled()) { - log.trace("Error sending message", x); + log.trace("Error sending message", e); } if (cx == null) { - if (x instanceof ChannelException) { - cx = (ChannelException) x; + if (e instanceof ChannelException) { + cx = (ChannelException) e; } else { - cx = new ChannelException(sm.getString("parallelNioSender.send.failed"), x); + cx = new ChannelException(sm.getString("parallelNioSender.send.failed"), e); } } for (NioSender sender : senders) { if (!sender.isComplete()) { - cx.addFaultyMember(sender.getDestination(), x); + cx.addFaultyMember(sender.getDestination(), e); } } throw cx; @@ -126,16 +126,16 @@ // there was an error throw cx; } - } catch (Exception x) { + } catch (Exception e) { try { this.disconnect(); - } catch (Exception e) { + } catch (Exception ignore) { // Ignore } - if (x instanceof ChannelException) { - throw (ChannelException) x; + if (e instanceof ChannelException) { + throw (ChannelException) e; } else { - throw new ChannelException(x); + throw new ChannelException(e); } } @@ -173,9 +173,9 @@ } SenderState.getSenderState(sender.getDestination()).setReady(); } // end if - } catch (Exception x) { + } catch (Exception e) { if (log.isTraceEnabled()) { - log.trace("Error while processing send to " + sender.getDestination().getName(), x); + log.trace("Error while processing send to " + sender.getDestination().getName(), e); } SenderState state = SenderState.getSenderState(sender.getDestination()); int attempt = sender.getAttempt() + 1; @@ -192,7 +192,7 @@ log.warn(sm.getString("parallelNioSender.send.fail.retrying", sender.getDestination().getName())); } else { - log.warn(sm.getString("parallelNioSender.send.fail", sender.getDestination().getName()), x); + log.warn(sm.getString("parallelNioSender.send.fail", sender.getDestination().getName()), e); } } } @@ -200,8 +200,8 @@ log.warn(sm.getString("parallelNioSender.sender.disconnected.notRetry", sender.getDestination().getName())); ChannelException cx = - new ChannelException(sm.getString("parallelNioSender.sender.disconnected.sendFailed"), x); - cx.addFaultyMember(sender.getDestination(), x); + new ChannelException(sm.getString("parallelNioSender.sender.disconnected.sendFailed"), e); + cx.addFaultyMember(sender.getDestination(), e); result.failed(cx); break; } @@ -218,8 +218,8 @@ } } else { ChannelException cx = new ChannelException(sm.getString("parallelNioSender.sendFailed.attempt", - Integer.toString(sender.getAttempt()), Integer.toString(maxAttempts)), x); - cx.addFaultyMember(sender.getDestination(), x); + Integer.toString(sender.getAttempt()), Integer.toString(maxAttempts)), e); + cx.addFaultyMember(sender.getDestination(), e); result.failed(cx); } // end if } @@ -366,7 +366,7 @@ setConnected(false); try { close(); - } catch (Exception x) { + } catch (Exception ignore) { // Ignore } } @@ -384,14 +384,14 @@ } else { try { sender.read(); - } catch (IOException x) { + } catch (IOException ioe) { sender.disconnect(); sender.reset(); // nioSenders.remove(entry.getKey()); i.remove(); result = true; - } catch (Exception x) { - log.warn(sm.getString("parallelNioSender.error.keepalive", sender), x); + } catch (Exception e) { + log.warn(sm.getString("parallelNioSender.error.keepalive", sender), e); } } } @@ -399,8 +399,9 @@ if (result) { try { state.selector.selectNow(); - } catch (Exception e) { - /* Ignore */} + } catch (Exception ignore) { + // Ignore + } } return result; } @@ -422,7 +423,7 @@ NioSender nioSender = iter.next(); try { nioSender.disconnect(); - } catch (Exception e) { + } catch (Exception ignore) { // Ignore } iter.remove(); diff -Nru tomcat10-10.1.40/java/org/apache/catalina/tribes/transport/nio/PooledParallelSender.java tomcat10-10.1.52/java/org/apache/catalina/tribes/transport/nio/PooledParallelSender.java --- tomcat10-10.1.40/java/org/apache/catalina/tribes/transport/nio/PooledParallelSender.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/tribes/transport/nio/PooledParallelSender.java 2026-01-23 19:33:36.000000000 +0000 @@ -64,8 +64,8 @@ ParallelNioSender sender = new ParallelNioSender(); transferProperties(this, sender); return sender; - } catch (IOException x) { - throw new RuntimeException(sm.getString("pooledParallelSender.unable.open"), x); + } catch (IOException ioe) { + throw new RuntimeException(sm.getString("pooledParallelSender.unable.open"), ioe); } } } \ No newline at end of file diff -Nru tomcat10-10.1.40/java/org/apache/catalina/tribes/util/LocalStrings_ru.properties tomcat10-10.1.52/java/org/apache/catalina/tribes/util/LocalStrings_ru.properties --- tomcat10-10.1.40/java/org/apache/catalina/tribes/util/LocalStrings_ru.properties 1970-01-01 00:00:00.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/tribes/util/LocalStrings_ru.properties 2026-01-23 19:33:36.000000000 +0000 @@ -0,0 +1,19 @@ +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# Do not edit this file directly. +# To edit translations see: https://tomcat.apache.org/getinvolved.html#Translations + +arrays.length.outOfBounds=Недостаточно элементов данных в ключе, длина вне границ. diff -Nru tomcat10-10.1.40/java/org/apache/catalina/tribes/util/StringManager.java tomcat10-10.1.52/java/org/apache/catalina/tribes/util/StringManager.java --- tomcat10-10.1.40/java/org/apache/catalina/tribes/util/StringManager.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/tribes/util/StringManager.java 2026-01-23 19:33:36.000000000 +0000 @@ -39,10 +39,6 @@ *

        * Please see the documentation for java.util.ResourceBundle for more information. * - * @author James Duncan Davidson [duncan@eng.sun.com] - * @author James Todd [gonzo@eng.sun.com] - * @author Mel Martinez [mmartinez@g1440.com] - * * @see java.util.ResourceBundle */ public class StringManager { @@ -68,14 +64,15 @@ try { bnd = ResourceBundle.getBundle(bundleName, locale); } catch (MissingResourceException ex) { - // Try from the current loader (that's the case for trusted apps) - // Should only be required if using a TC5 style classloader structure - // where common != shared != server + /* + * Try from the current loader (that's the case for trusted apps). Should only be required if using a class + * loader structure where common != shared != server + */ ClassLoader cl = Thread.currentThread().getContextClassLoader(); if (cl != null) { try { bnd = ResourceBundle.getBundle(bundleName, locale, cl); - } catch (MissingResourceException ex2) { + } catch (MissingResourceException ignore) { // Ignore } } @@ -106,8 +103,7 @@ */ public String getString(String key) { if (key == null) { - String msg = "key may not have a null value"; - throw new IllegalArgumentException(msg); + throw new IllegalArgumentException("key may not have a null value"); } String str = null; @@ -117,7 +113,7 @@ if (bundle != null) { str = bundle.getString(key); } - } catch (MissingResourceException mre) { + } catch (MissingResourceException ignore) { // bad: shouldn't mask an exception the following way: // str = "[cannot find message associated with key '" + key + // "' due to " + mre + "]"; diff -Nru tomcat10-10.1.40/java/org/apache/catalina/users/AbstractGroup.java tomcat10-10.1.52/java/org/apache/catalina/users/AbstractGroup.java --- tomcat10-10.1.40/java/org/apache/catalina/users/AbstractGroup.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/users/AbstractGroup.java 2026-01-23 19:33:36.000000000 +0000 @@ -25,8 +25,6 @@ * Convenience base class for {@link Group} implementations. *

        * - * @author Craig R. McClanahan - * * @since 4.1 */ public abstract class AbstractGroup implements Group { diff -Nru tomcat10-10.1.40/java/org/apache/catalina/users/AbstractRole.java tomcat10-10.1.52/java/org/apache/catalina/users/AbstractRole.java --- tomcat10-10.1.40/java/org/apache/catalina/users/AbstractRole.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/users/AbstractRole.java 2026-01-23 19:33:36.000000000 +0000 @@ -25,8 +25,6 @@ * Convenience base class for {@link Role} implementations. *

        * - * @author Craig R. McClanahan - * * @since 4.1 */ public abstract class AbstractRole implements Role { diff -Nru tomcat10-10.1.40/java/org/apache/catalina/users/AbstractUser.java tomcat10-10.1.52/java/org/apache/catalina/users/AbstractUser.java --- tomcat10-10.1.40/java/org/apache/catalina/users/AbstractUser.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/users/AbstractUser.java 2026-01-23 19:33:36.000000000 +0000 @@ -25,8 +25,6 @@ * Convenience base class for {@link User} implementations. *

        * - * @author Craig R. McClanahan - * * @since 4.1 */ public abstract class AbstractUser implements User { diff -Nru tomcat10-10.1.40/java/org/apache/catalina/users/Constants.java tomcat10-10.1.52/java/org/apache/catalina/users/Constants.java --- tomcat10-10.1.40/java/org/apache/catalina/users/Constants.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/users/Constants.java 2026-01-23 19:33:36.000000000 +0000 @@ -20,8 +20,6 @@ /** * Manifest constants for this Java package. * - * @author Craig R. McClanahan - * * @since 4.1 */ public final class Constants { diff -Nru tomcat10-10.1.40/java/org/apache/catalina/users/DataSourceUserDatabaseFactory.java tomcat10-10.1.52/java/org/apache/catalina/users/DataSourceUserDatabaseFactory.java --- tomcat10-10.1.40/java/org/apache/catalina/users/DataSourceUserDatabaseFactory.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/users/DataSourceUserDatabaseFactory.java 2026-01-23 19:33:36.000000000 +0000 @@ -40,8 +40,6 @@ *
      • dataSourceName - JNDI name of the DataSource, which must be located in the same Context * environment as the UserDatabase
      • *
      - * - * @author Craig R. McClanahan */ public class DataSourceUserDatabaseFactory implements ObjectFactory { diff -Nru tomcat10-10.1.40/java/org/apache/catalina/users/GenericGroup.java tomcat10-10.1.52/java/org/apache/catalina/users/GenericGroup.java --- tomcat10-10.1.40/java/org/apache/catalina/users/GenericGroup.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/users/GenericGroup.java 2026-01-23 19:33:36.000000000 +0000 @@ -33,8 +33,6 @@ *

      * * @param The specific type of UserDase with which this group is associated - * - * @author Craig R. McClanahan */ public class GenericGroup extends AbstractGroup { diff -Nru tomcat10-10.1.40/java/org/apache/catalina/users/GenericRole.java tomcat10-10.1.52/java/org/apache/catalina/users/GenericRole.java --- tomcat10-10.1.40/java/org/apache/catalina/users/GenericRole.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/users/GenericRole.java 2026-01-23 19:33:36.000000000 +0000 @@ -26,8 +26,6 @@ *

      * * @param The specific type of UserDase with which this role is associated - * - * @author Craig R. McClanahan */ public class GenericRole extends AbstractRole { diff -Nru tomcat10-10.1.40/java/org/apache/catalina/users/GenericUser.java tomcat10-10.1.52/java/org/apache/catalina/users/GenericUser.java --- tomcat10-10.1.40/java/org/apache/catalina/users/GenericUser.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/users/GenericUser.java 2026-01-23 19:33:36.000000000 +0000 @@ -31,8 +31,6 @@ *

      * * @param The specific type of UserDase with which this role is associated - * - * @author Craig R. McClanahan */ public class GenericUser extends AbstractUser { diff -Nru tomcat10-10.1.40/java/org/apache/catalina/users/MemoryGroup.java tomcat10-10.1.52/java/org/apache/catalina/users/MemoryGroup.java --- tomcat10-10.1.40/java/org/apache/catalina/users/MemoryGroup.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/users/MemoryGroup.java 2026-01-23 19:33:36.000000000 +0000 @@ -27,8 +27,6 @@ * {@link UserDatabase}. *

      * - * @author Craig R. McClanahan - * * @since 4.1 * * @deprecated Use {@link GenericGroup} instead. diff -Nru tomcat10-10.1.40/java/org/apache/catalina/users/MemoryRole.java tomcat10-10.1.52/java/org/apache/catalina/users/MemoryRole.java --- tomcat10-10.1.40/java/org/apache/catalina/users/MemoryRole.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/users/MemoryRole.java 2026-01-23 19:33:36.000000000 +0000 @@ -26,8 +26,6 @@ * {@link UserDatabase}. *

      * - * @author Craig R. McClanahan - * * @since 4.1 * * @deprecated Use {@link GenericRole} instead. diff -Nru tomcat10-10.1.40/java/org/apache/catalina/users/MemoryUser.java tomcat10-10.1.52/java/org/apache/catalina/users/MemoryUser.java --- tomcat10-10.1.40/java/org/apache/catalina/users/MemoryUser.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/users/MemoryUser.java 2026-01-23 19:33:36.000000000 +0000 @@ -27,8 +27,6 @@ * {@link UserDatabase}. *

      * - * @author Craig R. McClanahan - * * @since 4.1 * * @deprecated Use {@link GenericUser} instead. diff -Nru tomcat10-10.1.40/java/org/apache/catalina/users/MemoryUserDatabase.java tomcat10-10.1.52/java/org/apache/catalina/users/MemoryUserDatabase.java --- tomcat10-10.1.40/java/org/apache/catalina/users/MemoryUserDatabase.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/users/MemoryUserDatabase.java 2026-01-23 19:33:36.000000000 +0000 @@ -57,8 +57,6 @@ * This class does not enforce what, in an RDBMS, would be called referential integrity. Concurrent modifications may * result in inconsistent data such as a User retaining a reference to a Role that has been removed from the database. * - * @author Craig R. McClanahan - * * @since 4.1 */ /* @@ -481,10 +479,8 @@ // Print the file prolog writer.println(""); writer.println(""); // Print entries for each defined role, group, and user @@ -562,11 +558,11 @@ if (writer.checkError()) { throw new IOException(sm.getString("memoryUserDatabase.writeException", fileNew.getAbsolutePath())); } - } catch (IOException e) { + } catch (IOException ioe) { if (fileNew.exists() && !fileNew.delete()) { log.warn(sm.getString("memoryUserDatabase.fileDelete", fileNew)); } - throw e; + throw ioe; } this.lastModified = fileNew.lastModified(); } finally { @@ -632,8 +628,8 @@ writeLock.unlock(); } } - } catch (Exception ioe) { - log.error(sm.getString("memoryUserDatabase.reloadError", id, uri), ioe); + } catch (Exception e) { + log.error(sm.getString("memoryUserDatabase.reloadError", id, uri), e); } finally { if (uConn != null) { try { @@ -654,8 +650,8 @@ @Override public String toString() { - return "MemoryUserDatabase[id=" + this.id + ",pathname=" + pathname + ",groupCount=" + - this.groups.size() + ",roleCount=" + this.roles.size() + ",userCount=" + this.users.size() + ']'; + return "MemoryUserDatabase[id=" + this.id + ",pathname=" + pathname + ",groupCount=" + this.groups.size() + + ",roleCount=" + this.roles.size() + ",userCount=" + this.users.size() + ']'; } } diff -Nru tomcat10-10.1.40/java/org/apache/catalina/users/MemoryUserDatabaseFactory.java tomcat10-10.1.52/java/org/apache/catalina/users/MemoryUserDatabaseFactory.java --- tomcat10-10.1.40/java/org/apache/catalina/users/MemoryUserDatabaseFactory.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/users/MemoryUserDatabaseFactory.java 2026-01-23 19:33:36.000000000 +0000 @@ -41,8 +41,6 @@ * to which it is stored. [conf/tomcat-users.xml] *
    * - * @author Craig R. McClanahan - * * @since 4.1 */ public class MemoryUserDatabaseFactory implements ObjectFactory { diff -Nru tomcat10-10.1.40/java/org/apache/catalina/util/CharsetMapper.java tomcat10-10.1.52/java/org/apache/catalina/util/CharsetMapper.java --- tomcat10-10.1.40/java/org/apache/catalina/util/CharsetMapper.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/util/CharsetMapper.java 2026-01-23 19:33:36.000000000 +0000 @@ -30,8 +30,6 @@ * text (or generating output text) when the Content-Type header does not include one. You can customize the behavior of * this class by modifying the mapping data it loads, or by subclassing it (to change the algorithm) and then using your * own version for a particular web application. - * - * @author Craig R. McClanahan */ public class CharsetMapper { diff -Nru tomcat10-10.1.40/java/org/apache/catalina/util/CustomObjectInputStream.java tomcat10-10.1.52/java/org/apache/catalina/util/CustomObjectInputStream.java --- tomcat10-10.1.40/java/org/apache/catalina/util/CustomObjectInputStream.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/util/CustomObjectInputStream.java 2026-01-23 19:33:36.000000000 +0000 @@ -33,9 +33,6 @@ /** * Custom subclass of ObjectInputStream that loads from the class loader for this web application. This * allows classes defined only with the web application to be found correctly. - * - * @author Craig R. McClanahan - * @author Bip Thelin */ public final class CustomObjectInputStream extends ObjectInputStream { diff -Nru tomcat10-10.1.40/java/org/apache/catalina/util/FilterUtil.java tomcat10-10.1.52/java/org/apache/catalina/util/FilterUtil.java --- tomcat10-10.1.40/java/org/apache/catalina/util/FilterUtil.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/util/FilterUtil.java 2026-01-23 19:33:36.000000000 +0000 @@ -79,6 +79,11 @@ return false; } + /* + * Note: Order does not matter here in terms of specification compliance because this is Filter mapping. If any + * rule matches then this method returns true. Order would matter if this was Servlet mapping. + */ + // Case 1 - Exact Match if (testPath.equals(requestPath)) { return true; @@ -109,7 +114,12 @@ } } - // Case 4 - "Default" Match + // Case 4 - Context Root + if (testPath.isEmpty() && requestPath.equals("/")) { + return true; + } + + // Case 5 - "Default" Match return false; // NOTE - Not relevant for selecting filters } diff -Nru tomcat10-10.1.40/java/org/apache/catalina/util/IOTools.java tomcat10-10.1.52/java/org/apache/catalina/util/IOTools.java --- tomcat10-10.1.40/java/org/apache/catalina/util/IOTools.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/util/IOTools.java 2026-01-23 19:33:36.000000000 +0000 @@ -24,9 +24,7 @@ /** - * Contains commonly needed I/O-related methods - * - * @author Dan Sandberg + * Contains commonly needed I/O-related methods. */ public class IOTools { protected static final int DEFAULT_BUFFER_SIZE = 4 * 1024; // 4k diff -Nru tomcat10-10.1.40/java/org/apache/catalina/util/Introspection.java tomcat10-10.1.52/java/org/apache/catalina/util/Introspection.java --- tomcat10-10.1.40/java/org/apache/catalina/util/Introspection.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/util/Introspection.java 2026-01-23 19:33:36.000000000 +0000 @@ -60,7 +60,7 @@ */ public static boolean isValidSetter(Method method) { return method.getName().startsWith("set") && method.getName().length() > 3 && - method.getParameterTypes().length == 1 && method.getReturnType().getName().equals("void"); + method.getParameterTypes().length == 1 && method.getReturnType().getName().equals("void"); } /** diff -Nru tomcat10-10.1.40/java/org/apache/catalina/util/LifecycleBase.java tomcat10-10.1.52/java/org/apache/catalina/util/LifecycleBase.java --- tomcat10-10.1.40/java/org/apache/catalina/util/LifecycleBase.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/util/LifecycleBase.java 2026-01-23 19:33:36.000000000 +0000 @@ -184,8 +184,8 @@ /** * Subclasses must ensure that the state is changed to {@link LifecycleState#STARTING} during the execution of this * method. Changing state will trigger the {@link Lifecycle#START_EVENT} event. If a component fails to start it may - * either throw a {@link LifecycleException} which will cause it's parent to fail to start, or it can place itself in - * the error state in which case {@link #stop()} will be called on the failed component but the parent component + * either throw a {@link LifecycleException} which will cause it's parent to fail to start, or it can place itself + * in the error state in which case {@link #stop()} will be called on the failed component but the parent component * will continue to start normally. * * @throws LifecycleException Start error occurred @@ -392,22 +392,20 @@ private void invalidTransition(String type) throws LifecycleException { - String msg = sm.getString("lifecycleBase.invalidTransition", type, toString(), state); - throw new LifecycleException(msg); + throw new LifecycleException(sm.getString("lifecycleBase.invalidTransition", type, toString(), state)); } private void handleSubClassException(Throwable t, String key, Object... args) throws LifecycleException { setStateInternal(LifecycleState.FAILED, null, false); ExceptionUtils.handleThrowable(t); - String msg = sm.getString(key, args); if (getThrowOnFailure()) { if (!(t instanceof LifecycleException)) { - t = new LifecycleException(msg, t); + t = new LifecycleException(sm.getString(key, args), t); } throw (LifecycleException) t; } else { - log.error(msg, t); + log.error(sm.getString(key, args), t); } } } diff -Nru tomcat10-10.1.40/java/org/apache/catalina/util/ParameterMap.java tomcat10-10.1.52/java/org/apache/catalina/util/ParameterMap.java --- tomcat10-10.1.40/java/org/apache/catalina/util/ParameterMap.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/util/ParameterMap.java 2026-01-23 19:33:36.000000000 +0000 @@ -32,8 +32,6 @@ * * @param The type of Key * @param The type of Value - * - * @author Craig R. McClanahan */ public final class ParameterMap implements Map, Serializable { @@ -82,7 +80,12 @@ * @param map Map whose contents are duplicated in the new map */ public ParameterMap(Map map) { - delegatedMap = new LinkedHashMap<>(map); + // Unroll loop for performance - https://bz.apache.org/bugzilla/show_bug.cgi?id=69820 + int mapSize = map.size(); + delegatedMap = new LinkedHashMap<>((int) (mapSize * 1.5)); + for (Map.Entry entry : map.entrySet()) { + delegatedMap.put(entry.getKey(), entry.getValue()); + } unmodifiableDelegatedMap = Collections.unmodifiableMap(delegatedMap); } @@ -95,7 +98,12 @@ * @param map Map whose contents are duplicated in the new map */ public ParameterMap(ParameterMap map) { - delegatedMap = new LinkedHashMap<>(map.delegatedMap); + // Unroll loop for performance - https://bz.apache.org/bugzilla/show_bug.cgi?id=69820 + int mapSize = map.size(); + delegatedMap = new LinkedHashMap<>((int) (mapSize * 1.5)); + for (Map.Entry entry : map.entrySet()) { + delegatedMap.put(entry.getKey(), entry.getValue()); + } unmodifiableDelegatedMap = Collections.unmodifiableMap(delegatedMap); } diff -Nru tomcat10-10.1.40/java/org/apache/catalina/util/RateLimiterBase.java tomcat10-10.1.52/java/org/apache/catalina/util/RateLimiterBase.java --- tomcat10-10.1.40/java/org/apache/catalina/util/RateLimiterBase.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/util/RateLimiterBase.java 2026-01-23 19:33:36.000000000 +0000 @@ -48,8 +48,8 @@ private ScheduledThreadPoolExecutor internalExecutorService = null; /** - * If policy name has not been specified, the first call of {@link #getPolicyName()} returns an auto-generated policy - * name using the default policy name as prefix and followed by auto-increase index. + * If policy name has not been specified, the first call of {@link #getPolicyName()} returns an auto-generated + * policy name using the default policy name as prefix and followed by auto-increase index. * * @return default policy name, as a prefix of auto-generated policy name. */ diff -Nru tomcat10-10.1.40/java/org/apache/catalina/util/RequestUtil.java tomcat10-10.1.52/java/org/apache/catalina/util/RequestUtil.java --- tomcat10-10.1.40/java/org/apache/catalina/util/RequestUtil.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/util/RequestUtil.java 2026-01-23 19:33:36.000000000 +0000 @@ -18,11 +18,10 @@ import jakarta.servlet.http.HttpServletRequest; +import org.apache.catalina.connector.Request; + /** * General purpose request parsing and encoding utility methods. - * - * @author Craig R. McClanahan - * @author Tim Tye */ public final class RequestUtil { @@ -54,4 +53,51 @@ return url; } + + + /** + * Strip parameters for given path. + * + * @param input the input path + * @param request the request to add the parameters to + * + * @return the cleaned path + */ + public static String stripPathParams(String input, Request request) { + // Shortcut + if (input.indexOf(';') < 0) { + return input; + } + + StringBuilder sb = new StringBuilder(input.length()); + int pos = 0; + int limit = input.length(); + while (pos < limit) { + int nextSemiColon = input.indexOf(';', pos); + if (nextSemiColon < 0) { + nextSemiColon = limit; + } + sb.append(input, pos, nextSemiColon); + int followingSlash = input.indexOf('/', nextSemiColon); + if (followingSlash < 0) { + pos = limit; + } else { + pos = followingSlash; + } + if (request != null && nextSemiColon + 1 < pos) { + String pathVariablesString = input.substring(nextSemiColon + 1, pos); + String[] pathVariables = pathVariablesString.split(";"); + for (String pathVariable : pathVariables) { + int equals = pathVariable.indexOf('='); + if (equals > -1 && equals + 1 < pathVariable.length()) { + String name = pathVariable.substring(0, equals); + String value = pathVariable.substring(equals + 1); + request.addPathParameter(name, value); + } + } + } + } + + return sb.toString(); + } } diff -Nru tomcat10-10.1.40/java/org/apache/catalina/util/ResourceSet.java tomcat10-10.1.52/java/org/apache/catalina/util/ResourceSet.java --- tomcat10-10.1.40/java/org/apache/catalina/util/ResourceSet.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/util/ResourceSet.java 2026-01-23 19:33:36.000000000 +0000 @@ -29,8 +29,6 @@ * modifications. When first created, a ResourceMap is not locked. * * @param The type of elements in the Set - * - * @author Craig R. McClanahan */ public final class ResourceSet extends HashSet { diff -Nru tomcat10-10.1.40/java/org/apache/catalina/util/ServerInfo.java tomcat10-10.1.52/java/org/apache/catalina/util/ServerInfo.java --- tomcat10-10.1.40/java/org/apache/catalina/util/ServerInfo.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/util/ServerInfo.java 2026-01-23 19:33:36.000000000 +0000 @@ -25,8 +25,6 @@ /** * Simple utility module to make it easy to plug in the server identifier when integrating Tomcat. - * - * @author Craig R. McClanahan */ public class ServerInfo { diff -Nru tomcat10-10.1.40/java/org/apache/catalina/util/Strftime.java tomcat10-10.1.52/java/org/apache/catalina/util/Strftime.java --- tomcat10-10.1.40/java/org/apache/catalina/util/Strftime.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/util/Strftime.java 2026-01-23 19:33:36.000000000 +0000 @@ -34,9 +34,6 @@ *
  • The interface looks like a subset of DateFormat. Maybe someday someone will make this class extend * DateFormat.
  • * - * - * @author Bip Thelin - * @author Dan Sandberg */ public class Strftime { protected static final Properties translate; diff -Nru tomcat10-10.1.40/java/org/apache/catalina/util/TimeBucketCounterBase.java tomcat10-10.1.52/java/org/apache/catalina/util/TimeBucketCounterBase.java --- tomcat10-10.1.40/java/org/apache/catalina/util/TimeBucketCounterBase.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/util/TimeBucketCounterBase.java 2026-01-23 19:33:36.000000000 +0000 @@ -182,9 +182,9 @@ */ public void periodicEvict() { /* - * The implementation of this method assumes that the time taken for eviction is less than 1 bucket duration. - * It is possible that the eviction process starts in one bucket but finishes in another. Therefore, keys for - * the current bucket and the next bucket when the eviction process starts are excluded from eviction. + * The implementation of this method assumes that the time taken for eviction is less than 1 bucket duration. It + * is possible that the eviction process starts in one bucket but finishes in another. Therefore, keys for the + * current bucket and the next bucket when the eviction process starts are excluded from eviction. */ long currentBucketIndex = getCurrentBucketPrefix(); String currentBucketPrefix = String.valueOf(currentBucketIndex); diff -Nru tomcat10-10.1.40/java/org/apache/catalina/util/URLEncoder.java tomcat10-10.1.52/java/org/apache/catalina/util/URLEncoder.java --- tomcat10-10.1.40/java/org/apache/catalina/util/URLEncoder.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/util/URLEncoder.java 2026-01-23 19:33:36.000000000 +0000 @@ -20,15 +20,13 @@ import java.io.IOException; import java.io.OutputStreamWriter; import java.nio.charset.Charset; +import java.nio.charset.CodingErrorAction; import java.util.BitSet; /** * This class is very similar to the java.net.URLEncoder class. Unfortunately, with java.net.URLEncoder there is no way * to specify to the java.net.URLEncoder which characters should NOT be encoded. This code was moved from * DefaultServlet.java - * - * @author Craig R. McClanahan - * @author Remy Maucherat */ public final class URLEncoder implements Cloneable { @@ -149,7 +147,15 @@ int maxBytesPerChar = 10; StringBuilder rewrittenPath = new StringBuilder(path.length()); ByteArrayOutputStream buf = new ByteArrayOutputStream(maxBytesPerChar); - OutputStreamWriter writer = new OutputStreamWriter(buf, charset); + /* + * Most calls to this method use UTF-8 where malformed input and unmappable character issues are not expected to + * happen. The only Tomcat code that currently (January 2026) might call this method with something other than + * UTF-8 is the rewrite valve. In that case, the rewrite rules should be consistent with the configured URI + * encoding on the Connector. Given all of this, the IAE is only expected to be thrown as a result of + * configuration errors. + */ + OutputStreamWriter writer = new OutputStreamWriter(buf, charset.newEncoder() + .onMalformedInput(CodingErrorAction.REPORT).onUnmappableCharacter(CodingErrorAction.REPORT)); for (int i = 0; i < path.length(); i++) { int c = path.charAt(i); @@ -162,9 +168,8 @@ try { writer.write((char) c); writer.flush(); - } catch (IOException e) { - buf.reset(); - continue; + } catch (IOException ioe) { + throw new IllegalArgumentException(ioe); } byte[] ba = buf.toByteArray(); for (byte toEncode : ba) { diff -Nru tomcat10-10.1.40/java/org/apache/catalina/util/XMLWriter.java tomcat10-10.1.52/java/org/apache/catalina/util/XMLWriter.java --- tomcat10-10.1.40/java/org/apache/catalina/util/XMLWriter.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/util/XMLWriter.java 2026-01-23 19:33:36.000000000 +0000 @@ -141,7 +141,7 @@ } if (namespaceInfo != null) { buffer.append("<").append(namespace).append(":").append(name).append(" xmlns:") - .append(namespace).append("=\"").append(namespaceInfo).append("\">"); + .append(namespace).append("=\"").append(namespaceInfo).append("\">"); } else { buffer.append("<").append(namespace).append(":").append(name).append(">"); } @@ -158,7 +158,7 @@ } if (namespaceInfo != null) { buffer.append("<").append(namespace).append(":").append(name).append(" xmlns:") - .append(namespace).append("=\"").append(namespaceInfo).append("\"/>\n"); + .append(namespace).append("=\"").append(namespaceInfo).append("\"/>\n"); } else { buffer.append("<").append(namespace).append(":").append(name).append("/>\n"); } diff -Nru tomcat10-10.1.40/java/org/apache/catalina/valves/AbstractAccessLogValve.java tomcat10-10.1.52/java/org/apache/catalina/valves/AbstractAccessLogValve.java --- tomcat10-10.1.40/java/org/apache/catalina/valves/AbstractAccessLogValve.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/valves/AbstractAccessLogValve.java 2026-01-23 19:33:36.000000000 +0000 @@ -21,6 +21,7 @@ import java.io.IOException; import java.net.InetAddress; import java.text.SimpleDateFormat; +import java.time.Instant; import java.util.ArrayList; import java.util.Date; import java.util.Enumeration; @@ -56,15 +57,12 @@ /** - *

    * Abstract implementation of the Valve interface that generates a web server access log with the detailed line * contents matching a configurable pattern. The syntax of the available patterns is similar to that supported by the * Apache HTTP Server mod_log_config module. - *

    *

    * Patterns for the logged message may include constant text or any of the following replacement strings, for which the * corresponding information from the specified Response is substituted: - *

    *
      *
    • %a - Remote IP address *
    • %A - Local IP address @@ -97,7 +95,6 @@ *
    *

    * In addition, the caller can specify one of the following aliases for commonly utilized patterns: - *

    *
      *
    • common - %h %l %u %t "%r" %s %b *
    • combined - %h %l %u %t "%r" %s %b "%{Referer}i" "%{User-Agent}i" @@ -106,7 +103,6 @@ * There is also support to write information from the cookie, incoming header, the Session or something else in the * ServletRequest.
      * It is modeled after the Apache HTTP Server log configuration syntax: - *

      *
        *
      • %{xxx}i for incoming headers *
      • %{xxx}o for outgoing response headers @@ -126,17 +122,9 @@ * non-null value, the logging will be skipped. If the value returned from ServletRequest.getAttribute(conditionIf) * yields the null value, the logging will be skipped. The condition attribute is synonym for * conditionUnless and is provided for backwards compatibility. - *

        *

        * For extended attributes coming from a getAttribute() call, it is you responsibility to ensure there are no newline or * control characters. - *

        - * - * @author Craig R. McClanahan - * @author Jason Brittain - * @author Remy Maucherat - * @author Takayuki Kaneko - * @author Peter Rossbach */ public abstract class AbstractAccessLogValve extends ValveBase implements AccessLog { @@ -675,16 +663,13 @@ return; } - // Date for access log should be the beginning of the request - Date date = getDate(request.getCoyoteRequest().getStartTime()); - CharArrayWriter result = charArrayWriters.pop(); if (result == null) { result = new CharArrayWriter(128); } for (AccessLogElement logElement : logElements) { - logElement.addElement(result, date, request, response, time); + logElement.addElement(result, request, response, time); } log(result); @@ -747,9 +732,42 @@ /** * AccessLogElement writes the partial message into the buffer. + *

        + * At least one method must be implemented else a loop will occur. + *

        + * When the deprecated method is removed in Tomcat 12, the default implementation for + * {@link #addElement(CharArrayWriter, Request, Response, long)} will also be removed. */ protected interface AccessLogElement { - void addElement(CharArrayWriter buf, Date date, Request request, Response response, long time); + /** + * Called to create an access log entry. + * + * @param buf The buffer to which the log element should be added + * @param date The time stamp for the start of the request + * @param request The request that triggered this access log entry + * @param response The response to the request that triggered this access log entry + * @param time The time taken in nanoseconds to process the request + * + * @deprecated Unused. Will be removed in Tomcat 12. Use + * {@link #addElement(CharArrayWriter, Request, Response, long)} + */ + @Deprecated + default void addElement(CharArrayWriter buf, Date date, Request request, Response response, long time) { + addElement(buf, request, response, time); + } + + /** + * Called to create an access log entry. + * + * @param buf The buffer to which the log element should be added + * @param request The request that triggered this access log entry + * @param response The response to the request that triggered this access log entry + * @param time The time taken in nanoseconds to process the request + */ + default void addElement(CharArrayWriter buf, Request request, Response response, long time) { + Date date = getDate(request.getCoyoteRequest().getStartTime()); + addElement(buf, date, request, response, time); + } } /** @@ -768,7 +786,7 @@ */ protected static class ThreadNameElement implements AccessLogElement { @Override - public void addElement(CharArrayWriter buf, Date date, Request request, Response response, long time) { + public void addElement(CharArrayWriter buf, Request request, Response response, long time) { RequestInfo info = request.getCoyoteRequest().getRequestProcessor(); if (info != null) { buf.append(info.getWorkerThreadName()); @@ -789,8 +807,8 @@ String init; try { init = InetAddress.getLocalHost().getHostAddress(); - } catch (Throwable e) { - ExceptionUtils.handleThrowable(e); + } catch (Throwable t) { + ExceptionUtils.handleThrowable(t); init = "127.0.0.1"; } @@ -802,7 +820,7 @@ } @Override - public void addElement(CharArrayWriter buf, Date date, Request request, Response response, long time) { + public void addElement(CharArrayWriter buf, Request request, Response response, long time) { buf.append(localAddrValue); } } @@ -839,7 +857,7 @@ } @Override - public void addElement(CharArrayWriter buf, Date date, Request request, Response response, long time) { + public void addElement(CharArrayWriter buf, Request request, Response response, long time) { String value = null; if (remoteAddressType == RemoteAddressType.PEER) { value = request.getPeerAddr(); @@ -879,7 +897,7 @@ */ protected class HostElement implements AccessLogElement, CachedElement { @Override - public void addElement(CharArrayWriter buf, Date date, Request request, Response response, long time) { + public void addElement(CharArrayWriter buf, Request request, Response response, long time) { String value = null; if (requestAttributesEnabled) { Object host = request.getAttribute(REMOTE_HOST_ATTRIBUTE); @@ -913,7 +931,7 @@ */ protected static class LogicalUserNameElement implements AccessLogElement { @Override - public void addElement(CharArrayWriter buf, Date date, Request request, Response response, long time) { + public void addElement(CharArrayWriter buf, Request request, Response response, long time) { buf.append('-'); } } @@ -923,7 +941,7 @@ */ protected class ProtocolElement implements AccessLogElement { @Override - public void addElement(CharArrayWriter buf, Date date, Request request, Response response, long time) { + public void addElement(CharArrayWriter buf, Request request, Response response, long time) { if (requestAttributesEnabled) { Object proto = request.getAttribute(PROTOCOL_ATTRIBUTE); if (proto == null) { @@ -942,7 +960,7 @@ */ protected static class UserElement implements AccessLogElement { @Override - public void addElement(CharArrayWriter buf, Date date, Request request, Response response, long time) { + public void addElement(CharArrayWriter buf, Request request, Response response, long time) { if (request != null) { String value = request.getRemoteUser(); if (value != null) { @@ -1085,11 +1103,11 @@ } @Override - public void addElement(CharArrayWriter buf, Date date, Request request, Response response, long time) { - long timestamp = date.getTime(); + public void addElement(CharArrayWriter buf, Request request, Response response, long time) { + Instant requestStartInstant = Instant.from(request.getCoyoteRequest().getStartInstant()); long frac; if (!usesBegin) { - timestamp += TimeUnit.NANOSECONDS.toMillis(time); + requestStartInstant = requestStartInstant.plusNanos(time); } /* * Implementation note: This is deliberately not implemented using switch. If a switch is used the compiler @@ -1099,13 +1117,13 @@ * pre-loading up to date as the name changes is error prone. */ if (type == FormatType.CLF) { - buf.append(localDateCache.get().getFormat(timestamp)); + buf.append(localDateCache.get().getFormat(requestStartInstant.toEpochMilli())); } else if (type == FormatType.SEC) { - buf.append(Long.toString(timestamp / 1000)); + buf.append(Long.toString(requestStartInstant.getEpochSecond())); } else if (type == FormatType.MSEC) { - buf.append(Long.toString(timestamp)); + buf.append(Long.toString(requestStartInstant.toEpochMilli())); } else if (type == FormatType.MSEC_FRAC) { - frac = timestamp % 1000; + frac = requestStartInstant.toEpochMilli() % 1000; if (frac < 100) { if (frac < 10) { buf.append('0'); @@ -1117,12 +1135,13 @@ buf.append(Long.toString(frac)); } else { // FormatType.SDF + long timestamp = requestStartInstant.toEpochMilli(); String temp = localDateCache.get().getFormat(format, locale, timestamp); if (usesMsecs) { frac = timestamp % 1000; StringBuilder tripleMsec = new StringBuilder(4); if (frac < 100) { - buf.append('0'); + tripleMsec.append('0'); if (frac < 10) { tripleMsec.append('0'); } @@ -1145,7 +1164,7 @@ */ protected static class RequestElement implements AccessLogElement { @Override - public void addElement(CharArrayWriter buf, Date date, Request request, Response response, long time) { + public void addElement(CharArrayWriter buf, Request request, Response response, long time) { if (request != null) { String method = request.getMethod(); if (method == null) { @@ -1173,7 +1192,7 @@ */ protected static class HttpStatusCodeElement implements AccessLogElement { @Override - public void addElement(CharArrayWriter buf, Date date, Request request, Response response, long time) { + public void addElement(CharArrayWriter buf, Request request, Response response, long time) { if (response != null) { // This approach is used to reduce GC from toString conversion int status = response.getStatus(); @@ -1222,7 +1241,7 @@ } @Override - public void addElement(CharArrayWriter buf, Date date, Request request, Response response, long time) { + public void addElement(CharArrayWriter buf, Request request, Response response, long time) { if (requestAttributesEnabled && portType == PortType.LOCAL) { Object port = request.getAttribute(SERVER_PORT_ATTRIBUTE); if (port == null) { @@ -1261,7 +1280,7 @@ } @Override - public void addElement(CharArrayWriter buf, Date date, Request request, Response response, long time) { + public void addElement(CharArrayWriter buf, Request request, Response response, long time) { // Don't need to flush since trigger for log message is after the // response has been committed long length = response.getBytesWritten(false); @@ -1289,7 +1308,7 @@ */ protected static class MethodElement implements AccessLogElement { @Override - public void addElement(CharArrayWriter buf, Date date, Request request, Response response, long time) { + public void addElement(CharArrayWriter buf, Request request, Response response, long time) { if (request != null) { buf.append(request.getMethod()); } @@ -1369,7 +1388,7 @@ } @Override - public void addElement(CharArrayWriter buf, Date date, Request request, Response response, long time) { + public void addElement(CharArrayWriter buf, Request request, Response response, long time) { style.append(buf, time); } } @@ -1379,7 +1398,7 @@ */ protected static class FirstByteTimeElement implements AccessLogElement { @Override - public void addElement(CharArrayWriter buf, Date date, Request request, Response response, long time) { + public void addElement(CharArrayWriter buf, Request request, Response response, long time) { long commitTime = response.getCoyoteResponse().getCommitTimeNanos(); if (commitTime == -1) { buf.append('-'); @@ -1395,7 +1414,7 @@ */ protected static class QueryElement implements AccessLogElement { @Override - public void addElement(CharArrayWriter buf, Date date, Request request, Response response, long time) { + public void addElement(CharArrayWriter buf, Request request, Response response, long time) { String query = null; if (request != null) { query = request.getQueryString(); @@ -1412,7 +1431,7 @@ */ protected static class SessionIdElement implements AccessLogElement { @Override - public void addElement(CharArrayWriter buf, Date date, Request request, Response response, long time) { + public void addElement(CharArrayWriter buf, Request request, Response response, long time) { if (request == null) { buf.append('-'); } else { @@ -1431,7 +1450,7 @@ */ protected static class RequestURIElement implements AccessLogElement { @Override - public void addElement(CharArrayWriter buf, Date date, Request request, Response response, long time) { + public void addElement(CharArrayWriter buf, Request request, Response response, long time) { if (request != null) { buf.append(request.getRequestURI()); } else { @@ -1445,7 +1464,7 @@ */ protected class LocalServerNameElement implements AccessLogElement { @Override - public void addElement(CharArrayWriter buf, Date date, Request request, Response response, long time) { + public void addElement(CharArrayWriter buf, Request request, Response response, long time) { String value = null; if (requestAttributesEnabled) { Object serverName = request.getAttribute(SERVER_NAME_ATTRIBUTE); @@ -1478,7 +1497,7 @@ } @Override - public void addElement(CharArrayWriter buf, Date date, Request request, Response response, long time) { + public void addElement(CharArrayWriter buf, Request request, Response response, long time) { buf.append(str); } } @@ -1494,7 +1513,7 @@ } @Override - public void addElement(CharArrayWriter buf, Date date, Request request, Response response, long time) { + public void addElement(CharArrayWriter buf, Request request, Response response, long time) { Enumeration iter = request.getHeaders(header); if (iter.hasMoreElements()) { escapeAndAppend(iter.nextElement(), buf); @@ -1519,7 +1538,7 @@ } @Override - public void addElement(CharArrayWriter buf, Date date, Request request, Response response, long time) { + public void addElement(CharArrayWriter buf, Request request, Response response, long time) { StringBuilder value = null; boolean first = true; Cookie[] cookies = request.getCookies(); @@ -1557,7 +1576,7 @@ } @Override - public void addElement(CharArrayWriter buf, Date date, Request request, Response response, long time) { + public void addElement(CharArrayWriter buf, Request request, Response response, long time) { if (null != response) { Iterator iter = response.getHeaders(header).iterator(); if (iter.hasNext()) { @@ -1584,7 +1603,7 @@ } @Override - public void addElement(CharArrayWriter buf, Date date, Request request, Response response, long time) { + public void addElement(CharArrayWriter buf, Request request, Response response, long time) { Object value = null; if (request != null) { value = request.getAttribute(attribute); @@ -1614,7 +1633,7 @@ } @Override - public void addElement(CharArrayWriter buf, Date date, Request request, Response response, long time) { + public void addElement(CharArrayWriter buf, Request request, Response response, long time) { Object value = null; if (null != request) { HttpSession sess = request.getSession(false); @@ -1641,7 +1660,7 @@ */ protected static class ConnectionStatusElement implements AccessLogElement { @Override - public void addElement(CharArrayWriter buf, Date date, Request request, Response response, long time) { + public void addElement(CharArrayWriter buf, Request request, Response response, long time) { if (response != null && request != null) { boolean statusFound = false; @@ -1679,7 +1698,6 @@ } - /** * Write identifier element %{xxx}L */ @@ -1691,7 +1709,7 @@ private final IdentifierType identifierType; public IdentifierElement() { - this(null); + this(""); } @@ -1708,8 +1726,8 @@ } @Override - public void addElement(CharArrayWriter buf, Date date, Request request, Response response, long time) { - switch(identifierType) { + public void addElement(CharArrayWriter buf, Request request, Response response, long time) { + switch (identifierType) { case CONNECTION: buf.append(request.getServletConnection().getConnectionId()); break; diff -Nru tomcat10-10.1.40/java/org/apache/catalina/valves/AccessLogValve.java tomcat10-10.1.52/java/org/apache/catalina/valves/AccessLogValve.java --- tomcat10-10.1.40/java/org/apache/catalina/valves/AccessLogValve.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/valves/AccessLogValve.java 2026-01-23 19:33:36.000000000 +0000 @@ -446,9 +446,9 @@ close(false); try { holder.renameTo(new File(newFileName)); - } catch (Throwable e) { - ExceptionUtils.handleThrowable(e); - log.error(sm.getString("accessLogValve.rotateFail"), e); + } catch (Throwable t) { + ExceptionUtils.handleThrowable(t); + log.error(sm.getString("accessLogValve.rotateFail"), t); } /* Make sure date is correct */ @@ -515,9 +515,9 @@ if (!rotatedLogFile.renameTo(newLogFile)) { log.error(sm.getString("accessLogValve.renameFail", rotatedLogFile, newLogFile)); } - } catch (Throwable e) { - ExceptionUtils.handleThrowable(e); - log.error(sm.getString("accessLogValve.renameFail", rotatedLogFile, newLogFile), e); + } catch (Throwable t) { + ExceptionUtils.handleThrowable(t); + log.error(sm.getString("accessLogValve.renameFail", rotatedLogFile, newLogFile), t); } } } @@ -541,9 +541,9 @@ if (!currentLogFile.renameTo(newLogFile)) { log.error(sm.getString("accessLogValve.renameFail", currentLogFile, newLogFile)); } - } catch (Throwable e) { - ExceptionUtils.handleThrowable(e); - log.error(sm.getString("accessLogValve.renameFail", currentLogFile, newLogFile), e); + } catch (Throwable t) { + ExceptionUtils.handleThrowable(t); + log.error(sm.getString("accessLogValve.renameFail", currentLogFile, newLogFile), t); } } else { log.error(sm.getString("accessLogValve.alreadyExists", currentLogFile, newLogFile)); @@ -566,9 +566,9 @@ if (currentLogFile != null && !currentLogFile.exists()) { try { close(false); - } catch (Throwable e) { - ExceptionUtils.handleThrowable(e); - log.info(sm.getString("accessLogValve.closeFail"), e); + } catch (Throwable t) { + ExceptionUtils.handleThrowable(t); + log.info(sm.getString("accessLogValve.closeFail"), t); } /* Make sure date is correct */ @@ -622,10 +622,10 @@ false); currentLogFile = pathname; - } catch (IOException e) { + } catch (IOException ioe) { writer = null; currentLogFile = null; - log.error(sm.getString("accessLogValve.openFail", pathname, System.getProperty("user.name")), e); + log.error(sm.getString("accessLogValve.openFail", pathname, System.getProperty("user.name")), ioe); } // Rotating a log file will always trigger a new file to be opened so // when a new file is opened, check to see if any old files need to be diff -Nru tomcat10-10.1.40/java/org/apache/catalina/valves/Constants.java tomcat10-10.1.52/java/org/apache/catalina/valves/Constants.java --- tomcat10-10.1.40/java/org/apache/catalina/valves/Constants.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/valves/Constants.java 2026-01-23 19:33:36.000000000 +0000 @@ -19,8 +19,6 @@ /** * Manifest constants for the org.apache.catalina.valves package. - * - * @author Craig R. McClanahan */ public final class Constants { diff -Nru tomcat10-10.1.40/java/org/apache/catalina/valves/CrawlerSessionManagerValve.java tomcat10-10.1.52/java/org/apache/catalina/valves/CrawlerSessionManagerValve.java --- tomcat10-10.1.40/java/org/apache/catalina/valves/CrawlerSessionManagerValve.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/valves/CrawlerSessionManagerValve.java 2026-01-23 19:33:36.000000000 +0000 @@ -21,6 +21,7 @@ import java.util.Enumeration; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; +import java.util.function.Function; import java.util.regex.Pattern; import jakarta.servlet.ServletException; @@ -59,6 +60,8 @@ private boolean isContextAware = true; + private Function clientIdentifierFunction = this::getClientIdentifier; + /** * Specifies a default constructor so async support can be configured. @@ -162,6 +165,15 @@ this.isContextAware = isContextAware; } + /** + * Specify the clientIdentifier function that will be used to identify unique clients. The default is to use the + * client IP address, optionally combined with the host name and context name. + * + * @param clientIdentifierFunction The new function used to build identifiers for clients. + */ + public void setClientIdentifierFunction(Function clientIdentifierFunction) { + this.clientIdentifierFunction = clientIdentifierFunction; + } @Override protected void initInternal() throws LifecycleException { @@ -184,7 +196,7 @@ boolean isBot = false; String sessionId = null; String clientIp = request.getRemoteAddr(); - String clientIdentifier = getClientIdentifier(host, request.getContext(), clientIp); + String clientIdentifier = clientIdentifierFunction.apply(request); if (log.isTraceEnabled()) { log.trace(request.hashCode() + ": ClientIdentifier=" + clientIdentifier + ", RequestedSessionId=" + @@ -262,12 +274,12 @@ } } - - private String getClientIdentifier(Host host, Context context, String clientIp) { - StringBuilder result = new StringBuilder(clientIp); + private String getClientIdentifier(Request request) { + StringBuilder result = new StringBuilder(request.getRemoteAddr()); if (isHostAware) { - result.append('-').append(host.getName()); + result.append('-').append(request.getHost().getName()); } + Context context = request.getContext(); if (isContextAware && context != null) { result.append(context.getName()); } diff -Nru tomcat10-10.1.40/java/org/apache/catalina/valves/ErrorReportValve.java tomcat10-10.1.52/java/org/apache/catalina/valves/ErrorReportValve.java --- tomcat10-10.1.40/java/org/apache/catalina/valves/ErrorReportValve.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/valves/ErrorReportValve.java 2026-01-23 19:33:36.000000000 +0000 @@ -42,21 +42,11 @@ import org.apache.tomcat.util.security.Escape; /** - *

        * Implementation of a Valve that outputs HTML error pages. - *

        *

        * This Valve should be attached at the Host level, although it will work if attached to a Context. - *

        *

        * HTML code from the Cocoon 2 project. - *

        - * - * @author Remy Maucherat - * @author Craig R. McClanahan - * @author Nicola Ken Barozzi Aisa - * @author Stefano Mazzocchi - * @author Yoav Shapira */ public class ErrorReportValve extends ValveBase { @@ -389,11 +379,10 @@ response.setContentType("text/html"); response.setCharacterEncoding("UTF-8"); - try (OutputStream os = response.getOutputStream(); - InputStream is = new FileInputStream(file)) { + try (OutputStream os = response.getOutputStream(); InputStream is = new FileInputStream(file)) { IOTools.flow(is, os); - } catch (IOException e) { - getContainer().getLogger().warn(sm.getString("errorReportValve.errorPageIOException", location), e); + } catch (IOException ioe) { + getContainer().getLogger().warn(sm.getString("errorReportValve.errorPageIOException", location), ioe); return false; } diff -Nru tomcat10-10.1.40/java/org/apache/catalina/valves/ExtendedAccessLogValve.java tomcat10-10.1.52/java/org/apache/catalina/valves/ExtendedAccessLogValve.java --- tomcat10-10.1.40/java/org/apache/catalina/valves/ExtendedAccessLogValve.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/valves/ExtendedAccessLogValve.java 2026-01-23 19:33:36.000000000 +0000 @@ -42,8 +42,8 @@ /** * An implementation of the W3c Extended Log File Format. See - * WD-logfile-960323 - * for more information about the format. The following fields are supported: + * WD-logfile-960323 for more information about the format. The + * following fields are supported: *
          *
        • c-dns: Client hostname (or ip address if enableLookups for the connector is false)
        • *
        • c-ip: Client ip address
        • @@ -82,8 +82,6 @@ *
        • x-H(scheme): getScheme
        • *
        • x-H(secure): isSecure
        • *
        - * - * @author Peter Rossbach */ public class ExtendedAccessLogValve extends AccessLogValve { @@ -97,7 +95,7 @@ * toString() fails, '-' will be written to the buffer. * * @param value - The value to wrap - * @param buf the buffer to write to + * @param buf the buffer to write to */ static void wrap(Object value, CharArrayWriter buf) { String svalue; @@ -108,8 +106,8 @@ try { svalue = value.toString(); - } catch (Throwable e) { - ExceptionUtils.handleThrowable(e); + } catch (Throwable t) { + ExceptionUtils.handleThrowable(t); /* Log error */ buf.append('-'); return; @@ -145,11 +143,12 @@ ThreadLocal.withInitial(() -> new ElementTimestampStruct("yyyy-MM-dd")); @Override - public void addElement(CharArrayWriter buf, Date date, Request request, Response response, long time) { + public void addElement(CharArrayWriter buf, Request request, Response response, long time) { ElementTimestampStruct eds = currentDate.get(); long millis = eds.currentTimestamp.getTime(); - if (date.getTime() > (millis + INTERVAL - 1) || date.getTime() < millis) { - eds.currentTimestamp.setTime(date.getTime() - (date.getTime() % INTERVAL)); + long epochMilli = request.getCoyoteRequest().getStartInstant().toEpochMilli(); + if (epochMilli > (millis + INTERVAL - 1) || epochMilli < millis) { + eds.currentTimestamp.setTime(epochMilli - (epochMilli % INTERVAL)); eds.currentTimestampString = eds.currentTimestampFormat.format(eds.currentTimestamp); } buf.append(eds.currentTimestampString); @@ -164,11 +163,12 @@ ThreadLocal.withInitial(() -> new ElementTimestampStruct("HH:mm:ss")); @Override - public void addElement(CharArrayWriter buf, Date date, Request request, Response response, long time) { + public void addElement(CharArrayWriter buf, Request request, Response response, long time) { ElementTimestampStruct eds = currentTime.get(); long millis = eds.currentTimestamp.getTime(); - if (date.getTime() > (millis + INTERVAL - 1) || date.getTime() < millis) { - eds.currentTimestamp.setTime(date.getTime() - (date.getTime() % INTERVAL)); + long epochMilli = request.getCoyoteRequest().getStartInstant().toEpochMilli(); + if (epochMilli > (millis + INTERVAL - 1) || epochMilli < millis) { + eds.currentTimestamp.setTime(epochMilli - (epochMilli % INTERVAL)); eds.currentTimestampString = eds.currentTimestampFormat.format(eds.currentTimestamp); } buf.append(eds.currentTimestampString); @@ -183,7 +183,7 @@ } @Override - public void addElement(CharArrayWriter buf, Date date, Request request, Response response, long time) { + public void addElement(CharArrayWriter buf, Request request, Response response, long time) { wrap(request.getHeader(header), buf); } } @@ -196,7 +196,7 @@ } @Override - public void addElement(CharArrayWriter buf, Date date, Request request, Response response, long time) { + public void addElement(CharArrayWriter buf, Request request, Response response, long time) { wrap(response.getHeader(header), buf); } } @@ -209,7 +209,7 @@ } @Override - public void addElement(CharArrayWriter buf, Date date, Request request, Response response, long time) { + public void addElement(CharArrayWriter buf, Request request, Response response, long time) { wrap(request.getContext().getServletContext().getAttribute(attribute), buf); } } @@ -222,7 +222,7 @@ } @Override - public void addElement(CharArrayWriter buf, Date date, Request request, Response response, long time) { + public void addElement(CharArrayWriter buf, Request request, Response response, long time) { StringBuilder value = new StringBuilder(); boolean first = true; Cookie[] c = request.getCookies(); @@ -255,7 +255,7 @@ } @Override - public void addElement(CharArrayWriter buf, Date date, Request request, Response response, long time) { + public void addElement(CharArrayWriter buf, Request request, Response response, long time) { if (null != response) { Iterator iter = response.getHeaders(header).iterator(); if (iter.hasNext()) { @@ -287,7 +287,7 @@ } @Override - public void addElement(CharArrayWriter buf, Date date, Request request, Response response, long time) { + public void addElement(CharArrayWriter buf, Request request, Response response, long time) { wrap(request.getAttribute(attribute), buf); } } @@ -300,7 +300,7 @@ } @Override - public void addElement(CharArrayWriter buf, Date date, Request request, Response response, long time) { + public void addElement(CharArrayWriter buf, Request request, Response response, long time) { HttpSession session = null; if (request != null) { session = request.getSession(false); @@ -329,7 +329,7 @@ } @Override - public void addElement(CharArrayWriter buf, Date date, Request request, Response response, long time) { + public void addElement(CharArrayWriter buf, Request request, Response response, long time) { String parameterValue; try { parameterValue = request.getParameter(parameter); @@ -497,8 +497,8 @@ log.trace("finished decoding with element size of: " + list.size()); } return list.toArray(new AccessLogElement[0]); - } catch (IOException e) { - log.error(sm.getString("extendedAccessLogValve.patternParseError", pattern), e); + } catch (IOException ioe) { + log.error(sm.getString("extendedAccessLogValve.patternParseError", pattern), ioe); return null; } } @@ -549,13 +549,13 @@ } else if ("dns".equals(nextToken)) { return new AccessLogElement() { @Override - public void addElement(CharArrayWriter buf, Date date, Request request, Response response, + public void addElement(CharArrayWriter buf, Request request, Response response, long time) { String value; try { value = InetAddress.getLocalHost().getHostName(); - } catch (Throwable e) { - ExceptionUtils.handleThrowable(e); + } catch (Throwable t) { + ExceptionUtils.handleThrowable(t); value = "localhost"; } buf.append(value); @@ -588,7 +588,7 @@ } else if ("query".equals(token)) { return new AccessLogElement() { @Override - public void addElement(CharArrayWriter buf, Date date, Request request, Response response, + public void addElement(CharArrayWriter buf, Request request, Response response, long time) { String query = request.getQueryString(); if (query != null) { @@ -602,7 +602,7 @@ } else { return new AccessLogElement() { @Override - public void addElement(CharArrayWriter buf, Date date, Request request, Response response, + public void addElement(CharArrayWriter buf, Request request, Response response, long time) { String query = request.getQueryString(); buf.append(request.getRequestURI()); @@ -700,84 +700,84 @@ if ("authType".equals(parameter)) { return new AccessLogElement() { @Override - public void addElement(CharArrayWriter buf, Date date, Request request, Response response, long time) { + public void addElement(CharArrayWriter buf, Request request, Response response, long time) { wrap(request.getAuthType(), buf); } }; } else if ("remoteUser".equals(parameter)) { return new AccessLogElement() { @Override - public void addElement(CharArrayWriter buf, Date date, Request request, Response response, long time) { + public void addElement(CharArrayWriter buf, Request request, Response response, long time) { wrap(request.getRemoteUser(), buf); } }; } else if ("requestedSessionId".equals(parameter)) { return new AccessLogElement() { @Override - public void addElement(CharArrayWriter buf, Date date, Request request, Response response, long time) { + public void addElement(CharArrayWriter buf, Request request, Response response, long time) { wrap(request.getRequestedSessionId(), buf); } }; } else if ("requestedSessionIdFromCookie".equals(parameter)) { return new AccessLogElement() { @Override - public void addElement(CharArrayWriter buf, Date date, Request request, Response response, long time) { + public void addElement(CharArrayWriter buf, Request request, Response response, long time) { wrap(String.valueOf(request.isRequestedSessionIdFromCookie()), buf); } }; } else if ("requestedSessionIdValid".equals(parameter)) { return new AccessLogElement() { @Override - public void addElement(CharArrayWriter buf, Date date, Request request, Response response, long time) { + public void addElement(CharArrayWriter buf, Request request, Response response, long time) { wrap(String.valueOf(request.isRequestedSessionIdValid()), buf); } }; } else if ("contentLength".equals(parameter)) { return new AccessLogElement() { @Override - public void addElement(CharArrayWriter buf, Date date, Request request, Response response, long time) { + public void addElement(CharArrayWriter buf, Request request, Response response, long time) { wrap(String.valueOf(request.getContentLengthLong()), buf); } }; } else if ("connectionId".equals(parameter)) { return new AccessLogElement() { @Override - public void addElement(CharArrayWriter buf, Date date, Request request, Response response, long time) { + public void addElement(CharArrayWriter buf, Request request, Response response, long time) { wrap(request.getServletConnection().getConnectionId(), buf); } }; } else if ("characterEncoding".equals(parameter)) { return new AccessLogElement() { @Override - public void addElement(CharArrayWriter buf, Date date, Request request, Response response, long time) { + public void addElement(CharArrayWriter buf, Request request, Response response, long time) { wrap(request.getCharacterEncoding(), buf); } }; } else if ("locale".equals(parameter)) { return new AccessLogElement() { @Override - public void addElement(CharArrayWriter buf, Date date, Request request, Response response, long time) { + public void addElement(CharArrayWriter buf, Request request, Response response, long time) { wrap(request.getLocale(), buf); } }; } else if ("protocol".equals(parameter)) { return new AccessLogElement() { @Override - public void addElement(CharArrayWriter buf, Date date, Request request, Response response, long time) { + public void addElement(CharArrayWriter buf, Request request, Response response, long time) { wrap(request.getProtocol(), buf); } }; } else if ("scheme".equals(parameter)) { return new AccessLogElement() { @Override - public void addElement(CharArrayWriter buf, Date date, Request request, Response response, long time) { + public void addElement(CharArrayWriter buf, Request request, Response response, long time) { buf.append(request.getScheme()); } }; } else if ("secure".equals(parameter)) { return new AccessLogElement() { @Override - public void addElement(CharArrayWriter buf, Date date, Request request, Response response, long time) { + public void addElement(CharArrayWriter buf, Request request, Response response, long time) { wrap(Boolean.valueOf(request.isSecure()), buf); } }; diff -Nru tomcat10-10.1.40/java/org/apache/catalina/valves/JDBCAccessLogValve.java tomcat10-10.1.52/java/org/apache/catalina/valves/JDBCAccessLogValve.java --- tomcat10-10.1.40/java/org/apache/catalina/valves/JDBCAccessLogValve.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/valves/JDBCAccessLogValve.java 2026-01-23 19:33:36.000000000 +0000 @@ -96,9 +96,6 @@ * remoteHost, user, timeStamp, query, status, bytes *

        * - * @author Andre de Jesus - * @author Peter Rossbach - * * @deprecated Non scalable design, and not documented. Will be removed in Tomcat 12. */ @Deprecated diff -Nru tomcat10-10.1.40/java/org/apache/catalina/valves/JsonAccessLogValve.java tomcat10-10.1.52/java/org/apache/catalina/valves/JsonAccessLogValve.java --- tomcat10-10.1.40/java/org/apache/catalina/valves/JsonAccessLogValve.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/valves/JsonAccessLogValve.java 2026-01-23 19:33:36.000000000 +0000 @@ -20,7 +20,6 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; -import java.util.Date; import java.util.HashMap; import java.util.List; import java.util.ListIterator; @@ -125,7 +124,7 @@ } @Override - public void addElement(CharArrayWriter buf, Date date, Request request, Response response, long time) { + public void addElement(CharArrayWriter buf, Request request, Response response, long time) { buf.write(ch); } } @@ -257,12 +256,12 @@ } @Override - public void addElement(CharArrayWriter buf, Date date, Request request, Response response, long time) { + public void addElement(CharArrayWriter buf, Request request, Response response, long time) { buf.append('"').append(attributeName).append('"').append(':'); if (quoteValue) { buf.append('"'); } - delegate.addElement(buf, date, request, response, time); + delegate.addElement(buf, request, response, time); if (quoteValue) { buf.append('"'); } diff -Nru tomcat10-10.1.40/java/org/apache/catalina/valves/JsonErrorReportValve.java tomcat10-10.1.52/java/org/apache/catalina/valves/JsonErrorReportValve.java --- tomcat10-10.1.40/java/org/apache/catalina/valves/JsonErrorReportValve.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/valves/JsonErrorReportValve.java 2026-01-23 19:33:36.000000000 +0000 @@ -28,8 +28,8 @@ import org.apache.tomcat.util.res.StringManager; /** - * Implementation of a Valve that outputs error JSON. - * This Valve should be attached at the Host level, although it will work if attached to a Context. + * Implementation of a Valve that outputs error JSON. This Valve should be attached at the Host level, although it will + * work if attached to a Context. */ public class JsonErrorReportValve extends ErrorReportValve { @@ -112,7 +112,8 @@ } for (int i = 0; i < pos; i++) { if (!(elements[i].getClassName().startsWith("org.apache.catalina.core."))) { - sb.append(',').append('\"').append(' ').append(JSONFilter.escape(elements[i].toString())).append('\"'); + sb.append(',').append('\"').append(' ').append(JSONFilter.escape(elements[i].toString())) + .append('\"'); } } diff -Nru tomcat10-10.1.40/java/org/apache/catalina/valves/LocalStrings.properties tomcat10-10.1.52/java/org/apache/catalina/valves/LocalStrings.properties --- tomcat10-10.1.40/java/org/apache/catalina/valves/LocalStrings.properties 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/valves/LocalStrings.properties 2026-01-23 19:33:36.000000000 +0000 @@ -135,6 +135,13 @@ loadBalancerDrainingValve.draining=Load-balancer is in DISABLED state, draining this node loadBalancerDrainingValve.skip=Client is presenting a valid [{0}] cookie, re-balancing is being skipped +parameterLimitValve.closeError=Error closing configuration +parameterLimitValve.invalidLimits=Each limit configuration must contain either a single integer or three, comma-separated integers. Invalid limit string [{0}] +parameterLimitValve.invalidLine=Each line must contain at least one '=' character. Invalid line [{0}] +parameterLimitValve.noConfiguration=No configuration resource found [{0}] +parameterLimitValve.readConfiguration=Read configuration from [/WEB-INF/{0}] +parameterLimitValve.readError=Error reading configurationpatternTokenizer.unexpectedParenthesis=Unexpected ')' in pattern + patternTokenizer.unexpectedParenthesis=Unexpected ')' in pattern persistentValve.acquireFailed=The request for [{0}] did not obtain the per session Semaphore as no permit was available diff -Nru tomcat10-10.1.40/java/org/apache/catalina/valves/LocalStrings_fr.properties tomcat10-10.1.52/java/org/apache/catalina/valves/LocalStrings_fr.properties --- tomcat10-10.1.40/java/org/apache/catalina/valves/LocalStrings_fr.properties 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/valves/LocalStrings_fr.properties 2026-01-23 19:33:36.000000000 +0000 @@ -135,6 +135,13 @@ loadBalancerDrainingValve.draining=Le balanceur de charge est dans l'étât DISABLED, le changement de répartition de la charge est sauté loadBalancerDrainingValve.skip=Le client a envoyé un cookie [{0}] valide, le le changement de répartition de la charge est sauté +parameterLimitValve.closeError=Erreur lors de la fermeture de la configuration +parameterLimitValve.invalidLimits=Chaque configuration d''une limite doit contenir soit un seul nombre entier, soit trois, séparés par des virgules. Limite invalide [{0}] +parameterLimitValve.invalidLine=Chaque ligne doit contenir au moins un caractère ''='', la ligne invalide est [{0}] +parameterLimitValve.noConfiguration=La ressource de configuration [{0}] n''a pas été trouvée +parameterLimitValve.readConfiguration=Lecture de la configuration à partir de [/WEB-INF/{0}] +parameterLimitValve.readError=Erreur lors de la lecture de la configuration + patternTokenizer.unexpectedParenthesis=')' inattendu dans le modèle persistentValve.acquireFailed=La requête pour [{0}] n''a pas obtenu le sémaphore associé à la session car aucun permis n''était disponible @@ -163,6 +170,6 @@ sslValve.invalidProvider=Le fournisseur SSL spécifié pour le connecteur associé avec cette requête de [{0}] est invalide, le certificat n''a pas pu être traité stuckThreadDetectionValve.interrupted=Le fil d'exécution a été interrompu après la fin de la requête, cela sera ignoré -stuckThreadDetectionValve.notifyStuckThreadCompleted=Le Thread [{0}] (id=[{3}]) qui a été préalablement rapporté comme étant bloqué s''est terminé, il a été actif pendant approximativement [{1}] millisecondes, il y a [{2}] thread(s) au total qui sont surveillés par cette valve et qui pourraient être bloqués +stuckThreadDetectionValve.notifyStuckThreadCompleted=Le Thread [{0}] (id=[{3}]) qui a été préalablement rapporté comme étant bloqué s''est terminé, il a été actif pendant approximativement [{1}] millisecondes. {2,choice,0#|0< Il y a [{2}] thread(s) au total qui sont surveillés par cette valve et qui pourraient être bloqués.} stuckThreadDetectionValve.notifyStuckThreadDetected=Le Thread [{0}] (id=[{6}]) a été actif depuis [{1}] millisecondes (depuis [{2}]) pour traiter la même requête pour [{4}] et pourrait être bloqué (le seuil configurable est de [{5}] secondes pour cette StuckThreadDetectionValve), il y a [{3}] thread(s) au total qui sont surveillés par cette valve et qui pourraient être bloqués stuckThreadDetectionValve.notifyStuckThreadInterrupted=Le Thread [{0}] (id=[{5}]) a été interrompu car il a été actif depuis [{1}] millisecondes (depuis [{2}]) pour traiter la même requête pour [{3}] et était probablement bloqué (le seuil configurable est de [{4}] secondes pour cette StuckThreadDetectionValve) diff -Nru tomcat10-10.1.40/java/org/apache/catalina/valves/LocalStrings_ja.properties tomcat10-10.1.52/java/org/apache/catalina/valves/LocalStrings_ja.properties --- tomcat10-10.1.40/java/org/apache/catalina/valves/LocalStrings_ja.properties 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/valves/LocalStrings_ja.properties 2026-01-23 19:33:36.000000000 +0000 @@ -23,7 +23,7 @@ accessLogValve.invalidPortType=不正なポート種類 [{0}] の代わりにサーバーのローカルポートを使用します。 accessLogValve.invalidRemoteAddressType=リモート (非ピア) アドレスを使用している無効なリモートアドレスタイプ [{0}] accessLogValve.openDirFail=アクセスログのディレクトリ[{0}]の作成に失敗しました -accessLogValve.openFail=アクセスログファイル [{0}] を開けません。 +accessLogValve.openFail=アクセスログファイル [{0}] を開けません。注: ユーザー [{1}] として実行しています accessLogValve.renameFail=[{0}]から[{1}]へのアクセスログの名前の変更に失敗しました。 accessLogValve.rotateFail=アクセスログのローテーションに失敗しました accessLogValve.unsupportedEncoding=文字エンコーディングに [{0}] を指定できません。システムの既定値を使用します。 @@ -135,6 +135,13 @@ loadBalancerDrainingValve.draining=ロードバランサは DISABLED 状態にあり、このノードを使用していません loadBalancerDrainingValve.skip=クライアントは有効な [{0}] Cookie を提示しているため、リバランスはスキップされています +parameterLimitValve.closeError=設定をクローズする際のエラー +parameterLimitValve.invalidLimits=各制限構成には、1 つの整数かコンマで区切られた 3 つの整数が含まれている必要があります。無効な制限文字列 [{0}] +parameterLimitValve.invalidLine=各行には少なくとも 1 つの ''='' が含まれている必要があります。無効な行 [{0}] +parameterLimitValve.noConfiguration=構成リソースが見つかりません [{0}] +parameterLimitValve.readConfiguration=[/WEB-INF/{0}] から設定を読み取ります +parameterLimitValve.readError=設定の読み込みエラー + patternTokenizer.unexpectedParenthesis=パターンに予期しない ')' があります persistentValve.acquireFailed=リクエスト [{0}] は、利用可能な許可がなかったため、セッションごとのセマフォを取得できませんでした diff -Nru tomcat10-10.1.40/java/org/apache/catalina/valves/LocalStrings_ru.properties tomcat10-10.1.52/java/org/apache/catalina/valves/LocalStrings_ru.properties --- tomcat10-10.1.40/java/org/apache/catalina/valves/LocalStrings_ru.properties 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/valves/LocalStrings_ru.properties 2026-01-23 19:33:36.000000000 +0000 @@ -16,6 +16,11 @@ # Do not edit this file directly. # To edit translations see: https://tomcat.apache.org/getinvolved.html#Translations +accessLogValve.invalidLocale=Невозможно установить локаль [{0}] + +errorReportValve.description=Описание +errorReportValve.rootCauseInLogs=Полная трассировка стека первопричины ошибки доступна в логах сервера. + http.401.reason=Не авторизовано http.402.reason=Требуется оплата http.403.desc=Сервер получил запрос, но отказался его авторизовать. diff -Nru tomcat10-10.1.40/java/org/apache/catalina/valves/LocalStrings_zh_CN.properties tomcat10-10.1.52/java/org/apache/catalina/valves/LocalStrings_zh_CN.properties --- tomcat10-10.1.40/java/org/apache/catalina/valves/LocalStrings_zh_CN.properties 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/valves/LocalStrings_zh_CN.properties 2026-01-23 19:33:36.000000000 +0000 @@ -149,6 +149,6 @@ sslValve.certError=无法处理证书字符串[{0}]以创建java.security.cert.X509Certificate对象 sslValve.invalidProvider=与此[{0}]请求关联的连接器上指定的SSL提供程序无效。 无法处理证书数据。 -stuckThreadDetectionValve.notifyStuckThreadCompleted=线程[{0}](id=[{3}])之前报告为卡住,但是已经完成。它活跃了大概[{1}]毫秒。{2,选择,0#|0< 仍有[{2}]个被Valve监控的线程可能卡住} +stuckThreadDetectionValve.notifyStuckThreadCompleted=线程[{0}](id=[{3}])之前报告为卡住,但是已经完成。它活跃了大概[{1}]毫秒。{2,choice,0#|0< 仍有[{2}]个被Valve监控的线程可能卡住} stuckThreadDetectionValve.notifyStuckThreadDetected=线程[{0}](id=[{6}])已处于活动状态[{1}]毫秒(自[{2}]起),以便为[{4}]提供相同的请求,并且可能被卡住(此StuckThreadDetectionValve的配置阈值为[{5}]秒)。总共有[{3}]个线程受此阀监视,可能被卡住。 stuckThreadDetectionValve.notifyStuckThreadInterrupted=线程[{0}](id=[{5}])已被中断,因为它在[{1}]毫秒(自[{2}]起)内处于活动状态,以便为[{3}]提供相同的请求,并且可能被卡住(此StuckThreadDetectionValve的配置中断阈值为[{4}]秒)。 diff -Nru tomcat10-10.1.40/java/org/apache/catalina/valves/ParameterLimitValve.java tomcat10-10.1.52/java/org/apache/catalina/valves/ParameterLimitValve.java --- tomcat10-10.1.40/java/org/apache/catalina/valves/ParameterLimitValve.java 1970-01-01 00:00:00.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/valves/ParameterLimitValve.java 2026-01-23 19:33:36.000000000 +0000 @@ -0,0 +1,282 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.catalina.valves; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.StringReader; +import java.nio.charset.StandardCharsets; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.regex.Pattern; + +import jakarta.servlet.ServletException; + +import org.apache.catalina.Container; +import org.apache.catalina.Context; +import org.apache.catalina.LifecycleException; +import org.apache.catalina.connector.Request; +import org.apache.catalina.connector.Response; +import org.apache.juli.logging.LogFactory; +import org.apache.tomcat.util.buf.UDecoder; +import org.apache.tomcat.util.file.ConfigFileLoader; +import org.apache.tomcat.util.file.ConfigurationSource; + +/** + * This is a concrete implementation of {@link ValveBase} that allows alternative values for the + * Connector attributes {@code maxParameterCount}, {@code maxPartCount} and {@code maxPartHeaderSize} + * to be applied to a request. The features of this implementation include: + *
          + *
        • URL-specific parameter limits that can be defined using regular expressions
        • + *
        • Configurable through Tomcat's server.xml or context.xml
        • + *
        • Requires a parameter_limit.config file containing the URL-specific parameter limits. It must be + * placed in the Host configuration folder or in the WEB-INF folder of the web application.
        • + *
        + *

        + * The default limit, specified by Connector's value, applies to all requests unless a more specific URL pattern is + * matched. URL patterns and their corresponding limits can be configured via a regular expression mapping through the + * urlPatternLimits attribute. + *

        + * The Valve checks each incoming request and enforces the appropriate limit. If a request exceeds the allowed number of + * parameters, a 400 Bad Request response is returned. + *

        + * Example, configuration in context.xml: + * + *

        + * {@code
        + * 
        + *     
        + * }
        + * and in parameter_limit.config:
        + * 
        + * + *
        + * {@code
        + * /api/.*=150
        + * /admin/.*=50
        + * /upload/.*=30,5,1024
        + * }
        + * 
        + *

        + * The configuration allows for flexible control over different sections of your application, such as applying higher + * limits for API endpoints and stricter limits for admin areas. + *

        + * If a single integer is provided, it is used for {@code maxParameterCount}. + *

        + * If three integers are provided, they are applied to {@code maxParameterCount}, {@code maxPartCount} and + * {@code maxPartHeaderSize} respectively. + */ + +public class ParameterLimitValve extends ValveBase { + + /** + * Map for URL-specific limits. + */ + private Map urlPatternLimits = new ConcurrentHashMap<>(); + + /** + * Relative path to the configuration file. Note: If the valve's container is a context, this will be relative to + * /WEB-INF/. + */ + private String resourcePath = "parameter_limit.config"; + + /** + * Will be set to true if the valve is associated with a context. + */ + private boolean context = false; + + public ParameterLimitValve() { + super(true); + } + + public String getResourcePath() { + return resourcePath; + } + + public void setResourcePath(String resourcePath) { + this.resourcePath = resourcePath; + } + + @Override + protected void initInternal() throws LifecycleException { + super.initInternal(); + containerLog = LogFactory.getLog(getContainer().getLogName() + ".parameterLimit"); + } + + @Override + protected void startInternal() throws LifecycleException { + + super.startInternal(); + + InputStream is = null; + + // Process configuration file for this valve + if (getContainer() instanceof Context) { + context = true; + String webInfResourcePath = "/WEB-INF/" + resourcePath; + is = ((Context) getContainer()).getServletContext().getResourceAsStream(webInfResourcePath); + if (containerLog.isDebugEnabled()) { + if (is == null) { + containerLog.debug(sm.getString("parameterLimitValve.noConfiguration", webInfResourcePath)); + } else { + containerLog.debug(sm.getString("parameterLimitValve.readConfiguration", webInfResourcePath)); + } + } + } else { + String resourceName = Container.getConfigPath(getContainer(), resourcePath); + try { + ConfigurationSource.Resource resource = ConfigFileLoader.getSource().getResource(resourceName); + is = resource.getInputStream(); + } catch (IOException ioe) { + if (containerLog.isDebugEnabled()) { + containerLog.debug(sm.getString("parameterLimitValve.noConfiguration", resourceName), ioe); + } + } + } + + if (is == null) { + // Will use management operations to configure the valve dynamically + return; + } + + try (InputStreamReader isr = new InputStreamReader(is, StandardCharsets.UTF_8); + BufferedReader reader = new BufferedReader(isr)) { + setUrlPatternLimits(reader); + } catch (IOException ioe) { + containerLog.error(sm.getString("parameterLimitValve.closeError"), ioe); + } finally { + try { + is.close(); + } catch (IOException ioe) { + containerLog.error(sm.getString("parameterLimitValve.closeError"), ioe); + } + } + + } + + public void setUrlPatternLimits(String urlPatternConfig) { + urlPatternLimits.clear(); + setUrlPatternLimits(new BufferedReader(new StringReader(urlPatternConfig))); + } + + /** + * Set the mapping of URL patterns to their corresponding parameter limits. The input should be provided line by + * line, where each line contains a pattern and a limit, separated by the last '='. + *

        + * Example: + * + *

        +     * /api/.*=50
        +     * /api======/.*=150
        +     * /urlEncoded%20api=2
        +     * # This is a comment
        +     * 
        + * + * @param reader A BufferedReader containing URL pattern to parameter limit mappings, with each pair on a separate + * line. + */ + public void setUrlPatternLimits(BufferedReader reader) { + if (containerLog == null && getContainer() != null) { + containerLog = LogFactory.getLog(getContainer().getLogName() + ".parameterLimit"); + } + try { + String line; + while ((line = reader.readLine()) != null) { + // Trim whitespace from the line + line = line.trim(); + if (line.isEmpty() || line.startsWith("#")) { + // Skip empty lines or comments + continue; + } + + int lastEqualsIndex = line.lastIndexOf('='); + if (lastEqualsIndex == -1) { + throw new IllegalArgumentException(sm.getString("parameterLimitValve.invalidLine", line)); + } + + String patternString = line.substring(0, lastEqualsIndex).trim(); + String limitsString = line.substring(lastEqualsIndex + 1).trim(); + + Pattern pattern = Pattern.compile(UDecoder.URLDecode(patternString, StandardCharsets.UTF_8)); + String[] limits = limitsString.split(","); + if (limits.length == 1) { + urlPatternLimits.put(pattern, new Integer[] { Integer.valueOf(limits[0]), null, null }); + } else if (limits.length == 3) { + urlPatternLimits.put(pattern, new Integer[] { Integer.valueOf(limits[0]), + Integer.valueOf(limits[1]), Integer.valueOf(limits[2]) }); + } else { + throw new IllegalArgumentException( + sm.getString("parameterLimitValve.invalidLimitsString", limitsString)); + } + if (containerLog != null && containerLog.isTraceEnabled()) { + containerLog.trace("Add pattern " + pattern + " and limit(s) " + limitsString); + } + } + } catch (IOException ioe) { + if (containerLog != null) { + containerLog.error(sm.getString("parameterLimitValve.readError"), ioe); + } + } + } + + @Override + protected void stopInternal() throws LifecycleException { + super.stopInternal(); + urlPatternLimits.clear(); + } + + /** + * Checks if any of the defined patterns matches the URI of the request and if it does, enforces the corresponding + * parameter limit for the request. Then invoke the next Valve in the sequence. + * + * @param request The servlet request to be processed + * @param response The servlet response to be created + * + * @exception IOException if an input/output error occurs + * @exception ServletException if a servlet error occurs + */ + @Override + public void invoke(Request request, Response response) throws IOException, ServletException { + + if (urlPatternLimits.isEmpty()) { + getNext().invoke(request, response); + return; + } + + String requestURI = context ? request.getRequestPathMB().toString() : request.getDecodedRequestURI(); + + // Iterate over the URL patterns and apply corresponding limits + for (Map.Entry entry : urlPatternLimits.entrySet()) { + if (entry.getKey().matcher(requestURI).matches()) { + Integer[] limits = entry.getValue(); + // maxParameterCount should always be present + request.setMaxParameterCount(limits[0].intValue()); + if (limits[1] != null) { + request.setMaxPartCount(limits[1].intValue()); + request.setMaxPartHeaderSize(limits[2].intValue()); + } + break; + } + } + + // Invoke the next valve to continue processing the request + getNext().invoke(request, response); + } +} diff -Nru tomcat10-10.1.40/java/org/apache/catalina/valves/PersistentValve.java tomcat10-10.1.52/java/org/apache/catalina/valves/PersistentValve.java --- tomcat10-10.1.40/java/org/apache/catalina/valves/PersistentValve.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/valves/PersistentValve.java 2026-01-23 19:33:36.000000000 +0000 @@ -199,7 +199,7 @@ Session hsess; try { hsess = request.getSessionInternal(false); - } catch (Exception ex) { + } catch (Exception e) { hsess = null; } String newsessionId = null; diff -Nru tomcat10-10.1.40/java/org/apache/catalina/valves/ProxyErrorReportValve.java tomcat10-10.1.52/java/org/apache/catalina/valves/ProxyErrorReportValve.java --- tomcat10-10.1.40/java/org/apache/catalina/valves/ProxyErrorReportValve.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/valves/ProxyErrorReportValve.java 2026-01-23 19:33:36.000000000 +0000 @@ -193,7 +193,7 @@ } try { response.sendRedirect(urlString); - } catch (IOException e) { + } catch (IOException ioe) { // Ignore } } else { diff -Nru tomcat10-10.1.40/java/org/apache/catalina/valves/RemoteAddrValve.java tomcat10-10.1.52/java/org/apache/catalina/valves/RemoteAddrValve.java --- tomcat10-10.1.40/java/org/apache/catalina/valves/RemoteAddrValve.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/valves/RemoteAddrValve.java 2026-01-23 19:33:36.000000000 +0000 @@ -31,8 +31,9 @@ * Concrete implementation of RequestFilterValve that filters based on the string representation of the * remote client's IP address optionally combined with the server connector port number. * - * @author Craig R. McClanahan + * @deprecated This Valve will be removed in Tomcat 12 onwards. Use {@link RemoteCIDRValve} instead. */ +@Deprecated public final class RemoteAddrValve extends RequestFilterValve { private static final Log log = LogFactory.getLog(RemoteAddrValve.class); diff -Nru tomcat10-10.1.40/java/org/apache/catalina/valves/RemoteHostValve.java tomcat10-10.1.52/java/org/apache/catalina/valves/RemoteHostValve.java --- tomcat10-10.1.40/java/org/apache/catalina/valves/RemoteHostValve.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/valves/RemoteHostValve.java 2026-01-23 19:33:36.000000000 +0000 @@ -28,8 +28,6 @@ /** * Concrete implementation of RequestFilterValve that filters based on the remote client's host name * optionally combined with the server connector port number. - * - * @author Craig R. McClanahan */ public final class RemoteHostValve extends RequestFilterValve { diff -Nru tomcat10-10.1.40/java/org/apache/catalina/valves/RemoteIpValve.java tomcat10-10.1.52/java/org/apache/catalina/valves/RemoteIpValve.java --- tomcat10-10.1.40/java/org/apache/catalina/valves/RemoteIpValve.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/valves/RemoteIpValve.java 2026-01-23 19:33:36.000000000 +0000 @@ -397,14 +397,13 @@ /** * @see #setInternalProxies(String) */ - private Pattern internalProxies = - Pattern.compile("10\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}|" + "192\\.168\\.\\d{1,3}\\.\\d{1,3}|" + - "169\\.254\\.\\d{1,3}\\.\\d{1,3}|" + "127\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}|" + - "100\\.6[4-9]{1}\\.\\d{1,3}\\.\\d{1,3}|" + "100\\.[7-9]{1}\\d{1}\\.\\d{1,3}\\.\\d{1,3}|" + - "100\\.1[0-1]{1}\\d{1}\\.\\d{1,3}\\.\\d{1,3}|" + "100\\.12[0-7]{1}\\.\\d{1,3}\\.\\d{1,3}|" + - "172\\.1[6-9]{1}\\.\\d{1,3}\\.\\d{1,3}|" + "172\\.2[0-9]{1}\\.\\d{1,3}\\.\\d{1,3}|" + - "172\\.3[0-1]{1}\\.\\d{1,3}\\.\\d{1,3}|" + "0:0:0:0:0:0:0:1|::1|" + - "fe[89ab]\\p{XDigit}:.*|" + "f[cd]\\p{XDigit}{2}+:.*"); + private Pattern internalProxies = Pattern.compile("10\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}|" + + "192\\.168\\.\\d{1,3}\\.\\d{1,3}|" + "169\\.254\\.\\d{1,3}\\.\\d{1,3}|" + + "127\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}|" + "100\\.6[4-9]{1}\\.\\d{1,3}\\.\\d{1,3}|" + + "100\\.[7-9]{1}\\d{1}\\.\\d{1,3}\\.\\d{1,3}|" + "100\\.1[0-1]{1}\\d{1}\\.\\d{1,3}\\.\\d{1,3}|" + + "100\\.12[0-7]{1}\\.\\d{1,3}\\.\\d{1,3}|" + "172\\.1[6-9]{1}\\.\\d{1,3}\\.\\d{1,3}|" + + "172\\.2[0-9]{1}\\.\\d{1,3}\\.\\d{1,3}|" + "172\\.3[0-1]{1}\\.\\d{1,3}\\.\\d{1,3}|" + + "0:0:0:0:0:0:0:1|::1|" + "fe[89ab]\\p{XDigit}:.*|" + "f[cd]\\p{XDigit}{2}+:.*"); /** * @see #setProtocolHeader(String) @@ -642,7 +641,9 @@ // We know we need a DNS look up so use getCanonicalHostName() request.setRemoteHost(inetAddress.getCanonicalHostName()); } catch (UnknownHostException e) { - log.debug(sm.getString("remoteIpValve.invalidRemoteAddress", remoteIp), e); + if (log.isDebugEnabled()) { + log.debug(sm.getString("remoteIpValve.invalidRemoteAddress", remoteIp), e); + } request.setRemoteHost(remoteIp); } } else { @@ -697,7 +698,7 @@ } } catch (IllegalArgumentException iae) { - log.debug(sm.getString("remoteIpValve.invalidHostHeader", hostHeaderValue, hostHeader)); + log.debug(sm.getString("remoteIpValve.invalidHostHeader", hostHeaderValue, hostHeader), iae); } } } diff -Nru tomcat10-10.1.40/java/org/apache/catalina/valves/RequestFilterValve.java tomcat10-10.1.52/java/org/apache/catalina/valves/RequestFilterValve.java --- tomcat10-10.1.40/java/org/apache/catalina/valves/RequestFilterValve.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/valves/RequestFilterValve.java 2026-01-23 19:33:36.000000000 +0000 @@ -53,8 +53,6 @@ * authentication instead of denial. *

        * This Valve may be attached to any Container, depending on the granularity of the filtering you wish to perform. - * - * @author Craig R. McClanahan */ public abstract class RequestFilterValve extends ValveBase { diff -Nru tomcat10-10.1.40/java/org/apache/catalina/valves/SemaphoreValve.java tomcat10-10.1.52/java/org/apache/catalina/valves/SemaphoreValve.java --- tomcat10-10.1.40/java/org/apache/catalina/valves/SemaphoreValve.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/valves/SemaphoreValve.java 2026-01-23 19:33:36.000000000 +0000 @@ -35,8 +35,6 @@ * perform. Note that internally, some async requests may require multiple serial requests to complete what - to the * user - appears as a single request. *

        - * - * @author Remy Maucherat */ public class SemaphoreValve extends ValveBase { diff -Nru tomcat10-10.1.40/java/org/apache/catalina/valves/StuckThreadDetectionValve.java tomcat10-10.1.52/java/org/apache/catalina/valves/StuckThreadDetectionValve.java --- tomcat10-10.1.40/java/org/apache/catalina/valves/StuckThreadDetectionValve.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/valves/StuckThreadDetectionValve.java 2026-01-23 19:33:36.000000000 +0000 @@ -322,7 +322,9 @@ // going out from here, maybe already serving a new request this.interruptionSemaphore.acquire(); } catch (InterruptedException e) { - log.debug(sm.getString("stuckThreadDetectionValve.interrupted"), e); + if (log.isDebugEnabled()) { + log.debug(sm.getString("stuckThreadDetectionValve.interrupted"), e); + } } // no need to release the semaphore, it will be GCed } diff -Nru tomcat10-10.1.40/java/org/apache/catalina/valves/ValveBase.java tomcat10-10.1.52/java/org/apache/catalina/valves/ValveBase.java --- tomcat10-10.1.40/java/org/apache/catalina/valves/ValveBase.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/valves/ValveBase.java 2026-01-23 19:33:36.000000000 +0000 @@ -31,8 +31,6 @@ * Convenience base class for implementations of the Valve interface. A subclass MUST implement * an invoke() method to provide the required functionality, and MAY implement the * Lifecycle interface to provide configuration management and lifecycle support. - * - * @author Craig R. McClanahan */ public abstract class ValveBase extends LifecycleMBeanBase implements Contained, Valve { diff -Nru tomcat10-10.1.40/java/org/apache/catalina/valves/rewrite/LocalStrings.properties tomcat10-10.1.52/java/org/apache/catalina/valves/rewrite/LocalStrings.properties --- tomcat10-10.1.40/java/org/apache/catalina/valves/rewrite/LocalStrings.properties 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/valves/rewrite/LocalStrings.properties 2026-01-23 19:33:36.000000000 +0000 @@ -18,6 +18,8 @@ quotedStringTokenizer.tokenizeError=Error tokenizing text [{0}] after position [{1}] from mode [{2}] +resolverImpl.tlsError=Unable to obtain TLS information + rewriteMap.tooManyParameters=Too many parameters for this map rewriteMap.txtInvalidLine=Invalid line [{0}] in text file [{1}] rewriteMap.txtReadError=Error reading text file [{0}] diff -Nru tomcat10-10.1.40/java/org/apache/catalina/valves/rewrite/LocalStrings_fr.properties tomcat10-10.1.52/java/org/apache/catalina/valves/rewrite/LocalStrings_fr.properties --- tomcat10-10.1.40/java/org/apache/catalina/valves/rewrite/LocalStrings_fr.properties 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/valves/rewrite/LocalStrings_fr.properties 2026-01-23 19:33:36.000000000 +0000 @@ -18,6 +18,8 @@ quotedStringTokenizer.tokenizeError=Erreur de découpage du texte [{0}] après la position [{1}] en utilisant le mode [{2}] +resolverImpl.tlsError=Impossible d'obtenir l'information TLS + rewriteMap.tooManyParameters=Cette map ne supporte pas plusieurs paramètres rewriteMap.txtInvalidLine=Ligne invalide [{0}] dans le fichier texte [{1}] rewriteMap.txtReadError=Erreur en lisant le fichier texte [{0}] diff -Nru tomcat10-10.1.40/java/org/apache/catalina/valves/rewrite/LocalStrings_ja.properties tomcat10-10.1.52/java/org/apache/catalina/valves/rewrite/LocalStrings_ja.properties --- tomcat10-10.1.40/java/org/apache/catalina/valves/rewrite/LocalStrings_ja.properties 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/valves/rewrite/LocalStrings_ja.properties 2026-01-23 19:33:36.000000000 +0000 @@ -18,6 +18,8 @@ quotedStringTokenizer.tokenizeError=モード [{2}] の位置 [{1}] の後のテキスト [{0}] のトークン化中にエラーが発生しました +resolverImpl.tlsError=TLS情報を取得できません + rewriteMap.tooManyParameters=このマップのパラメータが多すぎます rewriteMap.txtInvalidLine=テキスト ファイル [{1}] の行 [{0}] が無効です rewriteMap.txtReadError=テキスト ファイル [{0}] の読み取り中のエラー diff -Nru tomcat10-10.1.40/java/org/apache/catalina/valves/rewrite/QuotedStringTokenizer.java tomcat10-10.1.52/java/org/apache/catalina/valves/rewrite/QuotedStringTokenizer.java --- tomcat10-10.1.40/java/org/apache/catalina/valves/rewrite/QuotedStringTokenizer.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/valves/rewrite/QuotedStringTokenizer.java 2026-01-23 19:33:36.000000000 +0000 @@ -79,7 +79,7 @@ break; default: throw new IllegalStateException(sm.getString("quotedStringTokenizer.tokenizeError", inputText, - Integer.valueOf(pos), currentMode)); + Integer.valueOf(pos), currentMode)); } pos++; } diff -Nru tomcat10-10.1.40/java/org/apache/catalina/valves/rewrite/RandomizedTextRewriteMap.java tomcat10-10.1.52/java/org/apache/catalina/valves/rewrite/RandomizedTextRewriteMap.java --- tomcat10-10.1.40/java/org/apache/catalina/valves/rewrite/RandomizedTextRewriteMap.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/valves/rewrite/RandomizedTextRewriteMap.java 2026-01-23 19:33:36.000000000 +0000 @@ -50,8 +50,11 @@ BufferedReader reader = new BufferedReader(new InputStreamReader(txtResource.getInputStream()))) { while ((line = reader.readLine()) != null) { if (line.startsWith("#") || line.isEmpty()) { - // Ignore comment or empty lines + // Ignore comment line or empty lines continue; + } else if (line.indexOf('#') > 0) { + // Ignore comment characters after '#' + line = line.substring(0, line.indexOf('#')).trim(); } String[] keyValuePair = line.split(" ", 2); if (keyValuePair.length > 1) { @@ -69,8 +72,8 @@ throw new IllegalArgumentException(sm.getString("rewriteMap.txtInvalidLine", line, txtFilePath)); } } - } catch (IOException e) { - throw new IllegalArgumentException(sm.getString("rewriteMap.txtReadError", txtFilePath), e); + } catch (IOException ioe) { + throw new IllegalArgumentException(sm.getString("rewriteMap.txtReadError", txtFilePath), ioe); } } diff -Nru tomcat10-10.1.40/java/org/apache/catalina/valves/rewrite/ResolverImpl.java tomcat10-10.1.52/java/org/apache/catalina/valves/rewrite/ResolverImpl.java --- tomcat10-10.1.40/java/org/apache/catalina/valves/rewrite/ResolverImpl.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/valves/rewrite/ResolverImpl.java 2026-01-23 19:33:36.000000000 +0000 @@ -34,21 +34,42 @@ import org.apache.catalina.WebResource; import org.apache.catalina.WebResourceRoot; import org.apache.catalina.connector.Request; +import org.apache.juli.logging.Log; import org.apache.tomcat.util.http.FastHttpDateFormat; import org.apache.tomcat.util.net.SSLSupport; import org.apache.tomcat.util.net.jsse.PEMFile; import org.apache.tomcat.util.net.openssl.ciphers.Cipher; import org.apache.tomcat.util.net.openssl.ciphers.EncryptionLevel; import org.apache.tomcat.util.net.openssl.ciphers.OpenSSLCipherConfigurationParser; +import org.apache.tomcat.util.res.StringManager; public class ResolverImpl extends Resolver { - protected Request request; + private static final StringManager sm = StringManager.getManager(ResolverImpl.class); + protected final Request request; + private final Log containerLog; + + + /** + * Create a resolver for the given request. + * + * @param request The request + * + * @deprecated Will be removed in Tomcat 12 onwards. Use {@link #ResolverImpl(Request, Log)} + */ + @Deprecated public ResolverImpl(Request request) { + this(request, request.getContext().getLogger()); + } + + + public ResolverImpl(Request request, Log containerLog) { this.request = request; + this.containerLog = containerLog; } + /** * The following are not implemented: *
          @@ -228,8 +249,11 @@ } } } - } catch (IOException e) { + } catch (IOException ioe) { // TLS access error + if (containerLog.isDebugEnabled()) { + containerLog.debug(sm.getString("resolverImpl.tlsError"), ioe); + } } return null; } @@ -275,14 +299,14 @@ } else if (key.equals("CERT")) { try { return PEMFile.toPEM(certificates[0]); - } catch (CertificateEncodingException e) { + } catch (CertificateEncodingException ignore) { // Ignore } } else if (key.startsWith("CERT_CHAIN_")) { key = key.substring("CERT_CHAIN_".length()); try { return PEMFile.toPEM(certificates[Integer.parseInt(key)]); - } catch (NumberFormatException | ArrayIndexOutOfBoundsException | CertificateEncodingException e) { + } catch (NumberFormatException | ArrayIndexOutOfBoundsException | CertificateEncodingException ignore) { // Ignore } } @@ -317,7 +341,7 @@ return elements.get(n); } } - } catch (NumberFormatException | ArrayIndexOutOfBoundsException | CertificateParsingException e) { + } catch (NumberFormatException | ArrayIndexOutOfBoundsException | CertificateParsingException ignore) { // Ignore } return null; diff -Nru tomcat10-10.1.40/java/org/apache/catalina/valves/rewrite/RewriteValve.java tomcat10-10.1.52/java/org/apache/catalina/valves/rewrite/RewriteValve.java --- tomcat10-10.1.40/java/org/apache/catalina/valves/rewrite/RewriteValve.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/valves/rewrite/RewriteValve.java 2026-01-23 19:33:36.000000000 +0000 @@ -155,14 +155,17 @@ InputStream is = null; // Process configuration file for this valve + // Process configuration file for this valve if (getContainer() instanceof Context) { context = true; String webInfResourcePath = "/WEB-INF/" + resourcePath; is = ((Context) getContainer()).getServletContext().getResourceAsStream(webInfResourcePath); - if (containerLog.isDebugEnabled()) { - if (is == null) { - containerLog.debug(sm.getString("rewriteValve.noConfiguration", webInfResourcePath)); - } else { + if (is == null) { + if (containerLog.isInfoEnabled()) { + containerLog.info(sm.getString("rewriteValve.noConfiguration", webInfResourcePath)); + } + } else { + if (containerLog.isDebugEnabled()) { containerLog.debug(sm.getString("rewriteValve.readConfiguration", webInfResourcePath)); } } @@ -171,9 +174,9 @@ try { ConfigurationSource.Resource resource = ConfigFileLoader.getSource().getResource(resourceName); is = resource.getInputStream(); - } catch (IOException e) { - if (containerLog.isDebugEnabled()) { - containerLog.debug(sm.getString("rewriteValve.noConfiguration", resourceName), e); + } catch (IOException ioe) { + if (containerLog.isInfoEnabled()) { + containerLog.info(sm.getString("rewriteValve.noConfiguration", resourceName), ioe); } } } @@ -191,8 +194,8 @@ } finally { try { is.close(); - } catch (IOException e) { - containerLog.error(sm.getString("rewriteValve.closeError"), e); + } catch (IOException ioe) { + containerLog.error(sm.getString("rewriteValve.closeError"), ioe); } } @@ -202,6 +205,11 @@ if (containerLog == null) { containerLog = LogFactory.getLog(getContainer().getLogName() + ".rewrite"); } + for (RewriteMap map : maps.values()) { + if (map instanceof Lifecycle) { + ((Lifecycle) map).stop(); + } + } maps.clear(); parse(new BufferedReader(new StringReader(configuration))); } @@ -226,6 +234,7 @@ protected void parse(BufferedReader reader) throws LifecycleException { List rules = new ArrayList<>(); List conditions = new ArrayList<>(); + ArrayList mapsConfiguration = new ArrayList<>(); while (true) { try { String line = reader.readLine(); @@ -247,7 +256,7 @@ for (RewriteCond condition : conditions) { if (containerLog.isTraceEnabled()) { containerLog.trace("Add condition " + condition.getCondPattern() + " test " + - condition.getTestString() + " to rule with pattern " + rule.getPatternString() + + condition.getTestString() + " to rule with pattern " + rule.getPatternString() + " and substitution " + rule.getSubstitutionString() + (condition.isOrnext() ? " [OR]" : "") + (condition.isNocase() ? " [NC]" : "")); } @@ -268,16 +277,18 @@ ((Lifecycle) map).start(); } } - } catch (IOException e) { - containerLog.error(sm.getString("rewriteValve.readError"), e); + } catch (IOException ioe) { + containerLog.error(sm.getString("rewriteValve.readError"), ioe); } } - this.rules = rules.toArray(new RewriteRule[0]); + this.mapsConfiguration = mapsConfiguration; // Finish parsing the rules - for (RewriteRule rule : this.rules) { + for (RewriteRule rule : rules) { rule.parse(maps); } + + this.rules = rules.toArray(new RewriteRule[0]); } @Override @@ -312,13 +323,13 @@ try { - Resolver resolver = new ResolverImpl(request); + Resolver resolver = new ResolverImpl(request, containerLog); invoked.set(Boolean.TRUE); // As long as MB isn't a char sequence or affiliated, this has to be converted to a string Charset uriCharset = request.getConnector().getURICharset(); - String originalQueryStringEncoded = request.getQueryString(); + String queryStringOriginalEncoded = request.getQueryString(); MessageBytes urlMB = context ? request.getRequestPathMB() : request.getDecodedRequestURIMB(); urlMB.toChars(); CharSequence urlDecoded = urlMB.getCharChunk(); @@ -332,8 +343,6 @@ * without the two becoming confused. The re-write rules also need to be able to insert literal '%' * characters without them being confused with %nn encoding. * - * The re-write rules cannot insert path parameters. - * * To meet these requirement, the URL is processed as follows. * * Step 1. The URL is partially re-encoded by encodeForRewrite(). This method encodes any literal '%', ';' @@ -421,10 +430,10 @@ StringBuilder urlStringEncoded = new StringBuilder(REWRITE_DEFAULT_ENCODER.encode(urlStringRewriteEncoded, uriCharset)); - if (!qsd && originalQueryStringEncoded != null && !originalQueryStringEncoded.isEmpty()) { + if (!qsd && queryStringOriginalEncoded != null && !queryStringOriginalEncoded.isEmpty()) { if (rewrittenQueryStringRewriteEncoded == null) { urlStringEncoded.append('?'); - urlStringEncoded.append(originalQueryStringEncoded); + urlStringEncoded.append(queryStringOriginalEncoded); } else { if (qsa) { // if qsa is specified append the query @@ -432,7 +441,7 @@ urlStringEncoded.append( REWRITE_QUERY_ENCODER.encode(rewrittenQueryStringRewriteEncoded, uriCharset)); urlStringEncoded.append('&'); - urlStringEncoded.append(originalQueryStringEncoded); + urlStringEncoded.append(queryStringOriginalEncoded); } else if (index == urlStringEncoded.length() - 1) { // if the ? is the last character delete it, its only purpose was to // prevent the rewrite module from appending the query string @@ -456,11 +465,13 @@ if (context && urlStringEncoded.charAt(0) == '/' && !UriUtil.hasScheme(urlStringEncoded)) { urlStringEncoded.insert(0, request.getContext().getEncodedPath()); } + String redirectPath; if (rule.isNoescape()) { - response.sendRedirect(UDecoder.URLDecode(urlStringEncoded.toString(), uriCharset)); + redirectPath = UDecoder.URLDecode(urlStringEncoded.toString(), uriCharset); } else { - response.sendRedirect(urlStringEncoded.toString()); + redirectPath = urlStringEncoded.toString(); } + response.sendRedirect(response.encodeRedirectURL(redirectPath)); response.setStatus(rule.getRedirectCode()); done = true; break; @@ -528,6 +539,9 @@ queryStringRewriteEncoded = urlStringRewriteEncoded.substring(queryIndex + 1); urlStringRewriteEncoded = urlStringRewriteEncoded.substring(0, queryIndex); } + // Parse path parameters from rewrite production and populate request path parameters + urlStringRewriteEncoded = + org.apache.catalina.util.RequestUtil.stripPathParams(urlStringRewriteEncoded, request); // Save the current context path before re-writing starts String contextPath = null; if (context) { @@ -543,24 +557,31 @@ // Step 3. Complete the 2nd stage to encoding. chunk.append(REWRITE_DEFAULT_ENCODER.encode(urlStringRewriteEncoded, uriCharset)); - // Decoded and normalized URI - // Rewriting may have denormalized the URL - urlStringRewriteEncoded = RequestUtil.normalize(urlStringRewriteEncoded); + // Rewriting may have denormalized the URL and added encoded characters + // Decode then normalize + String urlStringRewriteDecoded = URLDecoder.decode(urlStringRewriteEncoded, uriCharset); + urlStringRewriteDecoded = RequestUtil.normalize(urlStringRewriteDecoded); request.getCoyoteRequest().decodedURI().setChars(MessageBytes.EMPTY_CHAR_ARRAY, 0, 0); chunk = request.getCoyoteRequest().decodedURI().getCharChunk(); if (context) { // This is decoded and normalized chunk.append(request.getServletContext().getContextPath()); } - chunk.append(URLDecoder.decode(urlStringRewriteEncoded, uriCharset)); - // Set the new Query if there is one - if (queryStringRewriteEncoded != null) { + chunk.append(urlStringRewriteDecoded); + // Set the new Query String + if (queryStringRewriteEncoded == null) { + // No new query string. Therefore the original is retained unless QSD is defined. + if (qsd) { + request.getCoyoteRequest().queryString().setChars(MessageBytes.EMPTY_CHAR_ARRAY, 0, 0); + } + } else { + // New query string. Therefore the original is dropped unless QSA is defined (and QSD is not). request.getCoyoteRequest().queryString().setChars(MessageBytes.EMPTY_CHAR_ARRAY, 0, 0); chunk = request.getCoyoteRequest().queryString().getCharChunk(); chunk.append(REWRITE_QUERY_ENCODER.encode(queryStringRewriteEncoded, uriCharset)); - if (qsa && originalQueryStringEncoded != null && !originalQueryStringEncoded.isEmpty()) { + if (qsa && queryStringOriginalEncoded != null && !queryStringOriginalEncoded.isEmpty()) { chunk.append('&'); - chunk.append(originalQueryStringEncoded); + chunk.append(queryStringOriginalEncoded); } } // Set the new host if it changed @@ -570,6 +591,7 @@ chunk.append(host.toString()); } request.getMappingData().recycle(); + request.recycleSessionInfo(); // Reinvoke the whole request recursively Connector connector = request.getConnector(); try { @@ -654,6 +676,10 @@ while (flagsTokenizer.hasMoreElements()) { parseRuleFlag(line, rule, flagsTokenizer.nextToken()); } + // If QSD and QSA are present, QSD always takes precedence + if (rule.isQsdiscard()) { + rule.setQsappend(false); + } } return rule; } else if (token.equals("RewriteMap")) { @@ -879,4 +905,6 @@ return input; } } + + } diff -Nru tomcat10-10.1.40/java/org/apache/catalina/webresources/AbstractArchiveResourceSet.java tomcat10-10.1.52/java/org/apache/catalina/webresources/AbstractArchiveResourceSet.java --- tomcat10-10.1.40/java/org/apache/catalina/webresources/AbstractArchiveResourceSet.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/webresources/AbstractArchiveResourceSet.java 2026-01-23 19:33:36.000000000 +0000 @@ -31,17 +31,21 @@ import org.apache.catalina.WebResource; import org.apache.catalina.WebResourceRoot; import org.apache.catalina.util.ResourceSet; +import org.apache.juli.logging.Log; +import org.apache.juli.logging.LogFactory; public abstract class AbstractArchiveResourceSet extends AbstractResourceSet { + private static final Log log = LogFactory.getLog(AbstractArchiveResourceSet.class); + private URL baseUrl; private String baseUrlString; - private JarFile archive = null; + protected JarFile archive = null; protected Map archiveEntries = null; protected final Object archiveLock = new Object(); - private long archiveUseCount = 0; - private JarContents jarContents; - private boolean retainBloomFilterForArchives = false; + protected long archiveUseCount = 0; + protected JarContents jarContents; + protected boolean retainBloomFilterForArchives = false; protected final void setBaseUrl(URL baseUrl) { this.baseUrl = baseUrl; @@ -68,7 +72,7 @@ String webAppMount = getWebAppMount(); ArrayList result = new ArrayList<>(); - if (path.startsWith(webAppMount)) { + if (isPathMounted(path, webAppMount)) { String pathInJar = getInternalPath() + path.substring(webAppMount.length()); // Always strip off the leading '/' to get the JAR path if (!pathInJar.isEmpty() && pathInJar.charAt(0) == '/') { @@ -108,13 +112,14 @@ return result.toArray(new String[0]); } + @Override public final Set listWebAppPaths(String path) { checkPath(path); String webAppMount = getWebAppMount(); ResourceSet result = new ResourceSet<>(); - if (path.startsWith(webAppMount)) { + if (isPathMounted(path, webAppMount)) { String pathInJar = getInternalPath() + path.substring(webAppMount.length()); // Always strip off the leading '/' to get the JAR path and make // sure it ends in '/' @@ -225,7 +230,7 @@ // If the JAR has been mounted below the web application root, return // an empty resource for requests outside of the mount point. - if (path.startsWith(webAppMount)) { + if (isPathMounted(path, webAppMount)) { String pathInJar = getInternalPath() + path.substring(webAppMount.length()); // Always strip off the leading '/' to get the JAR path if (!pathInJar.isEmpty() && pathInJar.charAt(0) == '/') { @@ -293,6 +298,25 @@ throw new IllegalArgumentException(sm.getString("abstractArchiveResourceSet.setReadOnlyFalse")); } + /** + * {@inheritDoc} + *

          + * Calls to this method will be ignored as archives do not allow linking. + */ + @Override + public void setAllowLinking(boolean allowLinking) { + } + + /** + * {@inheritDoc} + *

          + * Calls to this method always return {@code false} as archives do not allow linking. + */ + @Override + public boolean getAllowLinking() { + return false; + } + @SuppressWarnings("deprecation") protected JarFile openJarFile() throws IOException { synchronized (archiveLock) { @@ -322,8 +346,8 @@ if (archive != null && archiveUseCount == 0) { try { archive.close(); - } catch (IOException e) { - // Log at least WARN + } catch (IOException ioe) { + log.warn(sm.getString("abstractArchiveResourceSet.archiveCloseFailed"), ioe); } archive = null; archiveEntries = null; diff -Nru tomcat10-10.1.40/java/org/apache/catalina/webresources/AbstractFileResourceSet.java tomcat10-10.1.52/java/org/apache/catalina/webresources/AbstractFileResourceSet.java --- tomcat10-10.1.40/java/org/apache/catalina/webresources/AbstractFileResourceSet.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/webresources/AbstractFileResourceSet.java 2026-01-23 19:33:36.000000000 +0000 @@ -37,6 +37,7 @@ private String absoluteBase; private String canonicalBase; private boolean readOnly = false; + private Boolean allowLinking; protected AbstractFileResourceSet(String internalPath) { setInternalPath(internalPath); @@ -56,6 +57,19 @@ return readOnly; } + @Override + public void setAllowLinking(boolean allowLinking) { + this.allowLinking = Boolean.valueOf(allowLinking); + } + + @Override + public boolean getAllowLinking() { + if (allowLinking == null) { + return getRoot().getAllowLinking(); + } + return allowLinking.booleanValue(); + } + protected final File file(String name, boolean mustExist) { if (name.equals("/")) { @@ -78,12 +92,12 @@ // If allow linking is enabled, files are not limited to being located // under the fileBase so all further checks are disabled. - if (getRoot().getAllowLinking()) { + if (getAllowLinking()) { return file; } // Additional Windows specific checks to handle known problems with - // File.getCanonicalPath() + // File.getCanonicalPath() and other issues if (JrePlatform.IS_WINDOWS && isInvalidWindowsFilename(name)) { return null; } @@ -92,7 +106,7 @@ String canPath = null; try { canPath = file.getCanonicalPath(); - } catch (IOException e) { + } catch (IOException ignore) { // Ignore } if (canPath == null || !canPath.startsWith(canonicalBase)) { @@ -150,38 +164,47 @@ protected void logIgnoredSymlink(String contextPath, String absPath, String canPath) { - String msg = sm.getString("abstractFileResourceSet.canonicalfileCheckFailed", contextPath, absPath, canPath); // Log issues with configuration files at a higher level if (absPath.startsWith("/META-INF/") || absPath.startsWith("/WEB-INF/")) { - log.error(msg); + log.error(sm.getString("abstractFileResourceSet.canonicalfileCheckFailed", contextPath, absPath, canPath)); } else { - log.warn(msg); + log.warn(sm.getString("abstractFileResourceSet.canonicalfileCheckFailed", contextPath, absPath, canPath)); } } + private boolean isInvalidWindowsFilename(String name) { final int len = name.length(); if (len == 0) { return false; } - // This consistently ~10 times faster than the equivalent regular - // expression irrespective of input length. + // This is consistently ~10 times faster than the equivalent regular expression irrespective of input length. for (int i = 0; i < len; i++) { char c = name.charAt(i); - if (c == '\"' || c == '<' || c == '>' || c == ':') { - // These characters are disallowed in Windows file names and - // there are known problems for file names with these characters - // when using File#getCanonicalPath(). - // Note: There are additional characters that are disallowed in - // Windows file names but these are not known to cause - // problems when using File#getCanonicalPath(). + /* + * '\"', ':', '<' and '>' are disallowed in Windows file names and there are known problems with these + * characters when using File#getCanonicalPath(). + * + * Control characters (0x00-0x31) are not permitted and tend to be display strangely in log messages and + * similar. + * + * '*', '?' and '|' are also not allowed and, while they are not currently known to cause other + * difficulties, they are checked here rather than wasting cycles trying to find an invalid file later. + * + * The file separators ('/' and '\\') are not allowed in file names but are not excluded here as paths are + * passed to this method. + * + * Note: Characters are listed in ASCII order. + */ + if (c < 32 || c == '\"' || c == '*' || c == ':' || c == '<' || c == '>' || c == '?' || c == '|') { return true; } } - // Windows does not allow file names to end in ' ' unless specific low - // level APIs are used to create the files that bypass various checks. - // File names that end in ' ' are known to cause problems when using - // File#getCanonicalPath(). + /* + * Windows does not allow file names to end in ' ' unless specific low-level APIs are used to create the files + * that bypass various checks. File names that end in ' ' are known to cause problems when using + * File#getCanonicalPath(). + */ return name.charAt(len - 1) == ' '; } @@ -228,8 +251,8 @@ try { this.canonicalBase = fileBase.getCanonicalPath(); - } catch (IOException e) { - throw new IllegalArgumentException(e); + } catch (IOException ioe) { + throw new IllegalArgumentException(ioe); } // Need to handle mapping of the file system root as a special case @@ -243,4 +266,4 @@ protected abstract void checkType(File file); -} +} \ No newline at end of file diff -Nru tomcat10-10.1.40/java/org/apache/catalina/webresources/AbstractResource.java tomcat10-10.1.52/java/org/apache/catalina/webresources/AbstractResource.java --- tomcat10-10.1.40/java/org/apache/catalina/webresources/AbstractResource.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/webresources/AbstractResource.java 2026-01-23 19:33:36.000000000 +0000 @@ -90,7 +90,7 @@ if (contentLength <= 16 * 1024) { byte[] buf = getContent(); if (buf != null) { - buf = ConcurrentMessageDigest.digest("SHA-1", buf); + buf = ConcurrentMessageDigest.digestSHA256(buf); strongETag = "\"" + HexUtils.toHexString(buf) + "\""; } else { strongETag = getETag(); @@ -98,7 +98,7 @@ } else { byte[] buf = new byte[4096]; try (InputStream is = getInputStream()) { - MessageDigest digest = MessageDigest.getInstance("SHA-1"); + MessageDigest digest = MessageDigest.getInstance("SHA-256"); while (true) { int n = is.read(buf); if (n <= 0) { @@ -128,6 +128,14 @@ @Override public final String getMimeType() { + if (mimeType == null) { + String name = getName(); + int extensionStart = name.lastIndexOf('.'); + if (extensionStart > -1) { + String extension = name.substring(extensionStart + 1); + mimeType = root.getContext().findMimeMapping(extension); + } + } return mimeType; } diff -Nru tomcat10-10.1.40/java/org/apache/catalina/webresources/AbstractResourceSet.java tomcat10-10.1.52/java/org/apache/catalina/webresources/AbstractResourceSet.java --- tomcat10-10.1.40/java/org/apache/catalina/webresources/AbstractResourceSet.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/webresources/AbstractResourceSet.java 2026-01-23 19:33:36.000000000 +0000 @@ -71,9 +71,13 @@ public final void setWebAppMount(String webAppMount) { checkPath(webAppMount); - // Optimise internal processing - if (webAppMount.equals("/")) { - this.webAppMount = ""; + /* + * Originally, only "/" was changed to "" to allow some optimisations. The fix for CVE-2025-49125 means that + * mounted WebResourceSets will break if webAppMount ends in '/'. So now the trailing "/" is removed in all + * cases. + */ + if (webAppMount.endsWith("/")) { + this.webAppMount = webAppMount.substring(0, webAppMount.length() - 1); } else { this.webAppMount = webAppMount; } @@ -83,6 +87,18 @@ return webAppMount; } + protected boolean isPathMounted(String path, String webAppMount) { + // Doesn't call getWebAppMount() as value might have changed + if (path.startsWith(webAppMount)) { + if (path.length() != webAppMount.length() && path.charAt(webAppMount.length()) != '/') { + return false; + } + return true; + } + return false; + } + + public final void setBase(String base) { this.base = base; } diff -Nru tomcat10-10.1.40/java/org/apache/catalina/webresources/AbstractSingleArchiveResource.java tomcat10-10.1.52/java/org/apache/catalina/webresources/AbstractSingleArchiveResource.java --- tomcat10-10.1.40/java/org/apache/catalina/webresources/AbstractSingleArchiveResource.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/webresources/AbstractSingleArchiveResource.java 2026-01-23 19:33:36.000000000 +0000 @@ -38,10 +38,10 @@ JarEntry jarEntry = jarFile.getJarEntry(getResource().getName()); InputStream is = jarFile.getInputStream(jarEntry); return new JarInputStreamWrapper(jarEntry, is); - } catch (IOException e) { + } catch (IOException ioe) { if (getLog().isDebugEnabled()) { getLog().debug(sm.getString("jarResource.getInputStreamFail", getResource().getName(), getBaseUrl()), - e); + ioe); } if (jarFile != null) { getArchiveResourceSet().closeJarFile(); diff -Nru tomcat10-10.1.40/java/org/apache/catalina/webresources/Cache.java tomcat10-10.1.52/java/org/apache/catalina/webresources/Cache.java --- tomcat10-10.1.40/java/org/apache/catalina/webresources/Cache.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/webresources/Cache.java 2026-01-23 19:33:36.000000000 +0000 @@ -233,8 +233,9 @@ private boolean noCache(String path) { // Don't cache classes. The class loader handles this. // Don't cache JARs. The ResourceSet handles this. - return (path.endsWith(".class") && (path.startsWith("/WEB-INF/classes/") || path.startsWith("/WEB-INF/lib/"))) || - (path.startsWith("/WEB-INF/lib/") && path.endsWith(".jar")); + return (path.endsWith(".class") && + (path.startsWith("/WEB-INF/classes/") || path.startsWith("/WEB-INF/lib/"))) || + (path.startsWith("/WEB-INF/lib/") && path.endsWith(".jar")); } private long evict(long targetSize, Iterator iter) { diff -Nru tomcat10-10.1.40/java/org/apache/catalina/webresources/CachedResource.java tomcat10-10.1.52/java/org/apache/catalina/webresources/CachedResource.java --- tomcat10-10.1.40/java/org/apache/catalina/webresources/CachedResource.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/webresources/CachedResource.java 2026-01-23 19:33:36.000000000 +0000 @@ -296,7 +296,7 @@ if (cachedStrongETag == null) { byte[] buf = getContent(); if (buf != null) { - buf = ConcurrentMessageDigest.digest("SHA-1", buf); + buf = ConcurrentMessageDigest.digestSHA256(buf); cachedStrongETag = "\"" + HexUtils.toHexString(buf) + "\""; } else { cachedStrongETag = webResource.getStrongETag(); @@ -660,5 +660,10 @@ return ((JarURLConnection) resourceURL.openConnection()).getJarFile(); } + @Override + public String getContentType() { + // "content/unknown" is the value used by sun.net.www.URLConnection. It is used here for consistency. + return Objects.requireNonNullElse(getResource().getMimeType(), "content/unknown"); + } } } diff -Nru tomcat10-10.1.40/java/org/apache/catalina/webresources/DirResourceSet.java tomcat10-10.1.52/java/org/apache/catalina/webresources/DirResourceSet.java --- tomcat10-10.1.40/java/org/apache/catalina/webresources/DirResourceSet.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/webresources/DirResourceSet.java 2026-01-23 19:33:36.000000000 +0000 @@ -103,7 +103,7 @@ String webAppMount = getWebAppMount(); WebResourceRoot root = getRoot(); boolean readOnly = isReadOnly(); - if (path.startsWith(webAppMount)) { + if (isPathMounted(path, webAppMount)) { /* * Lock the path for reading until the WebResource has been constructed. The lock prevents concurrent reads * and writes (e.g. HTTP GET and PUT / DELETE) for the same path causing corruption of the FileResource @@ -137,7 +137,7 @@ public String[] list(String path) { checkPath(path); String webAppMount = getWebAppMount(); - if (path.startsWith(webAppMount)) { + if (isPathMounted(path, webAppMount)) { File f = file(path.substring(webAppMount.length()), true); if (f == null) { return EMPTY_STRING_ARRAY; @@ -165,15 +165,16 @@ checkPath(path); String webAppMount = getWebAppMount(); ResourceSet result = new ResourceSet<>(); - if (path.startsWith(webAppMount)) { + if (isPathMounted(path, webAppMount)) { File f = file(path.substring(webAppMount.length()), true); if (f != null) { File[] list = f.listFiles(); if (list != null) { + String fCanPath = null; for (File entry : list) { // f has already been validated so the following checks // can be much simpler than those in file() - if (!getRoot().getAllowLinking()) { + if (!getAllowLinking()) { // allow linking is disabled so need to check for // symlinks boolean symlink = true; @@ -187,7 +188,9 @@ // that what is left does not contain a symlink. absPath = entry.getAbsolutePath().substring(f.getAbsolutePath().length()); String entryCanPath = entry.getCanonicalPath(); - String fCanPath = f.getCanonicalPath(); + if (fCanPath == null) { + fCanPath = f.getCanonicalPath(); + } if (entryCanPath.length() >= fCanPath.length()) { canPath = entryCanPath.substring(fCanPath.length()); if (absPath.equals(canPath)) { @@ -239,7 +242,7 @@ return false; } String webAppMount = getWebAppMount(); - if (path.startsWith(webAppMount)) { + if (isPathMounted(path, webAppMount)) { File f = file(path.substring(webAppMount.length()), false); if (f == null) { return false; @@ -269,7 +272,7 @@ } String webAppMount = getWebAppMount(); - if (!path.startsWith(webAppMount)) { + if (!isPathMounted(path, webAppMount)) { return false; } @@ -325,8 +328,8 @@ if (mf != null && mf.isFile()) { try (FileInputStream fis = new FileInputStream(mf)) { setManifest(new Manifest(fis)); - } catch (IOException e) { - log.warn(sm.getString("dirResourceSet.manifestFail", mf.getAbsolutePath()), e); + } catch (IOException ioe) { + log.warn(sm.getString("dirResourceSet.manifestFail", mf.getAbsolutePath()), ioe); } } } diff -Nru tomcat10-10.1.40/java/org/apache/catalina/webresources/EmptyResource.java tomcat10-10.1.52/java/org/apache/catalina/webresources/EmptyResource.java --- tomcat10-10.1.40/java/org/apache/catalina/webresources/EmptyResource.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/webresources/EmptyResource.java 2026-01-23 19:33:36.000000000 +0000 @@ -99,7 +99,7 @@ } else { try { return file.getCanonicalPath(); - } catch (IOException e) { + } catch (IOException ioe) { return null; } } diff -Nru tomcat10-10.1.40/java/org/apache/catalina/webresources/EmptyResourceSet.java tomcat10-10.1.52/java/org/apache/catalina/webresources/EmptyResourceSet.java --- tomcat10-10.1.40/java/org/apache/catalina/webresources/EmptyResourceSet.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/webresources/EmptyResourceSet.java 2026-01-23 19:33:36.000000000 +0000 @@ -143,6 +143,25 @@ /** * {@inheritDoc} *

          + * Calls to this method will be ignored as this implementation does not allow linking. + */ + @Override + public void setAllowLinking(boolean allowLinking) { + } + + /** + * {@inheritDoc} + *

          + * Calls to this method always return {@code false} as this implementation does not allow linking. + */ + @Override + public boolean getAllowLinking() { + return false; + } + + /** + * {@inheritDoc} + *

          * This implementation always returns true. */ @Override diff -Nru tomcat10-10.1.40/java/org/apache/catalina/webresources/FileResource.java tomcat10-10.1.52/java/org/apache/catalina/webresources/FileResource.java --- tomcat10-10.1.40/java/org/apache/catalina/webresources/FileResource.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/webresources/FileResource.java 2026-01-23 19:33:36.000000000 +0000 @@ -267,9 +267,9 @@ try { BasicFileAttributes attrs = Files.readAttributes(resource.toPath(), BasicFileAttributes.class); return attrs.creationTime().toMillis(); - } catch (IOException e) { + } catch (IOException ioe) { if (log.isDebugEnabled()) { - log.debug(sm.getString("fileResource.getCreationFail", resource.getPath()), e); + log.debug(sm.getString("fileResource.getCreationFail", resource.getPath()), ioe); } return 0; } diff -Nru tomcat10-10.1.40/java/org/apache/catalina/webresources/JarContents.java tomcat10-10.1.52/java/org/apache/catalina/webresources/JarContents.java --- tomcat10-10.1.40/java/org/apache/catalina/webresources/JarContents.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/webresources/JarContents.java 2026-01-23 19:33:36.000000000 +0000 @@ -17,6 +17,7 @@ package org.apache.catalina.webresources; import java.util.BitSet; +import java.util.Collection; import java.util.Enumeration; import java.util.jar.JarEntry; import java.util.jar.JarFile; @@ -27,8 +28,7 @@ * from the beginning of the key. The hash methods are simple but good enough for this purpose. */ public final class JarContents { - private final BitSet bits1; - private final BitSet bits2; + /** * Constant used by a typical hashing method. */ @@ -44,6 +44,10 @@ */ private static final int TABLE_SIZE = 2048; + private final BitSet bits1 = new BitSet(TABLE_SIZE); + private final BitSet bits2 = new BitSet(TABLE_SIZE); + + /** * Parses the passed-in jar and populates the bit array. * @@ -51,52 +55,66 @@ */ public JarContents(JarFile jar) { Enumeration entries = jar.entries(); - bits1 = new BitSet(TABLE_SIZE); - bits2 = new BitSet(TABLE_SIZE); - while (entries.hasMoreElements()) { JarEntry entry = entries.nextElement(); - String name = entry.getName(); - int startPos = 0; + processEntry(entry); + } + } - // If the path starts with a slash, that's not useful information. - // Skipping it increases the significance of our key by - // removing an insignificant character. - boolean precedingSlash = name.charAt(0) == '/'; - if (precedingSlash) { - startPos = 1; - } - // Versioned entries should be added to the table according to their real name - if (name.startsWith("META-INF/versions/", startPos)) { - int i = name.indexOf('/', 18 + startPos); - if (i > 0) { - int version = Integer.parseInt(name.substring(18 + startPos, i)); - if (version <= Runtime.version().feature()) { - startPos = i + 1; - } - } - if (startPos == name.length()) { - continue; + /** + * Populates the bit array from the provided set of JAR entries. + * + * @param entries The set of entries for the JAR file being processed + */ + public JarContents(Collection entries) { + for (JarEntry entry : entries) { + processEntry(entry); + } + } + + + private void processEntry(JarEntry entry) { + String name = entry.getName(); + int startPos = 0; + + // If the path starts with a slash, that's not useful information. + // Skipping it increases the significance of our key by + // removing an insignificant character. + boolean precedingSlash = name.charAt(0) == '/'; + if (precedingSlash) { + startPos = 1; + } + + // Versioned entries should be added to the table according to their real name + if (name.startsWith("META-INF/versions/", startPos)) { + int i = name.indexOf('/', 18 + startPos); + if (i > 0) { + int version = Integer.parseInt(name.substring(18 + startPos, i)); + if (version <= Runtime.version().feature()) { + startPos = i + 1; } } + if (startPos == name.length()) { + return; + } + } - // Find the correct table slot - int pathHash1 = hashcode(name, startPos, HASH_PRIME_1); - int pathHash2 = hashcode(name, startPos, HASH_PRIME_2); + // Find the correct table slot + int pathHash1 = hashcode(name, startPos, HASH_PRIME_1); + int pathHash2 = hashcode(name, startPos, HASH_PRIME_2); + + bits1.set(pathHash1 % TABLE_SIZE); + bits2.set(pathHash2 % TABLE_SIZE); + + // While directory entry names always end in "/", application code + // may look them up without the trailing "/". Add this second form. + if (entry.isDirectory()) { + pathHash1 = hashcode(name, startPos, name.length() - 1, HASH_PRIME_1); + pathHash2 = hashcode(name, startPos, name.length() - 1, HASH_PRIME_2); bits1.set(pathHash1 % TABLE_SIZE); bits2.set(pathHash2 % TABLE_SIZE); - - // While directory entry names always end in "/", application code - // may look them up without the trailing "/". Add this second form. - if (entry.isDirectory()) { - pathHash1 = hashcode(name, startPos, name.length() - 1, HASH_PRIME_1); - pathHash2 = hashcode(name, startPos, name.length() - 1, HASH_PRIME_2); - - bits1.set(pathHash1 % TABLE_SIZE); - bits2.set(pathHash2 % TABLE_SIZE); - } } } diff -Nru tomcat10-10.1.40/java/org/apache/catalina/webresources/JarWarResource.java tomcat10-10.1.52/java/org/apache/catalina/webresources/JarWarResource.java --- tomcat10-10.1.40/java/org/apache/catalina/webresources/JarWarResource.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/webresources/JarWarResource.java 2026-01-23 19:33:36.000000000 +0000 @@ -63,9 +63,9 @@ } return new JarInputStreamWrapper(entry, jarIs); - } catch (IOException e) { + } catch (IOException ioe) { if (log.isDebugEnabled()) { - log.debug(sm.getString("jarResource.getInputStreamFail", getResource().getName(), getBaseUrl()), e); + log.debug(sm.getString("jarResource.getInputStreamFail", getResource().getName(), getBaseUrl()), ioe); } // Ensure jarIs is closed if there is an exception entry = null; diff -Nru tomcat10-10.1.40/java/org/apache/catalina/webresources/JarWarResourceSet.java tomcat10-10.1.52/java/org/apache/catalina/webresources/JarWarResourceSet.java --- tomcat10-10.1.40/java/org/apache/catalina/webresources/JarWarResourceSet.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/webresources/JarWarResourceSet.java 2026-01-23 19:33:36.000000000 +0000 @@ -28,6 +28,7 @@ import java.util.jar.JarFile; import java.util.jar.JarInputStream; import java.util.jar.Manifest; +import java.util.zip.ZipFile; import org.apache.catalina.LifecycleException; import org.apache.catalina.WebResource; @@ -141,16 +142,39 @@ if (jarFileIs != null) { try { jarFileIs.close(); - } catch (IOException e) { + } catch (IOException ignore) { // Ignore } } } } + WebResourceRoot root = getRoot(); + if (root.getArchiveIndexStrategyEnum().getUsesBloom()) { + jarContents = new JarContents(archiveEntries.values()); + retainBloomFilterForArchives = root.getArchiveIndexStrategyEnum().getRetain(); + } return archiveEntries; } } + + /** + * {@inheritDoc} + *

          + * JarWar needs to generate jarContents for the inner JAR, not the outer WAR. + */ + @Override + protected JarFile openJarFile() throws IOException { + synchronized (archiveLock) { + if (archive == null) { + archive = new JarFile(new File(getBase()), true, ZipFile.OPEN_READ, Runtime.version()); + // Don't populate JarContents here. Populate at the end of getArchiveEntries() + } + archiveUseCount++; + return archive; + } + } + protected void processArchivesEntriesForMultiRelease() { diff -Nru tomcat10-10.1.40/java/org/apache/catalina/webresources/LocalStrings.properties tomcat10-10.1.52/java/org/apache/catalina/webresources/LocalStrings.properties --- tomcat10-10.1.40/java/org/apache/catalina/webresources/LocalStrings.properties 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/webresources/LocalStrings.properties 2026-01-23 19:33:36.000000000 +0000 @@ -16,6 +16,7 @@ # Do not edit this file directly. # To edit translations see: https://tomcat.apache.org/getinvolved.html#Translations +abstractArchiveResourceSet.archiveCloseFailed=Error closing archive. Archive may still be open. abstractArchiveResourceSet.setReadOnlyFalse=Archive based WebResourceSets such as those based on JARs are hard-coded to be read-only and may not be configured to be read-write abstractFileResourceSet.canonicalfileCheckFailed=Resource for web application [{0}] at path [{1}] was not loaded as the canonical path [{2}] did not match. Use of symlinks is one possible cause. diff -Nru tomcat10-10.1.40/java/org/apache/catalina/webresources/LocalStrings_fr.properties tomcat10-10.1.52/java/org/apache/catalina/webresources/LocalStrings_fr.properties --- tomcat10-10.1.40/java/org/apache/catalina/webresources/LocalStrings_fr.properties 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/webresources/LocalStrings_fr.properties 2026-01-23 19:33:36.000000000 +0000 @@ -16,6 +16,7 @@ # Do not edit this file directly. # To edit translations see: https://tomcat.apache.org/getinvolved.html#Translations +abstractArchiveResourceSet.archiveCloseFailed=Erreur lors de la fermeture de l'archive, elle pourrait toujours être ouverte abstractArchiveResourceSet.setReadOnlyFalse=Les archives basées sur WebResourceSets telles que celles des JARs sont fixées comme étant en lecture seule et ne peuvent être configurées en lecture écriture abstractFileResourceSet.canonicalfileCheckFailed=La ressource de l''application web [{0}] du chemin [{1}] n''a pas été chargée car le chemin canonique [{2}] ne correspond pas; l''utilisation de liens symboliques peut être une cause possible diff -Nru tomcat10-10.1.40/java/org/apache/catalina/webresources/LocalStrings_ja.properties tomcat10-10.1.52/java/org/apache/catalina/webresources/LocalStrings_ja.properties --- tomcat10-10.1.40/java/org/apache/catalina/webresources/LocalStrings_ja.properties 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/webresources/LocalStrings_ja.properties 2026-01-23 19:33:36.000000000 +0000 @@ -16,6 +16,7 @@ # Do not edit this file directly. # To edit translations see: https://tomcat.apache.org/getinvolved.html#Translations +abstractArchiveResourceSet.archiveCloseFailed=アーカイブを閉じる際にエラーが発生しました。アーカイブがまだ開いている可能性があります。 abstractArchiveResourceSet.setReadOnlyFalse=JAR に基づく WebResourceSet などのアーカイブ ベースの WebResourceSet は、読み取り専用にハードコードされており、読み取り/書き込み可能に構成されていない可能性があります abstractFileResourceSet.canonicalfileCheckFailed=正規パス [{2}] が一致しなかったため、パス [{1}] のWebアプリケーション [{0}] のリソースが読み込まれませんでした。 シンボリックリンクの使用は、考えられる原因の1つです。 diff -Nru tomcat10-10.1.40/java/org/apache/catalina/webresources/LocalStrings_ru.properties tomcat10-10.1.52/java/org/apache/catalina/webresources/LocalStrings_ru.properties --- tomcat10-10.1.40/java/org/apache/catalina/webresources/LocalStrings_ru.properties 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/webresources/LocalStrings_ru.properties 2026-01-23 19:33:36.000000000 +0000 @@ -16,6 +16,8 @@ # Do not edit this file directly. # To edit translations see: https://tomcat.apache.org/getinvolved.html#Translations +dirResourceSet.notDirectory=Директория указанная по основному и внутреннему пути [{0}]{1}[{2}] не существует. + extractingRoot.targetFailed=Ошибка создания директории [{0}] для распакованных JAR файлов standardRoot.createUnknownType=Невозможно создать WebResourceSet неизвестного типа [{0}] diff -Nru tomcat10-10.1.40/java/org/apache/catalina/webresources/StandardRoot.java tomcat10-10.1.52/java/org/apache/catalina/webresources/StandardRoot.java --- tomcat10-10.1.40/java/org/apache/catalina/webresources/StandardRoot.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/webresources/StandardRoot.java 2026-01-23 19:33:36.000000000 +0000 @@ -790,7 +790,7 @@ trackedResource.getCreatedBy()); try { trackedResource.close(); - } catch (IOException e) { + } catch (IOException ignore) { // Ignore } } diff -Nru tomcat10-10.1.40/java/org/apache/catalina/webresources/TomcatJarInputStream.java tomcat10-10.1.52/java/org/apache/catalina/webresources/TomcatJarInputStream.java --- tomcat10-10.1.40/java/org/apache/catalina/webresources/TomcatJarInputStream.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/catalina/webresources/TomcatJarInputStream.java 2026-01-23 19:33:36.000000000 +0000 @@ -42,7 +42,7 @@ ZipEntry ze = super.createZipEntry(name); if (metaInfEntry == null && "META-INF/".equals(name)) { metaInfEntry = (JarEntry) ze; - } else if (manifestEntry == null && "META-INF/MANIFESR.MF".equals(name)) { + } else if (manifestEntry == null && "META-INF/MANIFEST.MF".equals(name)) { manifestEntry = (JarEntry) ze; } return ze; diff -Nru tomcat10-10.1.40/java/org/apache/coyote/AbstractProcessor.java tomcat10-10.1.52/java/org/apache/coyote/AbstractProcessor.java --- tomcat10-10.1.40/java/org/apache/coyote/AbstractProcessor.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/coyote/AbstractProcessor.java 2026-01-23 19:33:36.000000000 +0000 @@ -375,8 +375,8 @@ try { // Validate and write response headers prepareResponse(); - } catch (IOException e) { - handleIOException(e); + } catch (IOException ioe) { + handleIOException(ioe); } } break; @@ -385,8 +385,8 @@ action(ActionCode.COMMIT, null); try { finishResponse(); - } catch (IOException e) { - handleIOException(e); + } catch (IOException ioe) { + handleIOException(ioe); } break; } @@ -397,8 +397,8 @@ case EARLY_HINTS: { try { earlyHints(); - } catch (IOException e) { - handleIOException(e); + } catch (IOException ioe) { + handleIOException(ioe); } break; } @@ -406,9 +406,9 @@ action(ActionCode.COMMIT, null); try { flush(); - } catch (IOException e) { - handleIOException(e); - response.setErrorException(e); + } catch (IOException ioe) { + handleIOException(ioe); + response.setErrorException(ioe); } break; } @@ -1075,7 +1075,7 @@ // information (e.g. client IP) setSocketWrapper(socketWrapper); // Set up the minimal request information - request.setStartTimeNanos(System.nanoTime()); + request.markStartTime(); // Set up the minimal response information response.setStatus(400); response.setError(); diff -Nru tomcat10-10.1.40/java/org/apache/coyote/AbstractProtocol.java tomcat10-10.1.52/java/org/apache/coyote/AbstractProtocol.java --- tomcat10-10.1.40/java/org/apache/coyote/AbstractProtocol.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/coyote/AbstractProtocol.java 2026-01-23 19:33:36.000000000 +0000 @@ -1017,9 +1017,9 @@ } finally { try { instanceManager.destroyInstance(httpUpgradeHandler); - } catch (Throwable e) { - ExceptionUtils.handleThrowable(e); - getLog().error(sm.getString("abstractConnectionHandler.error"), e); + } catch (Throwable t) { + ExceptionUtils.handleThrowable(t); + getLog().error(sm.getString("abstractConnectionHandler.error"), t); } upgradeToken.getContextBind().unbind(false, oldCL); } @@ -1036,14 +1036,19 @@ return state; } catch (SocketException e) { // SocketExceptions are normal - getLog().debug(sm.getString("abstractConnectionHandler.socketexception.debug"), e); - } catch (IOException e) { + if (getLog().isDebugEnabled()) { + getLog().debug(sm.getString("abstractConnectionHandler.socketexception.debug"), e); + } + } catch (IOException ioe) { // IOExceptions are normal - getLog().debug(sm.getString("abstractConnectionHandler.ioexception.debug"), e); + if (getLog().isDebugEnabled()) { + getLog().debug(sm.getString("abstractConnectionHandler.ioexception.debug"), ioe); + } } catch (ProtocolException e) { - // Protocol exceptions normally mean the client sent invalid or - // incomplete data. - getLog().debug(sm.getString("abstractConnectionHandler.protocolexception.debug"), e); + // Protocol exceptions normally mean the client sent invalid or incomplete data. + if (getLog().isDebugEnabled()) { + getLog().debug(sm.getString("abstractConnectionHandler.protocolexception.debug"), e); + } } // Future developers: if you discover any other // rare-but-nonfatal exceptions, catch them here, and log as @@ -1054,12 +1059,12 @@ // Worst case, it isn't recoverable and the attempt at logging // will trigger another OOME. getLog().error(sm.getString("abstractConnectionHandler.oome"), oome); - } catch (Throwable e) { - ExceptionUtils.handleThrowable(e); + } catch (Throwable t) { + ExceptionUtils.handleThrowable(t); // any other exception or error is odd. Here we log it // with "ERROR" level, so it will show up even on // less-than-verbose logs. - getLog().error(sm.getString("abstractConnectionHandler.error"), e); + getLog().error(sm.getString("abstractConnectionHandler.error"), t); } // Make sure socket/processor is removed from the list of current diff -Nru tomcat10-10.1.40/java/org/apache/coyote/ActionCode.java tomcat10-10.1.52/java/org/apache/coyote/ActionCode.java --- tomcat10-10.1.40/java/org/apache/coyote/ActionCode.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/coyote/ActionCode.java 2026-01-23 19:33:36.000000000 +0000 @@ -22,8 +22,6 @@ * * @see ProtocolHandler * @see ActionHook - * - * @author Remy Maucherat */ public enum ActionCode { diff -Nru tomcat10-10.1.40/java/org/apache/coyote/ActionHook.java tomcat10-10.1.52/java/org/apache/coyote/ActionHook.java --- tomcat10-10.1.40/java/org/apache/coyote/ActionHook.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/coyote/ActionHook.java 2026-01-23 19:33:36.000000000 +0000 @@ -22,8 +22,6 @@ * coyote connectors. Some standard actions are defined in ActionCode, however custom actions are permitted. The param * object can be used to pass and return information related with the action. This interface is typically implemented by * ProtocolHandlers, and the param is usually a Request or Response object. - * - * @author Remy Maucherat */ public interface ActionHook { diff -Nru tomcat10-10.1.40/java/org/apache/coyote/Adapter.java tomcat10-10.1.52/java/org/apache/coyote/Adapter.java --- tomcat10-10.1.40/java/org/apache/coyote/Adapter.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/coyote/Adapter.java 2026-01-23 19:33:36.000000000 +0000 @@ -21,8 +21,6 @@ /** * Adapter. This represents the entry point in a coyote-based servlet container. * - * @author Remy Maucherat - * * @see ProtocolHandler */ public interface Adapter { diff -Nru tomcat10-10.1.40/java/org/apache/coyote/CompressionConfig.java tomcat10-10.1.52/java/org/apache/coyote/CompressionConfig.java --- tomcat10-10.1.40/java/org/apache/coyote/CompressionConfig.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/coyote/CompressionConfig.java 2026-01-23 19:33:36.000000000 +0000 @@ -206,18 +206,18 @@ Set tokens = new HashSet<>(); try { TokenList.parseTokenList(responseHeaders.values("Content-Encoding"), tokens); - } catch (IOException e) { + } catch (IOException ioe) { // Because we are using StringReader, any exception here is a // Tomcat bug. - log.warn(sm.getString("compressionConfig.ContentEncodingParseFail"), e); + log.warn(sm.getString("compressionConfig.ContentEncodingParseFail"), ioe); return false; } if (tokens.contains("identity")) { // If identity, do not do content modifications useContentEncoding = false; - } else if (tokens.contains("br") || tokens.contains("compress") || tokens.contains("dcb") - || tokens.contains("dcz") || tokens.contains("deflate") || tokens.contains("gzip") - || tokens.contains("pack200-gzip") || tokens.contains("zstd")) { + } else if (tokens.contains("br") || tokens.contains("compress") || tokens.contains("dcb") || + tokens.contains("dcz") || tokens.contains("deflate") || tokens.contains("gzip") || + tokens.contains("pack200-gzip") || tokens.contains("zstd")) { // Content should not be compressed twice return false; } diff -Nru tomcat10-10.1.40/java/org/apache/coyote/Constants.java tomcat10-10.1.52/java/org/apache/coyote/Constants.java --- tomcat10-10.1.40/java/org/apache/coyote/Constants.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/coyote/Constants.java 2026-01-23 19:33:36.000000000 +0000 @@ -21,8 +21,6 @@ /** * Constants. - * - * @author Remy Maucherat */ public final class Constants { diff -Nru tomcat10-10.1.40/java/org/apache/coyote/OutputBuffer.java tomcat10-10.1.52/java/org/apache/coyote/OutputBuffer.java --- tomcat10-10.1.40/java/org/apache/coyote/OutputBuffer.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/coyote/OutputBuffer.java 2026-01-23 19:33:36.000000000 +0000 @@ -22,8 +22,6 @@ /** * Output buffer. This class is used internally by the protocol implementation. All writes from higher level code should * happen via Response.doWrite(). - * - * @author Remy Maucherat */ public interface OutputBuffer { diff -Nru tomcat10-10.1.40/java/org/apache/coyote/ProtocolHandler.java tomcat10-10.1.52/java/org/apache/coyote/ProtocolHandler.java --- tomcat10-10.1.40/java/org/apache/coyote/ProtocolHandler.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/coyote/ProtocolHandler.java 2026-01-23 19:33:36.000000000 +0000 @@ -26,9 +26,6 @@ * Abstract the protocol implementation, including threading, etc. This is the main interface to be implemented by a * coyote protocol. Adapter is the main interface to be implemented by a coyote servlet container. * - * @author Remy Maucherat - * @author Costin Manolache - * * @see Adapter */ public interface ProtocolHandler { diff -Nru tomcat10-10.1.40/java/org/apache/coyote/Request.java tomcat10-10.1.52/java/org/apache/coyote/Request.java --- tomcat10-10.1.40/java/org/apache/coyote/Request.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/coyote/Request.java 2026-01-23 19:33:36.000000000 +0000 @@ -20,6 +20,7 @@ import java.io.StringReader; import java.io.UnsupportedEncodingException; import java.nio.charset.Charset; +import java.time.Instant; import java.util.HashMap; import java.util.Map; import java.util.Objects; @@ -34,6 +35,7 @@ import org.apache.tomcat.util.buf.B2CConverter; import org.apache.tomcat.util.buf.MessageBytes; import org.apache.tomcat.util.buf.UDecoder; +import org.apache.tomcat.util.http.Method; import org.apache.tomcat.util.http.MimeHeaders; import org.apache.tomcat.util.http.Parameters; import org.apache.tomcat.util.http.ServerCookies; @@ -50,15 +52,6 @@ *

            *
          • "org.apache.tomcat.request" - allows access to the low-level request object in trusted applications *
          - * - * @author James Duncan Davidson [duncan@eng.sun.com] - * @author James Todd [gonzo@eng.sun.com] - * @author Jason Hunter [jch@eng.sun.com] - * @author Harish Prabandham - * @author Alex Cruikshank [alex@epitonic.com] - * @author Hans Bergsten [hans@gefionsoftware.com] - * @author Costin Manolache - * @author Remy Maucherat */ public final class Request { @@ -72,8 +65,8 @@ * another 3,000,000 years before it gets back to zero). * * Local testing shows that 5, 10, 50, 500 or 1000 threads can obtain 60,000,000+ IDs a second from a single - * AtomicLong. That is about 17ns per request. It does not appear that the introduction of this counter will - * cause a bottleneck for request processing. + * AtomicLong. That is about 17ns per request. It does not appear that the introduction of this counter will cause a + * bottleneck for request processing. */ private static final AtomicLong requestIdGenerator = new AtomicLong(0); @@ -165,6 +158,7 @@ private long bytesRead = 0; // Time of the request - useful to avoid repeated calls to System.currentTime private long startTimeNanos = -1; + private Instant startInstant = null; private long threadId = 0; private int available = 0; @@ -317,10 +311,36 @@ return schemeMB; } + /** + * Get a MessageBytes instance that holds the current request's HTTP method. + * + * @return a MessageBytes instance that holds the current request's HTTP method. + * + * @deprecated Use {@link #getMethod()}, {@link Request#setMethod(String)} and {@link #setMethod(byte[], int, int)} + */ + @Deprecated public MessageBytes method() { return methodMB; } + public void setMethod(String method) { + methodMB.setString(method); + } + + public void setMethod(byte[] buf, int start, int len) { + String method = Method.bytesToString(buf, start, len); + if (method == null) { + methodMB.setBytes(buf, start, len); + method = methodMB.toStringType(); + } else { + methodMB.setString(method); + } + } + + public String getMethod() { + return methodMB.toStringType(); + } + public MessageBytes requestURI() { return uriMB; } @@ -698,21 +718,41 @@ return System.currentTimeMillis() - TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - startTimeNanos); } + public long getStartTimeNanos() { + return startTimeNanos; + } + /** * @param startTime time * - * @deprecated This setter will be removed in Tomcat 11 + * @deprecated This setter will be removed in Tomcat 11. Use {@link #markStartTime()}. */ @Deprecated public void setStartTime(long startTime) { + startTimeNanos = System.nanoTime() + TimeUnit.MILLISECONDS.toNanos(startTime - System.currentTimeMillis()); + startInstant = Instant.now(); } - public long getStartTimeNanos() { - return startTimeNanos; - } - + /** + * Set the start time using the value provided by {@code System.nanoTime()}. + * + * @param startTimeNanos The value returned from {@code System.nanoTime()} at the point the requests started. + * + * @deprecated Unused. Will be removed in Tomcat 12 onwards. Use {@link #markStartTime()}. + */ + @Deprecated public void setStartTimeNanos(long startTimeNanos) { this.startTimeNanos = startTimeNanos; + startInstant = Instant.now(); + } + + public void markStartTime() { + startTimeNanos = System.nanoTime(); + startInstant = Instant.now(); + } + + public Instant getStartInstant() { + return startInstant; } public long getThreadId() { @@ -822,6 +862,7 @@ allDataReadEventSent.set(false); startTimeNanos = -1; + startInstant = null; threadId = 0; if (hook instanceof NonPipeliningProcessor) { @@ -866,7 +907,7 @@ MediaType mediaType = null; try { mediaType = MediaType.parseMediaType(new StringReader(contentType)); - } catch (IOException e) { + } catch (IOException ioe) { // Ignore - null test below handles this } if (mediaType != null) { diff -Nru tomcat10-10.1.40/java/org/apache/coyote/RequestInfo.java tomcat10-10.1.52/java/org/apache/coyote/RequestInfo.java --- tomcat10-10.1.40/java/org/apache/coyote/RequestInfo.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/coyote/RequestInfo.java 2026-01-23 19:33:36.000000000 +0000 @@ -25,9 +25,7 @@ * Structure holding the Request and Response objects. It also holds statistical information about request processing * and provide management information about the requests being processed. Each thread uses a Request/Response pair that * is recycled on each request. This object provides a place to collect global low-level statistics - without having to - * deal with synchronization ( since each thread will have its own RequestProcessorMX ). - * - * @author Costin Manolache + * deal with synchronization (since each thread will have its own RequestProcessorMX). */ public class RequestInfo { private RequestGroupInfo global = null; @@ -65,7 +63,7 @@ // This is useful for long-running requests only public String getMethod() { - return req.method().toString(); + return req.getMethod(); } public String getCurrentUri() { @@ -261,4 +259,18 @@ public void setLastRequestProcessingTime(long lastRequestProcessingTime) { this.lastRequestProcessingTime = lastRequestProcessingTime; } + + public void recycleStatistcs() { + this.bytesSent = 0; + this.bytesReceived = 0; + + this.processingTime = 0; + this.maxTime = 0; + this.maxRequestUri = null; + + this.requestCount = 0; + this.errorCount = 0; + + this.lastRequestProcessingTime = 0; + } } diff -Nru tomcat10-10.1.40/java/org/apache/coyote/Response.java tomcat10-10.1.52/java/org/apache/coyote/Response.java --- tomcat10-10.1.40/java/org/apache/coyote/Response.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/coyote/Response.java 2026-01-23 19:33:36.000000000 +0000 @@ -41,13 +41,6 @@ /** * Response object. - * - * @author James Duncan Davidson [duncan@eng.sun.com] - * @author Jason Hunter [jch@eng.sun.com] - * @author James Todd [gonzo@eng.sun.com] - * @author Harish Prabandham - * @author Hans Bergsten [hans@gefionsoftware.com] - * @author Remy Maucherat */ public final class Response { @@ -552,7 +545,7 @@ MediaType m = null; try { m = MediaType.parseMediaType(new StringReader(type)); - } catch (IOException e) { + } catch (IOException ignore) { // Ignore - null test below handles this } if (m == null) { diff -Nru tomcat10-10.1.40/java/org/apache/coyote/ajp/AjpMessage.java tomcat10-10.1.52/java/org/apache/coyote/ajp/AjpMessage.java --- tomcat10-10.1.40/java/org/apache/coyote/ajp/AjpMessage.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/coyote/ajp/AjpMessage.java 2026-01-23 19:33:36.000000000 +0000 @@ -29,16 +29,9 @@ * A single packet for communication between the web server and the container. Designed to be reused many times with no * creation of garbage. Understands the format of data types for these packets. Can be used (somewhat confusingly) for * both incoming and outgoing packets. - * - * @author Henri Gomez - * @author Dan Milstein - * @author Keith Wannamaker - * @author Kevin Seguin - * @author Costin Manolache */ public class AjpMessage { - private static final Log log = LogFactory.getLog(AjpMessage.class); /** @@ -47,17 +40,11 @@ protected static final StringManager sm = StringManager.getManager(AjpMessage.class); - // ------------------------------------------------------------ Constructor - - public AjpMessage(int packetSize) { buf = new byte[packetSize]; } - // ----------------------------------------------------- Instance Variables - - /** * Fixed size buffer. */ @@ -78,9 +65,6 @@ protected int len; - // --------------------------------------------------------- Public Methods - - /** * Prepare this packet for accumulating a message from the container to the web server. Set the write position to * just after the header (but leave the length unwritten, because it is as yet unknown). diff -Nru tomcat10-10.1.40/java/org/apache/coyote/ajp/AjpProcessor.java tomcat10-10.1.52/java/org/apache/coyote/ajp/AjpProcessor.java --- tomcat10-10.1.40/java/org/apache/coyote/ajp/AjpProcessor.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/coyote/ajp/AjpProcessor.java 2026-01-23 19:33:36.000000000 +0000 @@ -48,6 +48,7 @@ import org.apache.tomcat.util.ExceptionUtils; import org.apache.tomcat.util.buf.ByteChunk; import org.apache.tomcat.util.buf.MessageBytes; +import org.apache.tomcat.util.http.Method; import org.apache.tomcat.util.http.MimeHeaders; import org.apache.tomcat.util.net.AbstractEndpoint.Handler.SocketState; import org.apache.tomcat.util.net.ApplicationBufferHandler; @@ -128,19 +129,17 @@ System.arraycopy(pongMessage.getBuffer(), 0, pongMessageArray, 0, pongMessage.getLen()); // Build Map of Java Servlet to Jakarta Servlet attribute names - jakartaAttributeMapping = Map.of( - "jakarta.servlet.request.cipher_suite", "jakarta.servlet.request.cipher_suite", - "jakarta.servlet.request.key_size", "jakarta.servlet.request.key_size", - "jakarta.servlet.request.ssl_session", "jakarta.servlet.request.ssl_session", - "jakarta.servlet.request.X509Certificate", "jakarta.servlet.request.X509Certificate", - "javax.servlet.request.cipher_suite", "jakarta.servlet.request.cipher_suite", - "javax.servlet.request.key_size", "jakarta.servlet.request.key_size", - "javax.servlet.request.ssl_session", "jakarta.servlet.request.ssl_session", - "javax.servlet.request.X509Certificate", "jakarta.servlet.request.X509Certificate"); - - iisTlsAttributes = Set.of( - "CERT_ISSUER", "CERT_SUBJECT", "CERT_COOKIE", "HTTPS_SERVER_SUBJECT", "CERT_FLAGS", "HTTPS_SECRETKEYSIZE", - "CERT_SERIALNUMBER", "HTTPS_SERVER_ISSUER", "HTTPS_KEYSIZE"); + jakartaAttributeMapping = Map.of("jakarta.servlet.request.cipher_suite", "jakarta.servlet.request.cipher_suite", + "jakarta.servlet.request.key_size", "jakarta.servlet.request.key_size", + "jakarta.servlet.request.ssl_session", "jakarta.servlet.request.ssl_session", + "jakarta.servlet.request.X509Certificate", "jakarta.servlet.request.X509Certificate", + "javax.servlet.request.cipher_suite", "jakarta.servlet.request.cipher_suite", + "javax.servlet.request.key_size", "jakarta.servlet.request.key_size", + "javax.servlet.request.ssl_session", "jakarta.servlet.request.ssl_session", + "javax.servlet.request.X509Certificate", "jakarta.servlet.request.X509Certificate"); + + iisTlsAttributes = Set.of("CERT_ISSUER", "CERT_SUBJECT", "CERT_COOKIE", "HTTPS_SERVER_SUBJECT", "CERT_FLAGS", + "HTTPS_SECRETKEYSIZE", "CERT_SERIALNUMBER", "HTTPS_SERVER_ISSUER", "HTTPS_KEYSIZE"); } @@ -362,11 +361,11 @@ try { socketWrapper.write(true, pongMessageArray, 0, pongMessageArray.length); socketWrapper.flush(true); - } catch (IOException e) { + } catch (IOException ioe) { if (getLog().isDebugEnabled()) { - getLog().debug(sm.getString("ajpprocessor.pongFail"), e); + getLog().debug(sm.getString("ajpprocessor.pongFail"), ioe); } - setErrorState(ErrorState.CLOSE_CONNECTION_NOW, e); + setErrorState(ErrorState.CLOSE_CONNECTION_NOW, ioe); } recycle(); continue; @@ -379,13 +378,15 @@ setErrorState(ErrorState.CLOSE_CONNECTION_NOW, null); break; } - request.setStartTimeNanos(System.nanoTime()); - } catch (IOException e) { - setErrorState(ErrorState.CLOSE_CONNECTION_NOW, e); + request.markStartTime(); + } catch (IOException ioe) { + setErrorState(ErrorState.CLOSE_CONNECTION_NOW, ioe); break; } catch (Throwable t) { ExceptionUtils.handleThrowable(t); - getLog().debug(sm.getString("ajpprocessor.header.error"), t); + if (getLog().isDebugEnabled()) { + getLog().debug(sm.getString("ajpprocessor.header.error"), t); + } // 400 - Bad Request response.setStatus(400); setErrorState(ErrorState.CLOSE_CLEAN, t); @@ -398,7 +399,9 @@ prepareRequest(); } catch (Throwable t) { ExceptionUtils.handleThrowable(t); - getLog().debug(sm.getString("ajpprocessor.request.prepare"), t); + if (getLog().isDebugEnabled()) { + getLog().debug(sm.getString("ajpprocessor.request.prepare"), t); + } // 500 - Internal Server Error response.setStatus(500); setErrorState(ErrorState.CLOSE_CLEAN, t); @@ -564,7 +567,7 @@ // Zero length message. return true; } else { - if (messageLength > message.getBuffer().length) { + if (messageLength > (buf.length - Constants.H_SIZE)) { // Message too long for the buffer // Need to trigger a 400 response String msg = sm.getString("ajpprocessor.header.tooLong", Integer.valueOf(messageLength), @@ -637,7 +640,7 @@ byte methodCode = requestHeaderMessage.getByte(); if (methodCode != Constants.SC_M_JK_STORED) { String methodName = Constants.getMethodForCode(methodCode - 1); - request.method().setString(methodName); + request.setMethod(methodName); } requestHeaderMessage.getBytes(request.protocol()); @@ -765,12 +768,12 @@ case Constants.SC_A_CONTEXT: requestHeaderMessage.getBytes(tmpMB); - // nothing + // nothing break; case Constants.SC_A_SERVLET_PATH: requestHeaderMessage.getBytes(tmpMB); - // nothing + // nothing break; case Constants.SC_A_REMOTE_USER: @@ -801,7 +804,7 @@ case Constants.SC_A_JVM_ROUTE: requestHeaderMessage.getBytes(tmpMB); - // nothing + // nothing break; case Constants.SC_A_SSL_CERT: @@ -824,7 +827,9 @@ break; case Constants.SC_A_STORED_METHOD: - requestHeaderMessage.getBytes(request.method()); + requestHeaderMessage.getBytes(tmpMB); + ByteChunk tmpBC = tmpMB.getByteChunk(); + request.setMethod(tmpBC.getBytes(), tmpBC.getStart(), tmpBC.getLength()); break; case Constants.SC_A_SECRET: @@ -839,7 +844,7 @@ break; default: - // Ignore unknown attribute for backward compatibility + // Ignore unknown attribute for backward compatibility break; } @@ -892,9 +897,9 @@ protected void populateHost() { try { request.serverName().duplicate(request.localName()); - } catch (IOException e) { + } catch (IOException ioe) { response.setStatus(400); - setErrorState(ErrorState.CLOSE_CLEAN, e); + setErrorState(ErrorState.CLOSE_CLEAN, ioe); } } @@ -922,7 +927,7 @@ // Responses with certain status codes and/or methods are not permitted to include a response body. int statusCode = response.getStatus(); if (statusCode < 200 || statusCode == 204 || statusCode == 205 || statusCode == 304 || - request.method().equals("HEAD")) { + Method.HEAD.equals(request.getMethod())) { // No entity body swallowResponse = true; } @@ -1055,10 +1060,12 @@ if (empty && doRead) { try { refillReadBuffer(false); - } catch (IOException timeout) { - // Not ideal. This will indicate that data is available - // which should trigger a read which in turn will trigger - // another IOException and that one can be thrown. + } catch (IOException ioe) { + /* + * Probably a timeout. This approach isn't ideal but it works. Returning 1 will indicate that data is + * available which should trigger a read which in turn will trigger another IOException and that one can + * be thrown. + */ return 1; } } @@ -1300,8 +1307,8 @@ // Validate and write response headers try { prepareResponse(); - } catch (IOException e) { - setErrorState(ErrorState.CLOSE_CONNECTION_NOW, e); + } catch (IOException ioe) { + setErrorState(ErrorState.CLOSE_CONNECTION_NOW, ioe); } } diff -Nru tomcat10-10.1.40/java/org/apache/coyote/ajp/Constants.java tomcat10-10.1.52/java/org/apache/coyote/ajp/Constants.java --- tomcat10-10.1.40/java/org/apache/coyote/ajp/Constants.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/coyote/ajp/Constants.java 2026-01-23 19:33:36.000000000 +0000 @@ -19,10 +19,10 @@ import java.util.HashMap; import java.util.Map; +import org.apache.tomcat.util.http.Method; + /** * Constants. - * - * @author Remy Maucherat */ public final class Constants { @@ -104,10 +104,10 @@ public static final int MAX_SEND_SIZE = MAX_PACKET_SIZE - SEND_HEAD_LEN; // Translates integer codes to names of HTTP methods - private static final String[] methodTransArray = - { "OPTIONS", "GET", "HEAD", "POST", "PUT", "DELETE", "TRACE", "PROPFIND", "PROPPATCH", "MKCOL", "COPY", - "MOVE", "LOCK", "UNLOCK", "ACL", "REPORT", "VERSION-CONTROL", "CHECKIN", "CHECKOUT", "UNCHECKOUT", - "SEARCH", "MKWORKSPACE", "UPDATE", "LABEL", "MERGE", "BASELINE-CONTROL", "MKACTIVITY" }; + private static final String[] methodTransArray = { Method.OPTIONS, Method.GET, Method.HEAD, Method.POST, Method.PUT, + Method.DELETE, Method.TRACE, Method.PROPFIND, Method.PROPPATCH, Method.MKCOL, Method.COPY, Method.MOVE, + Method.LOCK, Method.UNLOCK, "ACL", "REPORT", "VERSION-CONTROL", "CHECKIN", "CHECKOUT", "UNCHECKOUT", + "SEARCH", "MKWORKSPACE", "UPDATE", "LABEL", "MERGE", "BASELINE-CONTROL", "MKACTIVITY" }; /** * Converts an AJP coded HTTP method to the method name. @@ -172,12 +172,8 @@ private static final Map responseTransMap = new HashMap<>(20); static { - try { - for (int i = 0; i < SC_RESP_AJP13_MAX; i++) { - responseTransMap.put(getResponseHeaderForCode(i), Integer.valueOf(0xA001 + i)); - } - } catch (Exception e) { - // Do nothing + for (int i = 0; i < SC_RESP_AJP13_MAX; i++) { + responseTransMap.put(getResponseHeaderForCode(i), Integer.valueOf(0xA001 + i)); } } diff -Nru tomcat10-10.1.40/java/org/apache/coyote/http11/AbstractHttp11Protocol.java tomcat10-10.1.52/java/org/apache/coyote/http11/AbstractHttp11Protocol.java --- tomcat10-10.1.40/java/org/apache/coyote/http11/AbstractHttp11Protocol.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/coyote/http11/AbstractHttp11Protocol.java 2026-01-23 19:33:36.000000000 +0000 @@ -562,7 +562,7 @@ } public boolean isTrailerHeaderAllowed(String headerName) { - return allowedTrailerHeaders.contains(headerName); + return allowedTrailerHeaders.contains(headerName.trim().toLowerCase(Locale.ENGLISH)); } public String getAllowedTrailerHeaders() { @@ -792,6 +792,10 @@ } + public boolean checkSni(String sniHostName, String protocolHostName) { + return getEndpoint().checkSni(sniHostName, protocolHostName); + } + // ------------------------------------------------------------- Common code @Override diff -Nru tomcat10-10.1.40/java/org/apache/coyote/http11/Constants.java tomcat10-10.1.52/java/org/apache/coyote/http11/Constants.java --- tomcat10-10.1.40/java/org/apache/coyote/http11/Constants.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/coyote/http11/Constants.java 2026-01-23 19:33:36.000000000 +0000 @@ -20,8 +20,6 @@ /** * Constants. - * - * @author Remy Maucherat */ public final class Constants { diff -Nru tomcat10-10.1.40/java/org/apache/coyote/http11/Http11InputBuffer.java tomcat10-10.1.52/java/org/apache/coyote/http11/Http11InputBuffer.java --- tomcat10-10.1.40/java/org/apache/coyote/http11/Http11InputBuffer.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/coyote/http11/Http11InputBuffer.java 2026-01-23 19:33:36.000000000 +0000 @@ -366,7 +366,7 @@ // just skipping blank lines) if (parsingRequestLinePhase == 0) { parsingRequestLinePhase = 1; - request.setStartTimeNanos(System.nanoTime()); + request.markStartTime(); } chr = byteBuffer.get(); } while (chr == Constants.CR || chr == Constants.LF); @@ -394,8 +394,7 @@ chr = byteBuffer.get(); if (chr == Constants.SP || chr == Constants.HT) { space = true; - request.method().setBytes(byteBuffer.array(), parsingRequestLineStart, - pos - parsingRequestLineStart); + request.setMethod(byteBuffer.array(), parsingRequestLineStart, pos - parsingRequestLineStart); } else if (!HttpParser.isToken(chr)) { // Avoid unknown protocol triggering an additional error request.protocol().setString(Constants.HTTP_11); diff -Nru tomcat10-10.1.40/java/org/apache/coyote/http11/Http11Processor.java tomcat10-10.1.52/java/org/apache/coyote/http11/Http11Processor.java --- tomcat10-10.1.40/java/org/apache/coyote/http11/Http11Processor.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/coyote/http11/Http11Processor.java 2026-01-23 19:33:36.000000000 +0000 @@ -55,6 +55,7 @@ import org.apache.tomcat.util.buf.ByteChunk; import org.apache.tomcat.util.buf.MessageBytes; import org.apache.tomcat.util.http.FastHttpDateFormat; +import org.apache.tomcat.util.http.Method; import org.apache.tomcat.util.http.MimeHeaders; import org.apache.tomcat.util.http.parser.HttpParser; import org.apache.tomcat.util.http.parser.TokenList; @@ -302,11 +303,11 @@ socketWrapper.setReadTimeout(protocol.getConnectionUploadTimeout()); } } - } catch (IOException e) { + } catch (IOException ioe) { if (log.isDebugEnabled()) { - log.debug(sm.getString("http11processor.header.parse"), e); + log.debug(sm.getString("http11processor.header.parse"), ioe); } - setErrorState(ErrorState.CLOSE_CONNECTION_NOW, e); + setErrorState(ErrorState.CLOSE_CONNECTION_NOW, ioe); break; } catch (Throwable t) { ExceptionUtils.handleThrowable(t); @@ -503,7 +504,7 @@ // Transfer the minimal information required for the copy of the Request // that is passed to the HTTP upgrade process dest.decodedURI().duplicate(source.decodedURI()); - dest.method().duplicate(source.method()); + dest.setMethod(source.getMethod()); dest.getMimeHeaders().duplicate(source.getMimeHeaders()); dest.requestURI().duplicate(source.requestURI()); dest.queryString().duplicate(source.queryString()); @@ -576,7 +577,7 @@ long contentLength = -1; try { contentLength = request.getContentLengthLong(); - } catch (Exception e) { + } catch (Exception ignore) { // Ignore, an error here is already processed in prepareRequest // but is done again since the content length is still -1 } @@ -608,6 +609,11 @@ http09 = true; http11 = false; keepAlive = false; + if (!Method.GET.equals(request.getMethod())) { + // Send 400, GET is the only allowed method for HTTP/0.9 + response.setStatus(400); + setErrorState(ErrorState.CLOSE_CLEAN, null); + } } else { // Unsupported protocol http09 = false; @@ -758,7 +764,7 @@ try { hostValueMB = headers.setValue("host"); hostValueMB.setBytes(uriB, uriBCStart + pos, slashPos - pos); - } catch (IllegalStateException e) { + } catch (IllegalStateException ignore) { // Edge case // If the request has too many headers it won't be // possible to create the host header. Ignore this as @@ -786,6 +792,11 @@ // Validate host name and extract port if present parseHost(hostValueMB); + // Match host name with SNI if required + if (!protocol.checkSni(socketWrapper.getSniHostName(), request.serverName().toString())) { + badRequest("http11processor.request.sni"); + } + if (!getErrorState().isIoAllowed()) { getAdapter().log(request, response, 0); } @@ -902,8 +913,7 @@ } } - MessageBytes methodMB = request.method(); - boolean head = methodMB.equals("HEAD"); + boolean head = Method.HEAD.equals(request.getMethod()); if (head) { // Any entity body, if present, should not be sent outputBuffer.addActiveFilter(outputFilters[Constants.VOID_FILTER]); @@ -1163,6 +1173,8 @@ endRequest(); inputBuffer.nextRequest(); outputBuffer.nextRequest(); + // Set keep alive timeout for next request + socketWrapper.setReadTimeout(protocol.getKeepAliveTimeout()); if (socketWrapper.isReadPending()) { return SocketState.LONG; } else { @@ -1205,8 +1217,8 @@ if (getErrorState().isIoAllowed()) { try { inputBuffer.endRequest(); - } catch (IOException e) { - setErrorState(ErrorState.CLOSE_CONNECTION_NOW, e); + } catch (IOException ioe) { + setErrorState(ErrorState.CLOSE_CONNECTION_NOW, ioe); } catch (Throwable t) { ExceptionUtils.handleThrowable(t); // 500 - Internal Server Error @@ -1221,8 +1233,8 @@ try { action(ActionCode.COMMIT, null); outputBuffer.end(); - } catch (IOException e) { - setErrorState(ErrorState.CLOSE_CONNECTION_NOW, e); + } catch (IOException ioe) { + setErrorState(ErrorState.CLOSE_CONNECTION_NOW, ioe); } catch (Throwable t) { ExceptionUtils.handleThrowable(t); setErrorState(ErrorState.CLOSE_NOW, t); @@ -1250,8 +1262,8 @@ if (!response.isCommitted() && request.hasExpectation()) { try { outputBuffer.sendAck(); - } catch (IOException e) { - setErrorState(ErrorState.CLOSE_CONNECTION_NOW, e); + } catch (IOException ioe) { + setErrorState(ErrorState.CLOSE_CONNECTION_NOW, ioe); } } } diff -Nru tomcat10-10.1.40/java/org/apache/coyote/http11/InputFilter.java tomcat10-10.1.52/java/org/apache/coyote/http11/InputFilter.java --- tomcat10-10.1.40/java/org/apache/coyote/http11/InputFilter.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/coyote/http11/InputFilter.java 2026-01-23 19:33:36.000000000 +0000 @@ -24,8 +24,6 @@ /** * Input filter interface. - * - * @author Remy Maucherat */ public interface InputFilter extends InputBuffer { diff -Nru tomcat10-10.1.40/java/org/apache/coyote/http11/LocalStrings.properties tomcat10-10.1.52/java/org/apache/coyote/http11/LocalStrings.properties --- tomcat10-10.1.40/java/org/apache/coyote/http11/LocalStrings.properties 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/coyote/http11/LocalStrings.properties 2026-01-23 19:33:36.000000000 +0000 @@ -39,6 +39,7 @@ http11processor.request.nonNumericContentLength=The request contained a content-length header with a non-numeric value http11processor.request.prepare=Error preparing request http11processor.request.process=Error processing request +http11processor.request.sni=The host header does not match the SNI host http11processor.request.unsupportedEncoding=Error preparing request, unsupported transfer encoding [{0}] http11processor.request.unsupportedVersion=Error preparing request, unsupported HTTP version [{0}] http11processor.response.finish=Error finishing response diff -Nru tomcat10-10.1.40/java/org/apache/coyote/http11/OutputFilter.java tomcat10-10.1.52/java/org/apache/coyote/http11/OutputFilter.java --- tomcat10-10.1.40/java/org/apache/coyote/http11/OutputFilter.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/coyote/http11/OutputFilter.java 2026-01-23 19:33:36.000000000 +0000 @@ -20,8 +20,6 @@ /** * Output filter. - * - * @author Remy Maucherat */ public interface OutputFilter extends HttpOutputBuffer { diff -Nru tomcat10-10.1.40/java/org/apache/coyote/http11/filters/ChunkedInputFilter.java tomcat10-10.1.52/java/org/apache/coyote/http11/filters/ChunkedInputFilter.java --- tomcat10-10.1.40/java/org/apache/coyote/http11/filters/ChunkedInputFilter.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/coyote/http11/filters/ChunkedInputFilter.java 2026-01-23 19:33:36.000000000 +0000 @@ -20,6 +20,7 @@ import java.nio.ByteBuffer; import java.nio.charset.StandardCharsets; import java.util.Set; +import java.util.concurrent.atomic.AtomicLong; import org.apache.coyote.ActionCode; import org.apache.coyote.BadRequestException; @@ -38,8 +39,6 @@ /** * Chunked input filter. Parses chunked data according to http://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.6.1
          - * - * @author Remy Maucherat */ public class ChunkedInputFilter implements InputFilter, ApplicationBufferHandler, HeaderDataSource { @@ -108,7 +107,7 @@ private volatile boolean crFound = false; private volatile int chunkSizeDigitsRead = 0; private volatile boolean parsingExtension = false; - private volatile long extensionSize; + private final AtomicLong extensionSize = new AtomicLong(0); private final HttpHeaderParser httpHeaderParser; // ----------------------------------------------------------- Constructors @@ -253,7 +252,7 @@ crFound = false; chunkSizeDigitsRead = 0; parsingExtension = false; - extensionSize = 0; + extensionSize.set(0); httpHeaderParser.recycle(); } @@ -367,7 +366,7 @@ // semicolons may appear to separate multiple chunk-extensions. // These need to be processed as part of parsing the extensions. parsingExtension = true; - extensionSize++; + extensionSize.incrementAndGet(); } else if (!parsingExtension) { int charValue = HexUtils.getDec(chr); if (charValue != -1 && chunkSizeDigitsRead < 8) { @@ -381,8 +380,8 @@ // Extension 'parsing' // Note that the chunk-extension is neither parsed nor // validated. Currently it is simply ignored. - extensionSize++; - if (maxExtensionSize > -1 && extensionSize > maxExtensionSize) { + long extSize = extensionSize.incrementAndGet(); + if (maxExtensionSize > -1 && extSize > maxExtensionSize) { throwBadRequestException(sm.getString("chunkedInputFilter.maxExtension")); } } @@ -430,7 +429,7 @@ // semicolons may appear to separate multiple chunk-extensions. // These need to be processed as part of parsing the extensions. parsingExtension = true; - extensionSize++; + extensionSize.incrementAndGet(); } else if (!parsingExtension) { int charValue = HexUtils.getDec(chr); if (charValue != -1 && chunkSizeDigitsRead < 8) { @@ -444,8 +443,8 @@ // Extension 'parsing' // Note that the chunk-extension is neither parsed nor // validated. Currently it is simply ignored. - extensionSize++; - if (maxExtensionSize > -1 && extensionSize > maxExtensionSize) { + long extSize = extensionSize.incrementAndGet(); + if (maxExtensionSize > -1 && extSize > maxExtensionSize) { return false; } } @@ -505,7 +504,7 @@ /** * Parse CRLF at end of chunk. * - * @return {@code true} if the read is complete or {@code false if incomplete}. In complete reads can only happen + * @return {@code true} if the read is complete or {@code false if incomplete}. Incomplete reads can only happen * with non-blocking I/O. * * @throws IOException An error occurred parsing CRLF diff -Nru tomcat10-10.1.40/java/org/apache/coyote/http11/filters/ChunkedOutputFilter.java tomcat10-10.1.52/java/org/apache/coyote/http11/filters/ChunkedOutputFilter.java --- tomcat10-10.1.40/java/org/apache/coyote/http11/filters/ChunkedOutputFilter.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/coyote/http11/filters/ChunkedOutputFilter.java 2026-01-23 19:33:36.000000000 +0000 @@ -34,8 +34,6 @@ /** * Chunked output filter. - * - * @author Remy Maucherat */ public class ChunkedOutputFilter implements OutputFilter { diff -Nru tomcat10-10.1.40/java/org/apache/coyote/http11/filters/GzipOutputFilter.java tomcat10-10.1.52/java/org/apache/coyote/http11/filters/GzipOutputFilter.java --- tomcat10-10.1.40/java/org/apache/coyote/http11/filters/GzipOutputFilter.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/coyote/http11/filters/GzipOutputFilter.java 2026-01-23 19:33:36.000000000 +0000 @@ -30,8 +30,6 @@ /** * Gzip output filter. - * - * @author Remy Maucherat */ public class GzipOutputFilter implements OutputFilter { @@ -98,9 +96,9 @@ log.trace("Flushing the compression stream!"); } compressionStream.flush(); - } catch (IOException e) { + } catch (IOException ioe) { if (log.isDebugEnabled()) { - log.debug(sm.getString("gzipOutputFilter.flushFail"), e); + log.debug(sm.getString("gzipOutputFilter.flushFail"), ioe); } } } diff -Nru tomcat10-10.1.40/java/org/apache/coyote/http11/filters/IdentityInputFilter.java tomcat10-10.1.52/java/org/apache/coyote/http11/filters/IdentityInputFilter.java --- tomcat10-10.1.40/java/org/apache/coyote/http11/filters/IdentityInputFilter.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/coyote/http11/filters/IdentityInputFilter.java 2026-01-23 19:33:36.000000000 +0000 @@ -29,8 +29,6 @@ /** * Identity input filter. - * - * @author Remy Maucherat */ public class IdentityInputFilter implements InputFilter, ApplicationBufferHandler { diff -Nru tomcat10-10.1.40/java/org/apache/coyote/http11/filters/IdentityOutputFilter.java tomcat10-10.1.52/java/org/apache/coyote/http11/filters/IdentityOutputFilter.java --- tomcat10-10.1.40/java/org/apache/coyote/http11/filters/IdentityOutputFilter.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/coyote/http11/filters/IdentityOutputFilter.java 2026-01-23 19:33:36.000000000 +0000 @@ -25,8 +25,6 @@ /** * Identity output filter. - * - * @author Remy Maucherat */ public class IdentityOutputFilter implements OutputFilter { diff -Nru tomcat10-10.1.40/java/org/apache/coyote/http11/filters/SavedRequestInputFilter.java tomcat10-10.1.52/java/org/apache/coyote/http11/filters/SavedRequestInputFilter.java --- tomcat10-10.1.40/java/org/apache/coyote/http11/filters/SavedRequestInputFilter.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/coyote/http11/filters/SavedRequestInputFilter.java 2026-01-23 19:33:36.000000000 +0000 @@ -49,11 +49,10 @@ return -1; } - ByteBuffer byteBuffer = handler.getByteBuffer(); - byteBuffer.position(byteBuffer.limit()).limit(byteBuffer.capacity()); - input.subtract(byteBuffer); - - return byteBuffer.remaining(); + int len = input.getLength(); + handler.setByteBuffer(ByteBuffer.wrap(input.getBytes(), input.getStart(), len)); + input.setStart(input.getEnd()); + return len; } /** diff -Nru tomcat10-10.1.40/java/org/apache/coyote/http11/filters/VoidInputFilter.java tomcat10-10.1.52/java/org/apache/coyote/http11/filters/VoidInputFilter.java --- tomcat10-10.1.40/java/org/apache/coyote/http11/filters/VoidInputFilter.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/coyote/http11/filters/VoidInputFilter.java 2026-01-23 19:33:36.000000000 +0000 @@ -27,8 +27,6 @@ /** * Void input filter, which returns -1 when attempting a read. Used with a GET, HEAD, or a similar request. - * - * @author Remy Maucherat */ public class VoidInputFilter implements InputFilter { diff -Nru tomcat10-10.1.40/java/org/apache/coyote/http11/filters/VoidOutputFilter.java tomcat10-10.1.52/java/org/apache/coyote/http11/filters/VoidOutputFilter.java --- tomcat10-10.1.40/java/org/apache/coyote/http11/filters/VoidOutputFilter.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/coyote/http11/filters/VoidOutputFilter.java 2026-01-23 19:33:36.000000000 +0000 @@ -25,8 +25,6 @@ /** * Void output filter, which silently swallows bytes written. Used with a 204 status (no content) or a HEAD request. - * - * @author Remy Maucherat */ public class VoidOutputFilter implements OutputFilter { diff -Nru tomcat10-10.1.40/java/org/apache/coyote/http11/upgrade/UpgradeServletInputStream.java tomcat10-10.1.52/java/org/apache/coyote/http11/upgrade/UpgradeServletInputStream.java --- tomcat10-10.1.40/java/org/apache/coyote/http11/upgrade/UpgradeServletInputStream.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/coyote/http11/upgrade/UpgradeServletInputStream.java 2026-01-23 19:33:36.000000000 +0000 @@ -79,8 +79,8 @@ try { ready = Boolean.valueOf(socketWrapper.isReadyForRead()); - } catch (IOException e) { - onError(e); + } catch (IOException ioe) { + onError(ioe); } return ready.booleanValue(); } @@ -213,8 +213,8 @@ if (listener == null || !socketWrapper.isReadyForRead()) { return; } - } catch (IOException e) { - onError(e); + } catch (IOException ioe) { + onError(ioe); } ready = Boolean.TRUE; ClassLoader oldCL = processor.getUpgradeToken().getContextBind().bind(false, null); diff -Nru tomcat10-10.1.40/java/org/apache/coyote/http2/AbstractNonZeroStream.java tomcat10-10.1.52/java/org/apache/coyote/http2/AbstractNonZeroStream.java --- tomcat10-10.1.40/java/org/apache/coyote/http2/AbstractNonZeroStream.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/coyote/http2/AbstractNonZeroStream.java 2026-01-23 19:33:36.000000000 +0000 @@ -85,9 +85,9 @@ /** * Notify that some data has been received. * - * @param payloadSize the byte count + * @param dataLength the byte count * * @throws Http2Exception if an error is detected */ - abstract void receivedData(int payloadSize) throws Http2Exception; + abstract void receivedData(int dataLength) throws Http2Exception; } diff -Nru tomcat10-10.1.40/java/org/apache/coyote/http2/ConnectionSettingsBase.java tomcat10-10.1.52/java/org/apache/coyote/http2/ConnectionSettingsBase.java --- tomcat10-10.1.40/java/org/apache/coyote/http2/ConnectionSettingsBase.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/coyote/http2/ConnectionSettingsBase.java 2026-01-23 19:33:36.000000000 +0000 @@ -66,6 +66,11 @@ final void set(Setting setting, long value) throws T { + set(setting, value, false); + } + + + final void set(Setting setting, long value, boolean force) throws T { if (log.isTraceEnabled()) { log.trace(sm.getString("connectionSettings.debug", connectionId, getEndpointName(), setting, Long.toString(value))); @@ -102,11 +107,21 @@ return; } - set(setting, Long.valueOf(value)); + set(setting, Long.valueOf(value), force); } - synchronized void set(Setting setting, Long value) { + /** + * Specify a new value for setting with the option to force the change to take effect immediately rather than + * waiting until an {@code ACK} is received. + * + * @param setting The setting to update + * @param value The new value for the setting + * @param force {@code false} if an {@code ACK} must be received before the setting takes effect or {@code true} + * if the setting to take effect immediately. Even if the setting takes effect immediately, it + * will still be included in the next {@code SETTINGS} frame and an {@code ACK} will be expected. + */ + synchronized void set(Setting setting, Long value, boolean force) { current.put(setting, value); } diff -Nru tomcat10-10.1.40/java/org/apache/coyote/http2/ConnectionSettingsLocal.java tomcat10-10.1.52/java/org/apache/coyote/http2/ConnectionSettingsLocal.java --- tomcat10-10.1.40/java/org/apache/coyote/http2/ConnectionSettingsLocal.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/coyote/http2/ConnectionSettingsLocal.java 2026-01-23 19:33:36.000000000 +0000 @@ -40,12 +40,15 @@ @Override - final synchronized void set(Setting setting, Long value) { + final synchronized void set(Setting setting, Long value, boolean force) { checkSend(); if (current.get(setting).longValue() == value.longValue()) { pending.remove(setting); } else { pending.put(setting, value); + if (force) { + current.put(setting, value); + } } } diff -Nru tomcat10-10.1.40/java/org/apache/coyote/http2/Hpack.java tomcat10-10.1.52/java/org/apache/coyote/http2/Hpack.java --- tomcat10-10.1.40/java/org/apache/coyote/http2/Hpack.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/coyote/http2/Hpack.java 2026-01-23 19:33:36.000000000 +0000 @@ -18,6 +18,7 @@ import java.nio.ByteBuffer; +import org.apache.tomcat.util.http.Method; import org.apache.tomcat.util.res.StringManager; final class Hpack { @@ -26,8 +27,16 @@ private static final byte LOWER_DIFF = 'a' - 'A'; static final int DEFAULT_TABLE_SIZE = 4096; - private static final int MAX_INTEGER_OCTETS = 8; // not sure what a good value for this is, but the spec says we - // need to provide an upper bound + /* + * The HPack specification says there SHOULD be an upper bound on this. + * + * Tomcat has opted to limit values to INTEGER.MAX_VALUE. Give that there is the prefix byte and then each octet + * provides up to 7-bits, a total a 5 octets plus the prefix may be required. + * + * Note: The maximum value represented by 5 octets is greater than INTEGER.MAX_VALUE. + * + */ + private static final int MAX_INTEGER_OCTETS = 5; /** * table that contains powers of two, used as both bitmask and to quickly calculate 2^n @@ -52,8 +61,8 @@ HeaderField[] fields = new HeaderField[62]; // note that zero is not used fields[1] = new HeaderField(":authority", null); - fields[2] = new HeaderField(":method", "GET"); - fields[3] = new HeaderField(":method", "POST"); + fields[2] = new HeaderField(":method", Method.GET); + fields[3] = new HeaderField(":method", Method.POST); fields[4] = new HeaderField(":path", "/"); fields[5] = new HeaderField(":path", "/index.html"); fields[6] = new HeaderField(":scheme", "http"); @@ -151,10 +160,12 @@ int sp = source.position(); int mask = PREFIX_TABLE[n]; - int i = mask & source.get(); + // Use long internally as the value may exceed Integer.MAX_VALUE + long result = mask & source.get(); int b; - if (i < PREFIX_TABLE[n]) { - return i; + if (result < PREFIX_TABLE[n]) { + // Casting is safe as result must be less than 255 at this point. + return (int) result; } else { int m = 0; do { @@ -169,11 +180,15 @@ return -1; } b = source.get(); - i = i + (b & 127) * (PREFIX_TABLE[m] + 1); + result = result + (b & 127) * (PREFIX_TABLE[m] + 1L); + if (result > Integer.MAX_VALUE) { + throw new HpackException(sm.getString("hpack.integerEncodedTooBig")); + } m += 7; } while ((b & 128) == 128); } - return i; + // Casting is safe as result must be less than Integer.MAX_VALUE at this point + return (int) result; } /** diff -Nru tomcat10-10.1.40/java/org/apache/coyote/http2/HpackDecoder.java tomcat10-10.1.52/java/org/apache/coyote/http2/HpackDecoder.java --- tomcat10-10.1.40/java/org/apache/coyote/http2/HpackDecoder.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/coyote/http2/HpackDecoder.java 2026-01-23 19:33:36.000000000 +0000 @@ -380,10 +380,9 @@ /** * Are the headers pass to the recipient so far valid? The decoder needs to process all the headers to maintain - * state even if there is a problem. In addition, it is easy for the intended recipient to track if the - * complete set of headers is valid since to do that state needs to be maintained between the parsing of the - * initial headers and the parsing of any trailer headers. The recipient is the best place to maintain that - * state. + * state even if there is a problem. In addition, it is easy for the intended recipient to track if the complete + * set of headers is valid since to do that state needs to be maintained between the parsing of the initial + * headers and the parsing of any trailer headers. The recipient is the best place to maintain that state. * * @throws StreamException If the headers received to date are not valid */ diff -Nru tomcat10-10.1.40/java/org/apache/coyote/http2/Http2AsyncUpgradeHandler.java tomcat10-10.1.52/java/org/apache/coyote/http2/Http2AsyncUpgradeHandler.java --- tomcat10-10.1.40/java/org/apache/coyote/http2/Http2AsyncUpgradeHandler.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/coyote/http2/Http2AsyncUpgradeHandler.java 2026-01-23 19:33:36.000000000 +0000 @@ -132,6 +132,10 @@ log.trace(sm.getString("upgradeHandler.rst.debug", connectionId, Integer.toString(se.getStreamId()), se.getError(), se.getMessage())); } + + // Treat a sent reset like a received reset and increment the overhead count + increaseOverheadCount(FrameType.RST, getProtocol().getOverheadResetFactor()); + // Write a RST frame byte[] rstFrame = new byte[13]; // Length @@ -335,7 +339,7 @@ (int) (sendfile.end - sendfile.pos); sendfile.streamReservation = sendfile.stream.reserveWindowSize(reservation, true); sendfile.connectionReservation = reserveWindowSize(sendfile.stream, sendfile.streamReservation, true); - } catch (IOException e) { + } catch (IOException ioe) { return SendfileState.ERROR; } @@ -372,7 +376,7 @@ ByteBuffer.wrap(header), sendfile.mappedBuffer); try { handleAsyncException(); - } catch (IOException e) { + } catch (IOException ioe) { return SendfileState.ERROR; } } @@ -397,8 +401,8 @@ if (sendfile.left == 0) { try { sendfile.stream.getOutputBuffer().end(); - } catch (IOException e) { - failed(e, sendfile); + } catch (IOException ioe) { + failed(ioe, sendfile); } return; } @@ -415,8 +419,8 @@ sendfile.connectionReservation = reserveWindowSize(sendfile.stream, sendfile.streamReservation, true); } - } catch (IOException e) { - failed(e, sendfile); + } catch (IOException ioe) { + failed(ioe, sendfile); return; } @@ -457,8 +461,8 @@ ByteBuffer.wrap(header), sendfile.mappedBuffer); try { handleAsyncException(); - } catch (IOException e) { - failed(e, sendfile); + } catch (IOException ioe) { + failed(ioe, sendfile); return; } } diff -Nru tomcat10-10.1.40/java/org/apache/coyote/http2/Http2Parser.java tomcat10-10.1.52/java/org/apache/coyote/http2/Http2Parser.java --- tomcat10-10.1.40/java/org/apache/coyote/http2/Http2Parser.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/coyote/http2/Http2Parser.java 2026-01-23 19:33:36.000000000 +0000 @@ -188,7 +188,7 @@ Integer.toString(dataLength), padding)); } - ByteBuffer dest = output.startRequestBodyFrame(streamId, payloadSize, endOfStream); + ByteBuffer dest = output.startRequestBodyFrame(streamId, dataLength, endOfStream); if (dest == null) { swallowPayload(streamId, FrameType.DATA.getId(), dataLength, false, buffer); // Process padding before sending any notifications in case padding @@ -201,7 +201,7 @@ } } else { synchronized (dest) { - if (dest.remaining() < payloadSize) { + if (dest.remaining() < dataLength) { // Client has sent more data than permitted by Window size swallowPayload(streamId, FrameType.DATA.getId(), dataLength, false, buffer); if (Flags.hasPadding(flags)) { @@ -298,7 +298,7 @@ // RFC 7450 priority frames are ignored. Still need to treat as overhead. try { swallowPayload(streamId, FrameType.PRIORITY.getId(), 5, false, buffer); - } catch (ConnectionException e) { + } catch (ConnectionException ignore) { // Will never happen because swallowPayload() is called with isPadding set // to false } @@ -785,7 +785,7 @@ HpackDecoder getHpackDecoder(); // Data frames - ByteBuffer startRequestBodyFrame(int streamId, int payloadSize, boolean endOfStream) throws Http2Exception; + ByteBuffer startRequestBodyFrame(int streamId, int dataLength, boolean endOfStream) throws Http2Exception; void endRequestBodyFrame(int streamId, int dataLength) throws Http2Exception, IOException; diff -Nru tomcat10-10.1.40/java/org/apache/coyote/http2/Http2Protocol.java tomcat10-10.1.52/java/org/apache/coyote/http2/Http2Protocol.java --- tomcat10-10.1.40/java/org/apache/coyote/http2/Http2Protocol.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/coyote/http2/Http2Protocol.java 2026-01-23 19:33:36.000000000 +0000 @@ -133,9 +133,8 @@ @Override public Processor getProcessor(SocketWrapperBase socketWrapper, Adapter adapter) { - return new UpgradeProcessorInternal(socketWrapper, - new UpgradeToken(getInternalUpgradeHandler(socketWrapper, adapter, null), null, - null, getUpgradeProtocolName()),null); + return new UpgradeProcessorInternal(socketWrapper, new UpgradeToken( + getInternalUpgradeHandler(socketWrapper, adapter, null), null, null, getUpgradeProtocolName()), null); } diff -Nru tomcat10-10.1.40/java/org/apache/coyote/http2/Http2UpgradeHandler.java tomcat10-10.1.52/java/org/apache/coyote/http2/Http2UpgradeHandler.java --- tomcat10-10.1.40/java/org/apache/coyote/http2/Http2UpgradeHandler.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/coyote/http2/Http2UpgradeHandler.java 2026-01-23 19:33:36.000000000 +0000 @@ -164,8 +164,12 @@ remoteSettings = new ConnectionSettingsRemote(connectionId); localSettings = new ConnectionSettingsLocal(connectionId); - localSettings.set(Setting.MAX_CONCURRENT_STREAMS, protocol.getMaxConcurrentStreams()); - localSettings.set(Setting.INITIAL_WINDOW_SIZE, protocol.getInitialWindowSize()); + /* + * Force set these initial limits. A well-behaved client should ACK the settings and adhere to them before it + * reaches the limits anyway. + */ + localSettings.set(Setting.MAX_CONCURRENT_STREAMS, protocol.getMaxConcurrentStreams(), true); + localSettings.set(Setting.INITIAL_WINDOW_SIZE, protocol.getInitialWindowSize(), true); pingManager.initiateDisabled = protocol.getInitiatePingDisabled(); @@ -522,7 +526,7 @@ try { writeGoAwayFrame((1 << 31) - 1, Http2Error.NO_ERROR.getCode(), null); - } catch (IOException ioe) { + } catch (IOException ignore) { // This is fatal for the connection. Ignore it here. There will be // further attempts at I/O in upgradeDispatch() and it can better // handle the IO errors. @@ -581,6 +585,9 @@ se.getError(), se.getMessage())); } + // Treat a sent reset like a received reset and increment the overhead count + increaseOverheadCount(FrameType.RST, getProtocol().getOverheadResetFactor()); + // Write a RST frame byte[] rstFrame = new byte[13]; // Length @@ -629,7 +636,7 @@ } try { writeGoAwayFrame(maxProcessedStreamId, code, msg); - } catch (IOException ioe) { + } catch (IOException ignore) { // Ignore. GOAWAY is sent on a best efforts basis and the original // error has already been logged. } @@ -653,6 +660,7 @@ } socketWrapper.flush(true); } catch (IOException ioe) { + // Exception is logged further up stack String msg = sm.getString("upgradeHandler.sendPrefaceFail", connectionId); if (log.isDebugEnabled()) { log.debug(msg); @@ -964,8 +972,8 @@ } else if (windowSize < 1) { /* * The connection window has no capacity. If the stream has not been granted an allocation, and the - * stream was not already added to the backlog due to a partial reservation (see next else if - * block) add it to the backlog so it can obtain an allocation when capacity is available. + * stream was not already added to the backlog due to a partial reservation (see next else if block) + * add it to the backlog so it can obtain an allocation when capacity is available. */ if (stream.getConnectionAllocationMade() == 0 && stream.getConnectionAllocationRequested() == 0) { stream.setConnectionAllocationRequested(reservation); @@ -1410,39 +1418,59 @@ void reduceOverheadCount(FrameType frameType) { - // A non-overhead frame reduces the overhead count by - // Http2Protocol.DEFAULT_OVERHEAD_REDUCTION_FACTOR. A simple browser - // request is likely to have one non-overhead frame (HEADERS) and one - // overhead frame (REPRIORITISE). With the default settings the overhead - // count will reduce by 10 for each simple request. - // Requests and responses with bodies will create additional - // non-overhead frames, further reducing the overhead count. + /* + * A non-overhead frame reduces the overhead count by {@code Http2Protocol.DEFAULT_OVERHEAD_REDUCTION_FACTOR}. + * + * A simple browser request is likely to have one non-overhead frame (HEADERS) that results in a response with + * one further non-overhead frame (DATA). With the default settings, the overhead count will reduce by 40 for + * each simple request. + * + * Requests and responses with bodies will create additional non-overhead frames, further reducing the overhead + * count. + */ updateOverheadCount(frameType, Http2Protocol.DEFAULT_OVERHEAD_REDUCTION_FACTOR); } @Override public void increaseOverheadCount(FrameType frameType) { - // An overhead frame increases the overhead count by - // overheadCountFactor. By default, this means an overhead frame - // increases the overhead count by 10. A simple browser request is - // likely to have one non-overhead frame (HEADERS) and one overhead - // frame (REPRIORITISE). With the default settings the overhead count - // will reduce by 10 for each simple request. + /* + * An overhead frame (SETTINGS, PRIORITY, PING) increases the overhead count by overheadCountFactor. By default, + * this means an overhead frame increases the overhead count by 10. + * + * If the client ignores maxConcurrentStreams then any HEADERS frame received will also increase the overhead + * count by overheadCountFactor. + * + * A simple browser request should not trigger any overhead frames. + */ updateOverheadCount(frameType, getProtocol().getOverheadCountFactor()); } - private void increaseOverheadCount(FrameType frameType, int increment) { - // Overhead frames that indicate inefficient (and potentially malicious) - // use of small frames trigger an increase that is inversely - // proportional to size. The default threshold for all three potential - // areas for abuse (HEADERS, DATA, WINDOW_UPDATE) is 1024 bytes. Frames - // with sizes smaller than this will trigger an increase of - // threshold/size. - // DATA and WINDOW_UPDATE take an average over the last two non-final - // frames to allow for client buffering schemes that can result in some - // small DATA payloads. + /** + * Used to increase the overhead for frames that don't use the {@code overheadCountFactor} ({@code CONTINUATION}, + * {@code DATA}, {@code WINDOW_UPDATE} and {@code RESET}). + * + * @param frameType The frame type triggering the overhead increase + * @param increment The amount by which the overhead is increased + */ + protected void increaseOverheadCount(FrameType frameType, int increment) { + /* + * Three types of frame are susceptible to inefficient (and potentially malicious) use of small frames. These + * trigger an increase in overhead that is inversely proportional to size. The default threshold for all three + * potential areas for abuse (CONTINUATION, DATA, WINDOW_UPDATE) is 1024 bytes. Frames with sizes smaller than + * this will trigger an increase of threshold/size. + * + * The check for DATA and WINDOW_UPDATE frames takes an average over the last two frames to allow for client + * buffering schemes that can result in some small DATA payloads. + * + * The CONTINUATION and DATA frames checks are skipped for end of headers (CONTINUATION) and end of stream + * (DATA) as those frames may be small for legitimate reasons. + * + * RESET frames (received or sent) trigger an increase of overheadResetFactor. + * + * In all cases, the calling method determines the extent to which the overhead count is increased. + */ updateOverheadCount(frameType, increment); } @@ -1523,7 +1551,7 @@ @Override - public ByteBuffer startRequestBodyFrame(int streamId, int payloadSize, boolean endOfStream) throws Http2Exception { + public ByteBuffer startRequestBodyFrame(int streamId, int dataLength, boolean endOfStream) throws Http2Exception { // DATA frames reduce the overhead count ... reduceOverheadCount(FrameType.DATA); @@ -1537,8 +1565,8 @@ // average over two frames to avoid false positives. if (!endOfStream) { int overheadThreshold = protocol.getOverheadDataThreshold(); - int average = (lastNonFinalDataPayload >> 1) + (payloadSize >> 1); - lastNonFinalDataPayload = payloadSize; + int average = (lastNonFinalDataPayload >> 1) + (dataLength >> 1); + lastNonFinalDataPayload = dataLength; // Avoid division by zero if (average == 0) { average = 1; @@ -1550,7 +1578,7 @@ AbstractNonZeroStream abstractNonZeroStream = getAbstractNonZeroStream(streamId, true); abstractNonZeroStream.checkState(FrameType.DATA); - abstractNonZeroStream.receivedData(payloadSize); + abstractNonZeroStream.receivedData(dataLength); ByteBuffer result = abstractNonZeroStream.getInputByteBuffer(true); if (log.isTraceEnabled()) { @@ -1651,9 +1679,9 @@ if (payloadSize < overheadThreshold) { if (payloadSize == 0) { // Avoid division by zero - increaseOverheadCount(FrameType.HEADERS, overheadThreshold); + increaseOverheadCount(FrameType.CONTINUATION, overheadThreshold); } else { - increaseOverheadCount(FrameType.HEADERS, overheadThreshold / payloadSize); + increaseOverheadCount(FrameType.CONTINUATION, overheadThreshold / payloadSize); } } } @@ -1914,6 +1942,10 @@ } } + String getSniHostName() { + return socketWrapper.getSniHostName(); + } + protected class PingManager { protected boolean initiateDisabled = false; @@ -1921,7 +1953,7 @@ // 10 seconds protected final long pingIntervalNano = 10000000000L; - protected int sequence = 0; + protected volatile int sequence = 0; protected long lastPingNanoTime = Long.MIN_VALUE; protected Queue inflightPings = new ConcurrentLinkedQueue<>(); @@ -1942,18 +1974,13 @@ if (force || now - lastPingNanoTime > pingIntervalNano) { lastPingNanoTime = now; byte[] payload = new byte[8]; - socketWrapper.getLock().lock(); - try { - int sentSequence = ++sequence; - PingRecord pingRecord = new PingRecord(sentSequence, now); - inflightPings.add(pingRecord); - ByteUtil.set31Bits(payload, 4, sentSequence); - socketWrapper.write(true, PING, 0, PING.length); - socketWrapper.write(true, payload, 0, payload.length); - socketWrapper.flush(true); - } finally { - socketWrapper.getLock().unlock(); - } + int sentSequence = ++sequence; + PingRecord pingRecord = new PingRecord(sentSequence, now); + inflightPings.add(pingRecord); + ByteUtil.set31Bits(payload, 4, sentSequence); + socketWrapper.write(true, PING, 0, PING.length); + socketWrapper.write(true, payload, 0, payload.length); + socketWrapper.flush(true); } } diff -Nru tomcat10-10.1.40/java/org/apache/coyote/http2/LocalStrings.properties tomcat10-10.1.52/java/org/apache/coyote/http2/LocalStrings.properties --- tomcat10-10.1.40/java/org/apache/coyote/http2/LocalStrings.properties 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/coyote/http2/LocalStrings.properties 2026-01-23 19:33:36.000000000 +0000 @@ -37,6 +37,7 @@ frameType.checkStream=Invalid frame type [{0}] hpack.integerEncodedOverTooManyOctets=HPACK variable length integer encoded over too many octets, max is [{0}] +hpack.integerEncodedTooBig=The maximum permitted value of an HPACK encoded variable length integer is Integer.MAX_VALUE hpack.invalidCharacter=The Unicode character [{0}] at code point [{1}] cannot be encoded as it is outside the permitted range of 0 to 255. hpackEncoder.encodeHeader=Encoding header [{0}] with value [{1}] @@ -104,6 +105,7 @@ stream.header.unexpectedPseudoHeader=Connection [{0}], Stream [{1}], Pseudo header [{2}] received after a regular header stream.header.unknownPseudoHeader=Connection [{0}], Stream [{1}], Unknown pseudo header [{2}] received stream.host.inconsistent=Connection [{0}], Stream [{1}], The header host header [{2}] is inconsistent with previously provided values for host [{3}] and/or port [{4}] +stream.host.sni=Connection [{0}], Stream [{1}], The host header [{2}] does not match the SNI host [{3}] stream.inputBuffer.copy=Copying [{0}] bytes from inBuffer to outBuffer stream.inputBuffer.dispatch=Data added to inBuffer when read interest is registered. Triggering a read dispatch stream.inputBuffer.empty=The Stream input buffer is empty. Waiting for more data diff -Nru tomcat10-10.1.40/java/org/apache/coyote/http2/LocalStrings_fr.properties tomcat10-10.1.52/java/org/apache/coyote/http2/LocalStrings_fr.properties --- tomcat10-10.1.40/java/org/apache/coyote/http2/LocalStrings_fr.properties 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/coyote/http2/LocalStrings_fr.properties 2026-01-23 19:33:36.000000000 +0000 @@ -37,6 +37,7 @@ frameType.checkStream=Type de trame invalide [{0}] hpack.integerEncodedOverTooManyOctets=Un entier de taille variable de HPACK a été encodé sur trop d''octets, le maximum est de [{0}] +hpack.integerEncodedTooBig=La valeur maximale permise pour un entier de longueur variable encodé par HPACK est Integer.MAX_VALUE hpack.invalidCharacter=Le caractère Unicode [{0}] ayant le code point [{1}] ne peut être encodé, parce qu''il est en-dehors de l''éventail permis 0-255. hpackEncoder.encodeHeader=Encodage de l''en-tête [{0}] avec la valeur [{1}] @@ -77,6 +78,7 @@ http2Parser.processFrameHeaders.decodingFailed=Une erreur de décodage HPACK des en-têtes HTTP s'est produite http2Parser.processFrameHeaders.payload=Connection [{0}], Flux [{1}], Traitement des en-têtes avec une taille de données de [{2}] http2Parser.processFramePriorityUpdate.debug=Connection [{0}], Stream [{1}], Urgency [{2}], Incremental [{3}] +http2Parser.processFramePriorityUpdate.invalid=Connection [{0}], Stream [{1}], La trame Priority Update a une valeur de champ de priorité invalide http2Parser.processFramePriorityUpdate.streamZero=Connection [{0}], La trame de mise à jour de priorité a été recue pour le flux zéro http2Parser.processFramePushPromise=Connexion [{0}], Flux (Stream) [{1}], les trames de promesse d''envoi ("Push promise frames") ne doivent pas être envoyées par le client. http2Parser.processFrameSettings.ackWithNonZeroPayload=La trame de paramètres a été reçue avec un indicateur ACK activé et des données présentes @@ -165,6 +167,7 @@ upgradeHandler.stream.even=Un nouvel ID de flux distant (remote stream) [{0}] a été requis, mais tous les flux distants doivent utiliser ID impairs upgradeHandler.stream.notWritable=Connection [{0}], Flux [{1}], Impossible d''écrire sur ce flux upgradeHandler.stream.old=Un nouveau flux distant avec l''ID [{0}] a été demandé mais le flux le plus récent est [{1}] +upgradeHandler.throwable=Connection [{0}] upgradeHandler.tooManyRemoteStreams=Le client a essayé d''utiliser plus de [{0}] flux actifs upgradeHandler.tooMuchOverhead=Connection [{0}], Le traitement est trop coûteux donc la connection sera fermée upgradeHandler.unexpectedAck=Connection [{0}], Flux [{1}], Une notification de réception de paramètres a été reçue alors qu''aucune n''était attendue diff -Nru tomcat10-10.1.40/java/org/apache/coyote/http2/LocalStrings_ja.properties tomcat10-10.1.52/java/org/apache/coyote/http2/LocalStrings_ja.properties --- tomcat10-10.1.40/java/org/apache/coyote/http2/LocalStrings_ja.properties 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/coyote/http2/LocalStrings_ja.properties 2026-01-23 19:33:36.000000000 +0000 @@ -37,6 +37,7 @@ frameType.checkStream=無効なフレームタイプ [{0}] hpack.integerEncodedOverTooManyOctets=エンコードされたHPACK可変長整数は多くのオクテットを超過。最大値は [{0}] +hpack.integerEncodedTooBig=HPACKエンコードされた可変長整数の最大許容値はInteger.MAX_VALUEです hpack.invalidCharacter=コードポイント [{1}] のユニコード文字 [{0}] は有効範囲 0 から 255 の範囲外のため、エンコードできません。 hpackEncoder.encodeHeader=ヘッダー[{0}]を値[{1}]でエンコードしています @@ -77,6 +78,7 @@ http2Parser.processFrameHeaders.decodingFailed=HTTP ヘッダーの HPACK 復号化中にエラーが発生しました。 http2Parser.processFrameHeaders.payload=コネクション [{0}]、ストリーム [{1}]、サイズ [{2}] のヘッダーペイロードを処理中 http2Parser.processFramePriorityUpdate.debug=接続 [{0}]、ストリーム [{1}]、緊急度 [{2}]、増分 [{3}] +http2Parser.processFramePriorityUpdate.invalid=コネクション [{0}]、ストリーム [{1}]、優先度フィールド値が無効な優先度更新フレーム http2Parser.processFramePriorityUpdate.streamZero=接続 [{0}] は、ストリーム 0 を優先するための優先更新フレームを受信しました http2Parser.processFramePushPromise=コネクション [{0}]、ストリーム [{1}]、クライアントから PUSH_PROMISE フレームを送信するべきではありません http2Parser.processFrameSettings.ackWithNonZeroPayload=ACKフラグがセットされ、ペイロードが存在する状態で受信されたSettingsフレーム @@ -165,6 +167,7 @@ upgradeHandler.stream.even=新しいリモートストリーム ID [{0}] を要求されましたがリモートストリームの ID は奇数でなければなりません。 upgradeHandler.stream.notWritable=コネクション [{0}]、ストリーム [{1}]、このストリームは書き込み可能ではありません upgradeHandler.stream.old=新しいリモートストリーム ID [{0}] を要求されましたが、最新のストリームは [{1}] です。 +upgradeHandler.throwable=コネクション[{0}] upgradeHandler.tooManyRemoteStreams=クライアントは [{0}] 以上のアクティブなストリームを使用しようとしました upgradeHandler.tooMuchOverhead=コネクション [{0}]、オーバーヘッドが多すぎるため、接続が閉じられます。 upgradeHandler.unexpectedAck=コネクション [{0}]、ストリーム [{1}]、予期しないときにsettings ackを受信しました @@ -177,7 +180,7 @@ upgradeHandler.windowUpdateConnection=コネクション [{0}]、ウィンドウの更新をクライアントに送信し、ウィンドウを[{1}]バイト増やします upgradeHandler.windowUpdateStream=コネクション [{0}]、ストリーム [{1}]、ウィンドウの更新をクライアントに送信し、ウィンドウを [{2}] バイト増やします upgradeHandler.writeBody=コネクション [{0}]、ストリーム [{1}]、データ長 [{2}] -upgradeHandler.writeHeaders=コネクション [{0}], ストリーム [{1}] +upgradeHandler.writeHeaders=コネクション [{0}], ストリーム [{1}], ヘッダの書き込み, EndOfStream [{2}] upgradeHandler.writePushHeaders=コネクション [{0}]、ストリーム [{1}]、プッシュされたストリーム [{2}]、EndOfStream [{3}] windowAllocationManager.dispatched=コネクション [{0}]、ストリーム [{1}]、ディスパッチされました diff -Nru tomcat10-10.1.40/java/org/apache/coyote/http2/RecycledStream.java tomcat10-10.1.52/java/org/apache/coyote/http2/RecycledStream.java --- tomcat10-10.1.40/java/org/apache/coyote/http2/RecycledStream.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/coyote/http2/RecycledStream.java 2026-01-23 19:33:36.000000000 +0000 @@ -47,8 +47,8 @@ @Override - void receivedData(int payloadSize) throws ConnectionException { - remainingFlowControlWindow -= payloadSize; + void receivedData(int dataLength) throws ConnectionException { + remainingFlowControlWindow -= dataLength; } diff -Nru tomcat10-10.1.40/java/org/apache/coyote/http2/Stream.java tomcat10-10.1.52/java/org/apache/coyote/http2/Stream.java --- tomcat10-10.1.40/java/org/apache/coyote/http2/Stream.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/coyote/http2/Stream.java 2026-01-23 19:33:36.000000000 +0000 @@ -49,6 +49,7 @@ import org.apache.juli.logging.LogFactory; import org.apache.tomcat.util.buf.ByteChunk; import org.apache.tomcat.util.buf.MessageBytes; +import org.apache.tomcat.util.http.Method; import org.apache.tomcat.util.http.MimeHeaders; import org.apache.tomcat.util.http.parser.Host; import org.apache.tomcat.util.http.parser.Priority; @@ -164,7 +165,7 @@ this.coyoteResponse.setOutputBuffer(http2OutputBuffer); this.coyoteRequest.setResponse(coyoteResponse); this.coyoteRequest.protocol().setString("HTTP/2.0"); - this.coyoteRequest.setStartTimeNanos(System.nanoTime()); + this.coyoteRequest.markStartTime(); } @@ -368,9 +369,9 @@ switch (name) { case ":method": { - if (coyoteRequest.method().isNull()) { - coyoteRequest.method().setString(value); - if ("HEAD".equals(value)) { + if (coyoteRequest.getMethod() == null) { + coyoteRequest.setMethod(value); + if (Method.HEAD.equals(value)) { configureVoidOutputFilter(); } } else { @@ -510,6 +511,12 @@ } else { coyoteRequest.serverName().setString(value); } + // Match host name with SNI if required + if (!handler.getProtocol().getHttp11Protocol().checkSni(handler.getSniHostName(), + coyoteRequest.serverName().getString())) { + throw new HpackException(sm.getString("stream.host.sni", getConnectionId(), getIdAsString(), value, + handler.getSniHostName())); + } } @@ -552,8 +559,8 @@ final boolean receivedEndOfHeaders() throws ConnectionException { - if (coyoteRequest.method().isNull() || coyoteRequest.scheme().isNull() || - !coyoteRequest.method().equals("CONNECT") && coyoteRequest.requestURI().isNull()) { + if (coyoteRequest.getMethod() == null || coyoteRequest.scheme().isNull() || + !Method.CONNECT.equals(coyoteRequest.getMethod()) && coyoteRequest.requestURI().isNull()) { throw new ConnectionException(sm.getString("stream.header.required", getConnectionId(), getIdAsString()), Http2Error.PROTOCOL_ERROR); } @@ -676,8 +683,8 @@ @Override - final void receivedData(int payloadSize) throws Http2Exception { - contentLengthReceived += payloadSize; + final void receivedData(int dataLength) throws Http2Exception { + contentLengthReceived += dataLength; long contentLengthHeader = coyoteRequest.getContentLengthLong(); if (contentLengthHeader > -1 && contentLengthReceived > contentLengthHeader) { throw new ConnectionException( @@ -862,7 +869,7 @@ return; } // Set the special HTTP/2 headers - request.getMimeHeaders().addValue(":method").duplicate(request.method()); + request.getMimeHeaders().addValue(":method").setString(request.getMethod()); request.getMimeHeaders().addValue(":scheme").duplicate(request.scheme()); StringBuilder path = new StringBuilder(request.requestURI().toString()); if (!request.queryString().isNull()) { @@ -1149,7 +1156,7 @@ // Only want to return false if the window size is zero AND we are // already waiting for an allocation. return (getWindowSize() <= 0 || !allocationManager.isWaitingForStream()) && - (handler.getWindowSize() <= 0 || !allocationManager.isWaitingForConnection()) && !dataLeft; + (handler.getWindowSize() <= 0 || !allocationManager.isWaitingForConnection()) && !dataLeft; } finally { writeLock.unlock(); } diff -Nru tomcat10-10.1.40/java/org/apache/coyote/http2/StreamProcessor.java tomcat10-10.1.52/java/org/apache/coyote/http2/StreamProcessor.java --- tomcat10-10.1.40/java/org/apache/coyote/http2/StreamProcessor.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/coyote/http2/StreamProcessor.java 2026-01-23 19:33:36.000000000 +0000 @@ -147,8 +147,14 @@ state = SocketState.CLOSED; } finally { if (state == SocketState.CLOSED) { - stream.recycle(); + /* + * Recycle this processor before the stream is recycled as recycling the stream will add the + * request and the response to the pool for re-use (if re-use is enabled) and the request + * statistics updating in StreamProcessor.recycle() needs to happen before the request and + * response are added to the pool to avoid concurrency issues corrupting the statistics. + */ recycle(); + stream.recycle(); } } } finally { @@ -308,7 +314,7 @@ stream.getInputBuffer().insertReplayedBody(body); try { stream.receivedEndOfStream(); - } catch (ConnectionException e) { + } catch (ConnectionException ignore) { // Exception will not be thrown in this case } } @@ -433,6 +439,12 @@ global.removeRequestProcessor(request.getRequestProcessor()); } + /* + * Clear the statistics ready for re-use of the request. If we don't clear the statistics, the statistics for + * the current request will be included in the statistics for all future requests. + */ + request.getRequestProcessor().recycleStatistcs(); + // Clear fields that can be cleared to aid GC and trigger NPEs if this // is reused setSocketWrapper(null); @@ -510,8 +522,7 @@ HttpParser httpParser = handler.getProtocol().getHttp11Protocol().getHttpParser(); // Method name must be a token - String method = request.method().toString(); - if (!HttpParser.isToken(method)) { + if (!HttpParser.isToken(request.getMethod())) { return false; } diff -Nru tomcat10-10.1.40/java/org/apache/el/ExpressionFactoryImpl.java tomcat10-10.1.52/java/org/apache/el/ExpressionFactoryImpl.java --- tomcat10-10.1.40/java/org/apache/el/ExpressionFactoryImpl.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/el/ExpressionFactoryImpl.java 2026-01-23 19:33:36.000000000 +0000 @@ -28,11 +28,8 @@ import org.apache.el.util.ExceptionUtils; import org.apache.el.util.MessageFactory; - /** * @see jakarta.el.ExpressionFactory - * - * @author Jacob Hookom [jacob@hookom.net] */ @aQute.bnd.annotation.spi.ServiceProvider(value = ExpressionFactory.class) public class ExpressionFactoryImpl extends ExpressionFactory { diff -Nru tomcat10-10.1.40/java/org/apache/el/MethodExpressionImpl.java tomcat10-10.1.52/java/org/apache/el/MethodExpressionImpl.java --- tomcat10-10.1.40/java/org/apache/el/MethodExpressionImpl.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/el/MethodExpressionImpl.java 2026-01-23 19:33:36.000000000 +0000 @@ -63,8 +63,6 @@ * @see jakarta.el.Expression * @see jakarta.el.ExpressionFactory * @see jakarta.el.MethodExpression - * - * @author Jacob Hookom [jacob@hookom.net] */ public final class MethodExpressionImpl extends MethodExpression implements Externalizable { diff -Nru tomcat10-10.1.40/java/org/apache/el/ValueExpressionImpl.java tomcat10-10.1.52/java/org/apache/el/ValueExpressionImpl.java --- tomcat10-10.1.40/java/org/apache/el/ValueExpressionImpl.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/el/ValueExpressionImpl.java 2026-01-23 19:33:36.000000000 +0000 @@ -70,8 +70,6 @@ * @see jakarta.el.Expression * @see jakarta.el.ExpressionFactory * @see jakarta.el.ValueExpression - * - * @author Jacob Hookom [jacob@hookom.net] */ public final class ValueExpressionImpl extends ValueExpression implements Externalizable { diff -Nru tomcat10-10.1.40/java/org/apache/el/lang/ELArithmetic.java tomcat10-10.1.52/java/org/apache/el/lang/ELArithmetic.java --- tomcat10-10.1.40/java/org/apache/el/lang/ELArithmetic.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/el/lang/ELArithmetic.java 2026-01-23 19:33:36.000000000 +0000 @@ -26,9 +26,7 @@ /** - * A helper class of Arithmetic defined by the EL Specification - * - * @author Jacob Hookom [jacob@hookom.net] + * A helper class of Arithmetic defined by the EL Specification. */ public abstract class ELArithmetic { diff -Nru tomcat10-10.1.40/java/org/apache/el/lang/ELSupport.java tomcat10-10.1.52/java/org/apache/el/lang/ELSupport.java --- tomcat10-10.1.40/java/org/apache/el/lang/ELSupport.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/el/lang/ELSupport.java 2026-01-23 19:33:36.000000000 +0000 @@ -40,9 +40,7 @@ /** - * A helper class that implements the EL Specification - * - * @author Jacob Hookom [jacob@hookom.net] + * A helper class that implements the EL Specification. */ public class ELSupport { @@ -190,8 +188,8 @@ } /* - * Going to have some casts /raw types somewhere so doing it here keeps them all in one place. There might - * be a neater / better solution, but I couldn't find it. + * Going to have some casts /raw types somewhere so doing it here keeps them all in one place. There might be a + * neater / better solution, but I couldn't find it. */ @SuppressWarnings("unchecked") public static Enum coerceToEnum(final ELContext ctx, final Object obj, @@ -240,8 +238,7 @@ * * @throws ELException if object is not Boolean or String */ - public static Boolean coerceToBoolean(final ELContext ctx, final Object obj, boolean primitive) - throws ELException { + public static Boolean coerceToBoolean(final ELContext ctx, final Object obj, boolean primitive) throws ELException { if (ctx != null) { boolean originalIsPropertyResolved = ctx.isPropertyResolved(); @@ -349,8 +346,7 @@ throw new ELException(MessageFactory.get("error.convert", number, number.getClass(), type)); } - public static Number coerceToNumber(final ELContext ctx, final Object obj, final Class type) - throws ELException { + public static Number coerceToNumber(final ELContext ctx, final Object obj, final Class type) throws ELException { if (ctx != null) { boolean originalIsPropertyResolved = ctx.isPropertyResolved(); @@ -489,8 +485,7 @@ } } - public static T coerceToType(final ELContext ctx, final Object obj, final Class type) - throws ELException { + public static T coerceToType(final ELContext ctx, final Object obj, final Class type) throws ELException { if (ctx != null) { boolean originalIsPropertyResolved = ctx.isPropertyResolved(); diff -Nru tomcat10-10.1.40/java/org/apache/el/lang/ExpressionBuilder.java tomcat10-10.1.52/java/org/apache/el/lang/ExpressionBuilder.java --- tomcat10-10.1.40/java/org/apache/el/lang/ExpressionBuilder.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/el/lang/ExpressionBuilder.java 2026-01-23 19:33:36.000000000 +0000 @@ -44,9 +44,6 @@ import org.apache.el.util.ExceptionUtils; import org.apache.el.util.MessageFactory; -/** - * @author Jacob Hookom [jacob@hookom.net] - */ public final class ExpressionBuilder implements NodeVisitor { private static final SynchronizedStack parserCache = new SynchronizedStack<>(); diff -Nru tomcat10-10.1.40/java/org/apache/el/lang/FunctionMapperFactory.java tomcat10-10.1.52/java/org/apache/el/lang/FunctionMapperFactory.java --- tomcat10-10.1.40/java/org/apache/el/lang/FunctionMapperFactory.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/el/lang/FunctionMapperFactory.java 2026-01-23 19:33:36.000000000 +0000 @@ -22,9 +22,6 @@ import org.apache.el.util.MessageFactory; -/** - * @author Jacob Hookom [jacob@hookom.net] - */ public class FunctionMapperFactory extends FunctionMapper { protected FunctionMapperImpl memento = null; diff -Nru tomcat10-10.1.40/java/org/apache/el/lang/FunctionMapperImpl.java tomcat10-10.1.52/java/org/apache/el/lang/FunctionMapperImpl.java --- tomcat10-10.1.40/java/org/apache/el/lang/FunctionMapperImpl.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/el/lang/FunctionMapperImpl.java 2026-01-23 19:33:36.000000000 +0000 @@ -29,10 +29,6 @@ import org.apache.el.util.MessageFactory; import org.apache.el.util.ReflectionUtil; - -/** - * @author Jacob Hookom [jacob@hookom.net] - */ public class FunctionMapperImpl extends FunctionMapper implements Externalizable { private static final long serialVersionUID = 1L; diff -Nru tomcat10-10.1.40/java/org/apache/el/parser/ArithmeticNode.java tomcat10-10.1.52/java/org/apache/el/parser/ArithmeticNode.java --- tomcat10-10.1.40/java/org/apache/el/parser/ArithmeticNode.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/el/parser/ArithmeticNode.java 2026-01-23 19:33:36.000000000 +0000 @@ -20,9 +20,6 @@ import org.apache.el.lang.EvaluationContext; -/** - * @author Jacob Hookom [jacob@hookom.net] - */ public abstract class ArithmeticNode extends SimpleNode { public ArithmeticNode(int i) { diff -Nru tomcat10-10.1.40/java/org/apache/el/parser/AstAnd.java tomcat10-10.1.52/java/org/apache/el/parser/AstAnd.java --- tomcat10-10.1.40/java/org/apache/el/parser/AstAnd.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/el/parser/AstAnd.java 2026-01-23 19:33:36.000000000 +0000 @@ -22,9 +22,6 @@ import org.apache.el.lang.ELSupport; import org.apache.el.lang.EvaluationContext; -/** - * @author Jacob Hookom [jacob@hookom.net] - */ public final class AstAnd extends BooleanNode { public AstAnd(int id) { diff -Nru tomcat10-10.1.40/java/org/apache/el/parser/AstBracketSuffix.java tomcat10-10.1.52/java/org/apache/el/parser/AstBracketSuffix.java --- tomcat10-10.1.40/java/org/apache/el/parser/AstBracketSuffix.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/el/parser/AstBracketSuffix.java 2026-01-23 19:33:36.000000000 +0000 @@ -21,9 +21,6 @@ import org.apache.el.lang.EvaluationContext; -/** - * @author Jacob Hookom [jacob@hookom.net] - */ public final class AstBracketSuffix extends SimpleNode { public AstBracketSuffix(int id) { diff -Nru tomcat10-10.1.40/java/org/apache/el/parser/AstChoice.java tomcat10-10.1.52/java/org/apache/el/parser/AstChoice.java --- tomcat10-10.1.40/java/org/apache/el/parser/AstChoice.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/el/parser/AstChoice.java 2026-01-23 19:33:36.000000000 +0000 @@ -22,9 +22,6 @@ import org.apache.el.lang.ELSupport; import org.apache.el.lang.EvaluationContext; -/** - * @author Jacob Hookom [jacob@hookom.net] - */ public final class AstChoice extends SimpleNode { public AstChoice(int id) { diff -Nru tomcat10-10.1.40/java/org/apache/el/parser/AstCompositeExpression.java tomcat10-10.1.52/java/org/apache/el/parser/AstCompositeExpression.java --- tomcat10-10.1.40/java/org/apache/el/parser/AstCompositeExpression.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/el/parser/AstCompositeExpression.java 2026-01-23 19:33:36.000000000 +0000 @@ -22,9 +22,6 @@ import org.apache.el.lang.ELSupport; import org.apache.el.lang.EvaluationContext; -/** - * @author Jacob Hookom [jacob@hookom.net] - */ public final class AstCompositeExpression extends SimpleNode { public AstCompositeExpression(int id) { diff -Nru tomcat10-10.1.40/java/org/apache/el/parser/AstDeferredExpression.java tomcat10-10.1.52/java/org/apache/el/parser/AstDeferredExpression.java --- tomcat10-10.1.40/java/org/apache/el/parser/AstDeferredExpression.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/el/parser/AstDeferredExpression.java 2026-01-23 19:33:36.000000000 +0000 @@ -21,9 +21,6 @@ import org.apache.el.lang.EvaluationContext; -/** - * @author Jacob Hookom [jacob@hookom.net] - */ public final class AstDeferredExpression extends SimpleNode { public AstDeferredExpression(int id) { diff -Nru tomcat10-10.1.40/java/org/apache/el/parser/AstDiv.java tomcat10-10.1.52/java/org/apache/el/parser/AstDiv.java --- tomcat10-10.1.40/java/org/apache/el/parser/AstDiv.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/el/parser/AstDiv.java 2026-01-23 19:33:36.000000000 +0000 @@ -22,9 +22,6 @@ import org.apache.el.lang.ELArithmetic; import org.apache.el.lang.EvaluationContext; -/** - * @author Jacob Hookom [jacob@hookom.net] - */ public final class AstDiv extends ArithmeticNode { public AstDiv(int id) { diff -Nru tomcat10-10.1.40/java/org/apache/el/parser/AstDotSuffix.java tomcat10-10.1.52/java/org/apache/el/parser/AstDotSuffix.java --- tomcat10-10.1.40/java/org/apache/el/parser/AstDotSuffix.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/el/parser/AstDotSuffix.java 2026-01-23 19:33:36.000000000 +0000 @@ -23,9 +23,6 @@ import org.apache.el.util.MessageFactory; import org.apache.el.util.Validation; -/** - * @author Jacob Hookom [jacob@hookom.net] - */ public final class AstDotSuffix extends SimpleNode { public AstDotSuffix(int id) { diff -Nru tomcat10-10.1.40/java/org/apache/el/parser/AstDynamicExpression.java tomcat10-10.1.52/java/org/apache/el/parser/AstDynamicExpression.java --- tomcat10-10.1.40/java/org/apache/el/parser/AstDynamicExpression.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/el/parser/AstDynamicExpression.java 2026-01-23 19:33:36.000000000 +0000 @@ -21,9 +21,6 @@ import org.apache.el.lang.EvaluationContext; -/** - * @author Jacob Hookom [jacob@hookom.net] - */ public final class AstDynamicExpression extends SimpleNode { public AstDynamicExpression(int id) { diff -Nru tomcat10-10.1.40/java/org/apache/el/parser/AstEqual.java tomcat10-10.1.52/java/org/apache/el/parser/AstEqual.java --- tomcat10-10.1.40/java/org/apache/el/parser/AstEqual.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/el/parser/AstEqual.java 2026-01-23 19:33:36.000000000 +0000 @@ -22,9 +22,6 @@ import org.apache.el.lang.ELSupport; import org.apache.el.lang.EvaluationContext; -/** - * @author Jacob Hookom [jacob@hookom.net] - */ public final class AstEqual extends BooleanNode { public AstEqual(int id) { diff -Nru tomcat10-10.1.40/java/org/apache/el/parser/AstFalse.java tomcat10-10.1.52/java/org/apache/el/parser/AstFalse.java --- tomcat10-10.1.40/java/org/apache/el/parser/AstFalse.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/el/parser/AstFalse.java 2026-01-23 19:33:36.000000000 +0000 @@ -21,9 +21,6 @@ import org.apache.el.lang.EvaluationContext; -/** - * @author Jacob Hookom [jacob@hookom.net] - */ public final class AstFalse extends BooleanNode { public AstFalse(int id) { diff -Nru tomcat10-10.1.40/java/org/apache/el/parser/AstFloatingPoint.java tomcat10-10.1.52/java/org/apache/el/parser/AstFloatingPoint.java --- tomcat10-10.1.40/java/org/apache/el/parser/AstFloatingPoint.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/el/parser/AstFloatingPoint.java 2026-01-23 19:33:36.000000000 +0000 @@ -23,9 +23,6 @@ import org.apache.el.lang.EvaluationContext; -/** - * @author Jacob Hookom [jacob@hookom.net] - */ public final class AstFloatingPoint extends SimpleNode { public AstFloatingPoint(int id) { diff -Nru tomcat10-10.1.40/java/org/apache/el/parser/AstFunction.java tomcat10-10.1.52/java/org/apache/el/parser/AstFunction.java --- tomcat10-10.1.40/java/org/apache/el/parser/AstFunction.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/el/parser/AstFunction.java 2026-01-23 19:33:36.000000000 +0000 @@ -31,9 +31,6 @@ import org.apache.el.lang.EvaluationContext; import org.apache.el.util.MessageFactory; -/** - * @author Jacob Hookom [jacob@hookom.net] - */ public final class AstFunction extends SimpleNode { private String localName = ""; diff -Nru tomcat10-10.1.40/java/org/apache/el/parser/AstGreaterThan.java tomcat10-10.1.52/java/org/apache/el/parser/AstGreaterThan.java --- tomcat10-10.1.40/java/org/apache/el/parser/AstGreaterThan.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/el/parser/AstGreaterThan.java 2026-01-23 19:33:36.000000000 +0000 @@ -22,9 +22,6 @@ import org.apache.el.lang.ELSupport; import org.apache.el.lang.EvaluationContext; -/** - * @author Jacob Hookom [jacob@hookom.net] - */ public final class AstGreaterThan extends BooleanNode { public AstGreaterThan(int id) { diff -Nru tomcat10-10.1.40/java/org/apache/el/parser/AstGreaterThanEqual.java tomcat10-10.1.52/java/org/apache/el/parser/AstGreaterThanEqual.java --- tomcat10-10.1.40/java/org/apache/el/parser/AstGreaterThanEqual.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/el/parser/AstGreaterThanEqual.java 2026-01-23 19:33:36.000000000 +0000 @@ -22,9 +22,6 @@ import org.apache.el.lang.ELSupport; import org.apache.el.lang.EvaluationContext; -/** - * @author Jacob Hookom [jacob@hookom.net] - */ public final class AstGreaterThanEqual extends BooleanNode { public AstGreaterThanEqual(int id) { diff -Nru tomcat10-10.1.40/java/org/apache/el/parser/AstIdentifier.java tomcat10-10.1.52/java/org/apache/el/parser/AstIdentifier.java --- tomcat10-10.1.40/java/org/apache/el/parser/AstIdentifier.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/el/parser/AstIdentifier.java 2026-01-23 19:33:36.000000000 +0000 @@ -32,9 +32,6 @@ import org.apache.el.util.MessageFactory; import org.apache.el.util.Validation; -/** - * @author Jacob Hookom [jacob@hookom.net] - */ public final class AstIdentifier extends SimpleNode { public AstIdentifier(int id) { diff -Nru tomcat10-10.1.40/java/org/apache/el/parser/AstInteger.java tomcat10-10.1.52/java/org/apache/el/parser/AstInteger.java --- tomcat10-10.1.40/java/org/apache/el/parser/AstInteger.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/el/parser/AstInteger.java 2026-01-23 19:33:36.000000000 +0000 @@ -23,9 +23,6 @@ import org.apache.el.lang.EvaluationContext; -/** - * @author Jacob Hookom [jacob@hookom.net] - */ public final class AstInteger extends SimpleNode { public AstInteger(int id) { diff -Nru tomcat10-10.1.40/java/org/apache/el/parser/AstLessThan.java tomcat10-10.1.52/java/org/apache/el/parser/AstLessThan.java --- tomcat10-10.1.40/java/org/apache/el/parser/AstLessThan.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/el/parser/AstLessThan.java 2026-01-23 19:33:36.000000000 +0000 @@ -22,9 +22,6 @@ import org.apache.el.lang.ELSupport; import org.apache.el.lang.EvaluationContext; -/** - * @author Jacob Hookom [jacob@hookom.net] - */ public final class AstLessThan extends BooleanNode { public AstLessThan(int id) { diff -Nru tomcat10-10.1.40/java/org/apache/el/parser/AstLessThanEqual.java tomcat10-10.1.52/java/org/apache/el/parser/AstLessThanEqual.java --- tomcat10-10.1.40/java/org/apache/el/parser/AstLessThanEqual.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/el/parser/AstLessThanEqual.java 2026-01-23 19:33:36.000000000 +0000 @@ -22,9 +22,6 @@ import org.apache.el.lang.ELSupport; import org.apache.el.lang.EvaluationContext; -/** - * @author Jacob Hookom [jacob@hookom.net] - */ public final class AstLessThanEqual extends BooleanNode { public AstLessThanEqual(int id) { diff -Nru tomcat10-10.1.40/java/org/apache/el/parser/AstLiteralExpression.java tomcat10-10.1.52/java/org/apache/el/parser/AstLiteralExpression.java --- tomcat10-10.1.40/java/org/apache/el/parser/AstLiteralExpression.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/el/parser/AstLiteralExpression.java 2026-01-23 19:33:36.000000000 +0000 @@ -21,9 +21,6 @@ import org.apache.el.lang.EvaluationContext; -/** - * @author Jacob Hookom [jacob@hookom.net] - */ public final class AstLiteralExpression extends SimpleNode { public AstLiteralExpression(int id) { diff -Nru tomcat10-10.1.40/java/org/apache/el/parser/AstMinus.java tomcat10-10.1.52/java/org/apache/el/parser/AstMinus.java --- tomcat10-10.1.40/java/org/apache/el/parser/AstMinus.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/el/parser/AstMinus.java 2026-01-23 19:33:36.000000000 +0000 @@ -22,9 +22,6 @@ import org.apache.el.lang.ELArithmetic; import org.apache.el.lang.EvaluationContext; -/** - * @author Jacob Hookom [jacob@hookom.net] - */ public final class AstMinus extends ArithmeticNode { public AstMinus(int id) { diff -Nru tomcat10-10.1.40/java/org/apache/el/parser/AstMod.java tomcat10-10.1.52/java/org/apache/el/parser/AstMod.java --- tomcat10-10.1.40/java/org/apache/el/parser/AstMod.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/el/parser/AstMod.java 2026-01-23 19:33:36.000000000 +0000 @@ -22,9 +22,6 @@ import org.apache.el.lang.ELArithmetic; import org.apache.el.lang.EvaluationContext; -/** - * @author Jacob Hookom [jacob@hookom.net] - */ public final class AstMod extends ArithmeticNode { public AstMod(int id) { diff -Nru tomcat10-10.1.40/java/org/apache/el/parser/AstMult.java tomcat10-10.1.52/java/org/apache/el/parser/AstMult.java --- tomcat10-10.1.40/java/org/apache/el/parser/AstMult.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/el/parser/AstMult.java 2026-01-23 19:33:36.000000000 +0000 @@ -22,9 +22,6 @@ import org.apache.el.lang.ELArithmetic; import org.apache.el.lang.EvaluationContext; -/** - * @author Jacob Hookom [jacob@hookom.net] - */ public final class AstMult extends ArithmeticNode { public AstMult(int id) { diff -Nru tomcat10-10.1.40/java/org/apache/el/parser/AstNegative.java tomcat10-10.1.52/java/org/apache/el/parser/AstNegative.java --- tomcat10-10.1.40/java/org/apache/el/parser/AstNegative.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/el/parser/AstNegative.java 2026-01-23 19:33:36.000000000 +0000 @@ -25,9 +25,6 @@ import org.apache.el.lang.ELSupport; import org.apache.el.lang.EvaluationContext; -/** - * @author Jacob Hookom [jacob@hookom.net] - */ public final class AstNegative extends SimpleNode { public AstNegative(int id) { diff -Nru tomcat10-10.1.40/java/org/apache/el/parser/AstNot.java tomcat10-10.1.52/java/org/apache/el/parser/AstNot.java --- tomcat10-10.1.40/java/org/apache/el/parser/AstNot.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/el/parser/AstNot.java 2026-01-23 19:33:36.000000000 +0000 @@ -22,9 +22,6 @@ import org.apache.el.lang.ELSupport; import org.apache.el.lang.EvaluationContext; -/** - * @author Jacob Hookom [jacob@hookom.net] - */ public final class AstNot extends SimpleNode { public AstNot(int id) { diff -Nru tomcat10-10.1.40/java/org/apache/el/parser/AstNotEqual.java tomcat10-10.1.52/java/org/apache/el/parser/AstNotEqual.java --- tomcat10-10.1.40/java/org/apache/el/parser/AstNotEqual.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/el/parser/AstNotEqual.java 2026-01-23 19:33:36.000000000 +0000 @@ -22,9 +22,6 @@ import org.apache.el.lang.ELSupport; import org.apache.el.lang.EvaluationContext; -/** - * @author Jacob Hookom [jacob@hookom.net] - */ public final class AstNotEqual extends BooleanNode { public AstNotEqual(int id) { diff -Nru tomcat10-10.1.40/java/org/apache/el/parser/AstNull.java tomcat10-10.1.52/java/org/apache/el/parser/AstNull.java --- tomcat10-10.1.40/java/org/apache/el/parser/AstNull.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/el/parser/AstNull.java 2026-01-23 19:33:36.000000000 +0000 @@ -21,9 +21,6 @@ import org.apache.el.lang.EvaluationContext; -/** - * @author Jacob Hookom [jacob@hookom.net] - */ public final class AstNull extends SimpleNode { public AstNull(int id) { diff -Nru tomcat10-10.1.40/java/org/apache/el/parser/AstOr.java tomcat10-10.1.52/java/org/apache/el/parser/AstOr.java --- tomcat10-10.1.40/java/org/apache/el/parser/AstOr.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/el/parser/AstOr.java 2026-01-23 19:33:36.000000000 +0000 @@ -22,9 +22,6 @@ import org.apache.el.lang.ELSupport; import org.apache.el.lang.EvaluationContext; -/** - * @author Jacob Hookom [jacob@hookom.net] - */ public final class AstOr extends BooleanNode { public AstOr(int id) { diff -Nru tomcat10-10.1.40/java/org/apache/el/parser/AstPlus.java tomcat10-10.1.52/java/org/apache/el/parser/AstPlus.java --- tomcat10-10.1.40/java/org/apache/el/parser/AstPlus.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/el/parser/AstPlus.java 2026-01-23 19:33:36.000000000 +0000 @@ -22,9 +22,6 @@ import org.apache.el.lang.ELArithmetic; import org.apache.el.lang.EvaluationContext; -/** - * @author Jacob Hookom [jacob@hookom.net] - */ public final class AstPlus extends ArithmeticNode { public AstPlus(int id) { diff -Nru tomcat10-10.1.40/java/org/apache/el/parser/AstString.java tomcat10-10.1.52/java/org/apache/el/parser/AstString.java --- tomcat10-10.1.40/java/org/apache/el/parser/AstString.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/el/parser/AstString.java 2026-01-23 19:33:36.000000000 +0000 @@ -21,9 +21,6 @@ import org.apache.el.lang.EvaluationContext; -/** - * @author Jacob Hookom [jacob@hookom.net] - */ public final class AstString extends SimpleNode { public AstString(int id) { diff -Nru tomcat10-10.1.40/java/org/apache/el/parser/AstTrue.java tomcat10-10.1.52/java/org/apache/el/parser/AstTrue.java --- tomcat10-10.1.40/java/org/apache/el/parser/AstTrue.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/el/parser/AstTrue.java 2026-01-23 19:33:36.000000000 +0000 @@ -21,9 +21,6 @@ import org.apache.el.lang.EvaluationContext; -/** - * @author Jacob Hookom [jacob@hookom.net] - */ public final class AstTrue extends BooleanNode { public AstTrue(int id) { diff -Nru tomcat10-10.1.40/java/org/apache/el/parser/AstValue.java tomcat10-10.1.52/java/org/apache/el/parser/AstValue.java --- tomcat10-10.1.40/java/org/apache/el/parser/AstValue.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/el/parser/AstValue.java 2026-01-23 19:33:36.000000000 +0000 @@ -35,9 +35,6 @@ import org.apache.el.util.MessageFactory; import org.apache.el.util.ReflectionUtil; -/** - * @author Jacob Hookom [jacob@hookom.net] - */ public final class AstValue extends SimpleNode { private static final Object[] EMPTY_ARRAY = new Object[0]; @@ -284,8 +281,8 @@ int paramCount = types.length; - if (m.isVarArgs() && paramCount > 1 && (src == null || paramCount > src.length) || !m.isVarArgs() && - (src == null || src.length != paramCount)) { + if (m.isVarArgs() && paramCount > 1 && (src == null || paramCount > src.length) || + !m.isVarArgs() && (src == null || src.length != paramCount)) { String srcCount = null; if (src != null) { srcCount = Integer.toString(src.length); diff -Nru tomcat10-10.1.40/java/org/apache/el/parser/BooleanNode.java tomcat10-10.1.52/java/org/apache/el/parser/BooleanNode.java --- tomcat10-10.1.40/java/org/apache/el/parser/BooleanNode.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/el/parser/BooleanNode.java 2026-01-23 19:33:36.000000000 +0000 @@ -20,9 +20,6 @@ import org.apache.el.lang.EvaluationContext; -/** - * @author Jacob Hookom [jacob@hookom.net] - */ public abstract class BooleanNode extends SimpleNode { public BooleanNode(int i) { diff -Nru tomcat10-10.1.40/java/org/apache/el/parser/ELParser.java tomcat10-10.1.52/java/org/apache/el/parser/ELParser.java --- tomcat10-10.1.40/java/org/apache/el/parser/ELParser.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/el/parser/ELParser.java 2026-01-23 19:33:36.000000000 +0000 @@ -26,7 +26,8 @@ boolean jjtc000 = true; jjtree.openNodeScope(jjtn000); try { - label_1: while (true) { + label_1: + while (true) { switch ((jj_ntk == -1) ? jj_ntk_f() : jj_ntk) { case LITERAL_EXPRESSION: case START_DYNAMIC_EXPRESSION: @@ -219,7 +220,8 @@ */ final public void Semicolon() throws ParseException { Assignment(); - label_2: while (true) { + label_2: + while (true) { switch ((jj_ntk == -1) ? jj_ntk_f() : jj_ntk) { case SEMICOLON: { ; @@ -292,7 +294,8 @@ case MINUS: case IDENTIFIER: { Choice(); - label_3: while (true) { + label_3: + while (true) { if (jj_2_1(2)) { ; } else { @@ -434,7 +437,8 @@ switch ((jj_ntk == -1) ? jj_ntk_f() : jj_ntk) { case IDENTIFIER: { Identifier(); - label_4: while (true) { + label_4: + while (true) { switch ((jj_ntk == -1) ? jj_ntk_f() : jj_ntk) { case COMMA: { ; @@ -534,7 +538,8 @@ } } jj_consume_token(RPAREN); - label_5: while (true) { + label_5: + while (true) { switch ((jj_ntk == -1) ? jj_ntk_f() : jj_ntk) { case LPAREN: { ; @@ -584,7 +589,8 @@ */ final public void Choice() throws ParseException { Or(); - label_6: while (true) { + label_6: + while (true) { if (jj_2_5(3)) { ; } else { @@ -644,7 +650,8 @@ boolean jjtc001 = true; jjtree.openNodeScope(jjtn001); try { - label_7: while (true) { + label_7: + while (true) { switch ((jj_ntk == -1) ? jj_ntk_f() : jj_ntk) { case OR0: { jj_consume_token(OR0); @@ -722,7 +729,8 @@ boolean jjtc001 = true; jjtree.openNodeScope(jjtn001); try { - label_8: while (true) { + label_8: + while (true) { switch ((jj_ntk == -1) ? jj_ntk_f() : jj_ntk) { case AND0: { jj_consume_token(AND0); @@ -793,7 +801,8 @@ */ final public void Equality() throws ParseException { Compare(); - label_9: while (true) { + label_9: + while (true) { switch ((jj_ntk == -1) ? jj_ntk_f() : jj_ntk) { case EQ0: case EQ1: @@ -928,7 +937,8 @@ */ final public void Compare() throws ParseException { Concatenation(); - label_10: while (true) { + label_10: + while (true) { switch ((jj_ntk == -1) ? jj_ntk_f() : jj_ntk) { case GT0: case GT1: @@ -1176,7 +1186,8 @@ */ final public void Concatenation() throws ParseException { Math(); - label_11: while (true) { + label_11: + while (true) { switch ((jj_ntk == -1) ? jj_ntk_f() : jj_ntk) { case CONCAT: { ; @@ -1231,7 +1242,8 @@ */ final public void Math() throws ParseException { Multiplication(); - label_12: while (true) { + label_12: + while (true) { switch ((jj_ntk == -1) ? jj_ntk_f() : jj_ntk) { case PLUS: case MINUS: { @@ -1336,7 +1348,8 @@ */ final public void Multiplication() throws ParseException { Unary(); - label_13: while (true) { + label_13: + while (true) { switch ((jj_ntk == -1) ? jj_ntk_f() : jj_ntk) { case MULT: case DIV0: @@ -1733,7 +1746,8 @@ jjtree.openNodeScope(jjtn001); try { ValuePrefix(); - label_14: while (true) { + label_14: + while (true) { switch ((jj_ntk == -1) ? jj_ntk_f() : jj_ntk) { case DOT: case LBRACK: { @@ -1926,7 +1940,8 @@ case MINUS: case IDENTIFIER: { Expression(); - label_15: while (true) { + label_15: + while (true) { switch ((jj_ntk == -1) ? jj_ntk_f() : jj_ntk) { case COMMA: { ; @@ -2055,7 +2070,8 @@ case MINUS: case IDENTIFIER: { Expression(); - label_16: while (true) { + label_16: + while (true) { switch ((jj_ntk == -1) ? jj_ntk_f() : jj_ntk) { case COMMA: { ; @@ -2130,7 +2146,8 @@ case MINUS: case IDENTIFIER: { Expression(); - label_17: while (true) { + label_17: + while (true) { switch ((jj_ntk == -1) ? jj_ntk_f() : jj_ntk) { case COMMA: { ; @@ -2209,7 +2226,8 @@ case MINUS: case IDENTIFIER: { MapEntry(); - label_18: while (true) { + label_18: + while (true) { switch ((jj_ntk == -1) ? jj_ntk_f() : jj_ntk) { case COMMA: { ; @@ -2350,7 +2368,8 @@ } else { jjtn000.setLocalName(t0.image); } - label_19: while (true) { + label_19: + while (true) { MethodParameters(); switch ((jj_ntk == -1) ? jj_ntk_f() : jj_ntk) { case LPAREN: { @@ -3417,9 +3436,9 @@ private boolean jj_3R_Multiplication_247_9_71() { Token xsp; xsp = jj_scanpos; - if (jj_scan_token(51)) { + if (jj_scan_token(50)) { jj_scanpos = xsp; - if (jj_scan_token(52)) { + if (jj_scan_token(51)) { return true; } } @@ -3432,9 +3451,9 @@ private boolean jj_3R_Multiplication_245_9_70() { Token xsp; xsp = jj_scanpos; - if (jj_scan_token(49)) { + if (jj_scan_token(48)) { jj_scanpos = xsp; - if (jj_scan_token(50)) { + if (jj_scan_token(49)) { return true; } } @@ -3891,11 +3910,10 @@ } private static void jj_la1_init_1() { - jj_la1_1 = new int[] { 0x0, 0x0, 0x0, 0x1008860, 0x1008860, 0x0, 0x1000000, 0x1000000, 0x1008860, 0x0, 0x600, - 0x600, 0x600, 0x180, 0x180, 0x180, 0x1e, 0x6, 0x18, 0x1e, 0x1, 0x0, 0x0, 0x1, 0x0, 0x1, 0x200000, - 0xc000, 0xc000, 0x1e2000, 0x60000, 0x180000, 0x1e2000, 0x60, 0x60, 0x8000, 0x1000860, 0x0, 0x1000000, - 0x0, 0x0, 0x0, 0x1008860, 0x0, 0x1000000, 0x0, 0x0, 0x1008860, 0x0, 0x1008860, 0x0, 0x1008860, 0x0, 0x0, - 0x0, 0x0, }; + jj_la1_1 = new int[] { 0x0, 0x0, 0x0, 0x804860, 0x804860, 0x0, 0x800000, 0x800000, 0x804860, 0x0, 0x600, 0x600, + 0x600, 0x180, 0x180, 0x180, 0x1e, 0x6, 0x18, 0x1e, 0x1, 0x0, 0x0, 0x1, 0x0, 0x1, 0x100000, 0x6000, + 0x6000, 0xf1000, 0x30000, 0xc0000, 0xf1000, 0x60, 0x60, 0x4000, 0x800860, 0x0, 0x800000, 0x0, 0x0, 0x0, + 0x804860, 0x0, 0x800000, 0x0, 0x0, 0x804860, 0x0, 0x804860, 0x0, 0x804860, 0x0, 0x0, 0x0, 0x0, }; } final private JJCalls[] jj_2_rtns = new JJCalls[9]; @@ -4170,7 +4188,7 @@ /** Generate ParseException. */ public ParseException generateParseException() { jj_expentries.clear(); - boolean[] la1tokens = new boolean[62]; + boolean[] la1tokens = new boolean[59]; if (jj_kind >= 0) { la1tokens[jj_kind] = true; jj_kind = -1; @@ -4187,7 +4205,7 @@ } } } - for (int i = 0; i < 62; i++) { + for (int i = 0; i < 59; i++) { if (la1tokens[i]) { jj_expentry = new int[1]; jj_expentry[0] = i; diff -Nru tomcat10-10.1.40/java/org/apache/el/parser/ELParser.jjt tomcat10-10.1.52/java/org/apache/el/parser/ELParser.jjt --- tomcat10-10.1.40/java/org/apache/el/parser/ELParser.jjt 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/el/parser/ELParser.jjt 2026-01-23 19:33:36.000000000 +0000 @@ -15,11 +15,6 @@ * limitations under the License. */ -/* - Author: Jacob Hookom - Email: jacob at hookom.net -*/ - /* == Option Declaration == */ options { @@ -535,7 +530,6 @@ | < OR0 : "||" > | < OR1 : "or" > | < EMPTY : "empty" > -| < INSTANCEOF : "instanceof" > | < MULT : "*" > | < PLUS : "+" > | < MINUS : "-" > @@ -547,9 +541,7 @@ | < CONCAT : "+=" > | < ASSIGN : "=" > | < ARROW : "->" > -| < IDENTIFIER : (|) (|)* > -| < FUNCTIONSUFFIX : () > -| < #IMPL_OBJ_START: "#" > +| < IDENTIFIER : (|)* > | < #JAVALETTER: [ "\u0024", diff -Nru tomcat10-10.1.40/java/org/apache/el/parser/ELParserConstants.java tomcat10-10.1.52/java/org/apache/el/parser/ELParserConstants.java --- tomcat10-10.1.40/java/org/apache/el/parser/ELParserConstants.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/el/parser/ELParserConstants.java 2026-01-23 19:33:36.000000000 +0000 @@ -88,41 +88,35 @@ /** RegularExpression Id. */ int EMPTY = 43; /** RegularExpression Id. */ - int INSTANCEOF = 44; + int MULT = 44; /** RegularExpression Id. */ - int MULT = 45; + int PLUS = 45; /** RegularExpression Id. */ - int PLUS = 46; + int MINUS = 46; /** RegularExpression Id. */ - int MINUS = 47; + int QUESTIONMARK = 47; /** RegularExpression Id. */ - int QUESTIONMARK = 48; + int DIV0 = 48; /** RegularExpression Id. */ - int DIV0 = 49; + int DIV1 = 49; /** RegularExpression Id. */ - int DIV1 = 50; + int MOD0 = 50; /** RegularExpression Id. */ - int MOD0 = 51; + int MOD1 = 51; /** RegularExpression Id. */ - int MOD1 = 52; + int CONCAT = 52; /** RegularExpression Id. */ - int CONCAT = 53; + int ASSIGN = 53; /** RegularExpression Id. */ - int ASSIGN = 54; + int ARROW = 54; /** RegularExpression Id. */ - int ARROW = 55; + int IDENTIFIER = 55; /** RegularExpression Id. */ - int IDENTIFIER = 56; + int JAVALETTER = 56; /** RegularExpression Id. */ - int FUNCTIONSUFFIX = 57; + int JAVADIGIT = 57; /** RegularExpression Id. */ - int IMPL_OBJ_START = 58; - /** RegularExpression Id. */ - int JAVALETTER = 59; - /** RegularExpression Id. */ - int JAVADIGIT = 60; - /** RegularExpression Id. */ - int ILLEGAL_CHARACTER = 61; + int ILLEGAL_CHARACTER = 58; /** Lexical state. */ int DEFAULT = 0; @@ -137,8 +131,7 @@ "", "\"true\"", "\"false\"", "\"null\"", "\".\"", "\"(\"", "\")\"", "\"[\"", "\"]\"", "\":\"", "\";\"", "\",\"", "\">\"", "\"gt\"", "\"<\"", "\"lt\"", "\">=\"", "\"ge\"", "\"<=\"", "\"le\"", "\"==\"", "\"eq\"", "\"!=\"", "\"ne\"", "\"!\"", "\"not\"", "\"&&\"", "\"and\"", "\"||\"", "\"or\"", - "\"empty\"", "\"instanceof\"", "\"*\"", "\"+\"", "\"-\"", "\"?\"", "\"/\"", "\"div\"", "\"%\"", "\"mod\"", - "\"+=\"", "\"=\"", "\"->\"", "", "", "\"#\"", "", "", - "", }; + "\"empty\"", "\"*\"", "\"+\"", "\"-\"", "\"?\"", "\"/\"", "\"div\"", "\"%\"", "\"mod\"", "\"+=\"", "\"=\"", + "\"->\"", "", "", "", "", }; } diff -Nru tomcat10-10.1.40/java/org/apache/el/parser/ELParserTokenManager.java tomcat10-10.1.52/java/org/apache/el/parser/ELParserTokenManager.java --- tomcat10-10.1.40/java/org/apache/el/parser/ELParserTokenManager.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/el/parser/ELParserTokenManager.java 2026-01-23 19:33:36.000000000 +0000 @@ -301,77 +301,39 @@ if ((active0 & 0x20000L) != 0L) { return 1; } - if ((active0 & 0x141d555401c000L) != 0L) { - jjmatchedKind = 56; - return 30; + if ((active0 & 0xa0d555401c000L) != 0L) { + jjmatchedKind = 55; + return 16; } return -1; case 1: - if ((active0 & 0x41554000000L) != 0L) { - return 30; - } - if ((active0 & 0x1419400001c000L) != 0L) { - jjmatchedKind = 56; + if ((active0 & 0xa09400001c000L) != 0L) { + jjmatchedKind = 55; jjmatchedPos = 1; - return 30; + return 16; + } + if ((active0 & 0x41554000000L) != 0L) { + return 16; } return -1; case 2: - if ((active0 & 0x14014000000000L) != 0L) { - return 30; + if ((active0 & 0xa014000000000L) != 0L) { + return 16; } - if ((active0 & 0x18000001c000L) != 0L) { - jjmatchedKind = 56; + if ((active0 & 0x8000001c000L) != 0L) { + jjmatchedKind = 55; jjmatchedPos = 2; - return 30; + return 16; } return -1; case 3: if ((active0 & 0x14000L) != 0L) { - return 30; + return 16; } - if ((active0 & 0x180000008000L) != 0L) { - jjmatchedKind = 56; - jjmatchedPos = 3; - return 30; - } - return -1; - case 4: if ((active0 & 0x80000008000L) != 0L) { - return 30; - } - if ((active0 & 0x100000000000L) != 0L) { - jjmatchedKind = 56; - jjmatchedPos = 4; - return 30; - } - return -1; - case 5: - if ((active0 & 0x100000000000L) != 0L) { - jjmatchedKind = 56; - jjmatchedPos = 5; - return 30; - } - return -1; - case 6: - if ((active0 & 0x100000000000L) != 0L) { - jjmatchedKind = 56; - jjmatchedPos = 6; - return 30; - } - return -1; - case 7: - if ((active0 & 0x100000000000L) != 0L) { - jjmatchedKind = 56; - jjmatchedPos = 7; - return 30; - } - return -1; - case 8: - if ((active0 & 0x100000000000L) != 0L) { - jjmatchedKind = 56; - jjmatchedPos = 8; - return 30; + jjmatchedKind = 55; + jjmatchedPos = 3; + return 16; } return -1; default: @@ -389,7 +351,7 @@ jjmatchedKind = 37; return jjMoveStringLiteralDfa1_2(0x800000000L); case 37: - return jjStopAtPos(0, 51); + return jjStopAtPos(0, 50); case 38: return jjMoveStringLiteralDfa1_2(0x8000000000L); case 40: @@ -397,19 +359,19 @@ case 41: return jjStopAtPos(0, 19); case 42: - return jjStopAtPos(0, 45); + return jjStopAtPos(0, 44); case 43: - jjmatchedKind = 46; - return jjMoveStringLiteralDfa1_2(0x20000000000000L); + jjmatchedKind = 45; + return jjMoveStringLiteralDfa1_2(0x10000000000000L); case 44: return jjStopAtPos(0, 24); case 45: - jjmatchedKind = 47; - return jjMoveStringLiteralDfa1_2(0x80000000000000L); + jjmatchedKind = 46; + return jjMoveStringLiteralDfa1_2(0x40000000000000L); case 46: return jjStartNfaWithStates_2(0, 17, 1); case 47: - return jjStopAtPos(0, 49); + return jjStopAtPos(0, 48); case 58: return jjStopAtPos(0, 22); case 59: @@ -418,13 +380,13 @@ jjmatchedKind = 27; return jjMoveStringLiteralDfa1_2(0x80000000L); case 61: - jjmatchedKind = 54; + jjmatchedKind = 53; return jjMoveStringLiteralDfa1_2(0x200000000L); case 62: jjmatchedKind = 25; return jjMoveStringLiteralDfa1_2(0x20000000L); case 63: - return jjStopAtPos(0, 48); + return jjStopAtPos(0, 47); case 91: return jjStopAtPos(0, 20); case 93: @@ -432,19 +394,17 @@ case 97: return jjMoveStringLiteralDfa1_2(0x10000000000L); case 100: - return jjMoveStringLiteralDfa1_2(0x4000000000000L); + return jjMoveStringLiteralDfa1_2(0x2000000000000L); case 101: return jjMoveStringLiteralDfa1_2(0x80400000000L); case 102: return jjMoveStringLiteralDfa1_2(0x8000L); case 103: return jjMoveStringLiteralDfa1_2(0x44000000L); - case 105: - return jjMoveStringLiteralDfa1_2(0x100000000000L); case 108: return jjMoveStringLiteralDfa1_2(0x110000000L); case 109: - return jjMoveStringLiteralDfa1_2(0x10000000000000L); + return jjMoveStringLiteralDfa1_2(0x8000000000000L); case 110: return jjMoveStringLiteralDfa1_2(0x5000010000L); case 111: @@ -484,49 +444,49 @@ return jjStopAtPos(1, 33); } else if ((active0 & 0x800000000L) != 0L) { return jjStopAtPos(1, 35); - } else if ((active0 & 0x20000000000000L) != 0L) { - return jjStopAtPos(1, 53); + } else if ((active0 & 0x10000000000000L) != 0L) { + return jjStopAtPos(1, 52); } break; case 62: - if ((active0 & 0x80000000000000L) != 0L) { - return jjStopAtPos(1, 55); + if ((active0 & 0x40000000000000L) != 0L) { + return jjStopAtPos(1, 54); } break; case 97: return jjMoveStringLiteralDfa2_2(active0, 0x8000L); case 101: if ((active0 & 0x40000000L) != 0L) { - return jjStartNfaWithStates_2(1, 30, 30); + return jjStartNfaWithStates_2(1, 30, 16); } else if ((active0 & 0x100000000L) != 0L) { - return jjStartNfaWithStates_2(1, 32, 30); + return jjStartNfaWithStates_2(1, 32, 16); } else if ((active0 & 0x1000000000L) != 0L) { - return jjStartNfaWithStates_2(1, 36, 30); + return jjStartNfaWithStates_2(1, 36, 16); } break; case 105: - return jjMoveStringLiteralDfa2_2(active0, 0x4000000000000L); + return jjMoveStringLiteralDfa2_2(active0, 0x2000000000000L); case 109: return jjMoveStringLiteralDfa2_2(active0, 0x80000000000L); case 110: - return jjMoveStringLiteralDfa2_2(active0, 0x110000000000L); + return jjMoveStringLiteralDfa2_2(active0, 0x10000000000L); case 111: - return jjMoveStringLiteralDfa2_2(active0, 0x10004000000000L); + return jjMoveStringLiteralDfa2_2(active0, 0x8004000000000L); case 113: if ((active0 & 0x400000000L) != 0L) { - return jjStartNfaWithStates_2(1, 34, 30); + return jjStartNfaWithStates_2(1, 34, 16); } break; case 114: if ((active0 & 0x40000000000L) != 0L) { - return jjStartNfaWithStates_2(1, 42, 30); + return jjStartNfaWithStates_2(1, 42, 16); } return jjMoveStringLiteralDfa2_2(active0, 0x4000L); case 116: if ((active0 & 0x4000000L) != 0L) { - return jjStartNfaWithStates_2(1, 26, 30); + return jjStartNfaWithStates_2(1, 26, 16); } else if ((active0 & 0x10000000L) != 0L) { - return jjStartNfaWithStates_2(1, 28, 30); + return jjStartNfaWithStates_2(1, 28, 16); } break; case 117: @@ -555,27 +515,25 @@ switch (curChar) { case 100: if ((active0 & 0x10000000000L) != 0L) { - return jjStartNfaWithStates_2(2, 40, 30); - } else if ((active0 & 0x10000000000000L) != 0L) { - return jjStartNfaWithStates_2(2, 52, 30); + return jjStartNfaWithStates_2(2, 40, 16); + } else if ((active0 & 0x8000000000000L) != 0L) { + return jjStartNfaWithStates_2(2, 51, 16); } break; case 108: return jjMoveStringLiteralDfa3_2(active0, 0x18000L); case 112: return jjMoveStringLiteralDfa3_2(active0, 0x80000000000L); - case 115: - return jjMoveStringLiteralDfa3_2(active0, 0x100000000000L); case 116: if ((active0 & 0x4000000000L) != 0L) { - return jjStartNfaWithStates_2(2, 38, 30); + return jjStartNfaWithStates_2(2, 38, 16); } break; case 117: return jjMoveStringLiteralDfa3_2(active0, 0x4000L); case 118: - if ((active0 & 0x4000000000000L) != 0L) { - return jjStartNfaWithStates_2(2, 50, 30); + if ((active0 & 0x2000000000000L) != 0L) { + return jjStartNfaWithStates_2(2, 49, 16); } break; default: @@ -597,18 +555,18 @@ switch (curChar) { case 101: if ((active0 & 0x4000L) != 0L) { - return jjStartNfaWithStates_2(3, 14, 30); + return jjStartNfaWithStates_2(3, 14, 16); } break; case 108: if ((active0 & 0x10000L) != 0L) { - return jjStartNfaWithStates_2(3, 16, 30); + return jjStartNfaWithStates_2(3, 16, 16); } break; case 115: return jjMoveStringLiteralDfa4_2(active0, 0x8000L); case 116: - return jjMoveStringLiteralDfa4_2(active0, 0x180000000000L); + return jjMoveStringLiteralDfa4_2(active0, 0x80000000000L); default: break; } @@ -626,16 +584,14 @@ return 4; } switch (curChar) { - case 97: - return jjMoveStringLiteralDfa5_2(active0, 0x100000000000L); case 101: if ((active0 & 0x8000L) != 0L) { - return jjStartNfaWithStates_2(4, 15, 30); + return jjStartNfaWithStates_2(4, 15, 16); } break; case 121: if ((active0 & 0x80000000000L) != 0L) { - return jjStartNfaWithStates_2(4, 43, 30); + return jjStartNfaWithStates_2(4, 43, 16); } break; default: @@ -644,104 +600,6 @@ return jjStartNfa_2(3, active0); } - private int jjMoveStringLiteralDfa5_2(long old0, long active0) { - if (((active0 &= old0)) == 0L) { - return jjStartNfa_2(3, old0); - } - try { - curChar = input_stream.readChar(); - } catch (java.io.IOException e) { - jjStopStringLiteralDfa_2(4, active0); - return 5; - } - switch (curChar) { - case 110: - return jjMoveStringLiteralDfa6_2(active0, 0x100000000000L); - default: - break; - } - return jjStartNfa_2(4, active0); - } - - private int jjMoveStringLiteralDfa6_2(long old0, long active0) { - if (((active0 &= old0)) == 0L) { - return jjStartNfa_2(4, old0); - } - try { - curChar = input_stream.readChar(); - } catch (java.io.IOException e) { - jjStopStringLiteralDfa_2(5, active0); - return 6; - } - switch (curChar) { - case 99: - return jjMoveStringLiteralDfa7_2(active0, 0x100000000000L); - default: - break; - } - return jjStartNfa_2(5, active0); - } - - private int jjMoveStringLiteralDfa7_2(long old0, long active0) { - if (((active0 &= old0)) == 0L) { - return jjStartNfa_2(5, old0); - } - try { - curChar = input_stream.readChar(); - } catch (java.io.IOException e) { - jjStopStringLiteralDfa_2(6, active0); - return 7; - } - switch (curChar) { - case 101: - return jjMoveStringLiteralDfa8_2(active0, 0x100000000000L); - default: - break; - } - return jjStartNfa_2(6, active0); - } - - private int jjMoveStringLiteralDfa8_2(long old0, long active0) { - if (((active0 &= old0)) == 0L) { - return jjStartNfa_2(6, old0); - } - try { - curChar = input_stream.readChar(); - } catch (java.io.IOException e) { - jjStopStringLiteralDfa_2(7, active0); - return 8; - } - switch (curChar) { - case 111: - return jjMoveStringLiteralDfa9_2(active0, 0x100000000000L); - default: - break; - } - return jjStartNfa_2(7, active0); - } - - private int jjMoveStringLiteralDfa9_2(long old0, long active0) { - if (((active0 &= old0)) == 0L) { - return jjStartNfa_2(7, old0); - } - try { - curChar = input_stream.readChar(); - } catch (java.io.IOException e) { - jjStopStringLiteralDfa_2(8, active0); - return 9; - } - switch (curChar) { - case 102: - if ((active0 & 0x100000000000L) != 0L) { - return jjStartNfaWithStates_2(9, 44, 30); - } - break; - default: - break; - } - return jjStartNfa_2(8, active0); - } - private int jjStartNfaWithStates_2(int pos, int kind, int state) { jjmatchedKind = kind; jjmatchedPos = pos; @@ -876,7 +734,7 @@ private int jjMoveNfa_2(int startState, int curPos) { int startsAt = 0; - jjnewStateCnt = 30; + jjnewStateCnt = 29; int i = 1; jjstateSet[0] = startState; int kind = 0x7fffffff; @@ -896,12 +754,12 @@ { jjCheckNAddStates(18, 22); } - } else if ((0x1800000000L & l) != 0L) { - if (kind > 56) { - kind = 56; + } else if (curChar == 36) { + if (kind > 55) { + kind = 55; } { - jjCheckNAddTwoStates(28, 29); + jjCheckNAdd(16); } } else if (curChar == 39) { jjCheckNAddStates(23, 25); @@ -911,24 +769,6 @@ jjCheckNAdd(1); } break; - case 30: - if ((0x3ff00100fffc1ffL & l) != 0L) { - if (kind > 57) { - kind = 57; - } - { - jjCheckNAdd(29); - } - } - if ((0x3ff00100fffc1ffL & l) != 0L) { - if (kind > 56) { - kind = 56; - } - { - jjCheckNAdd(28); - } - } - break; case 1: if ((0x3ff000000000000L & l) == 0L) { break; @@ -995,6 +835,26 @@ } break; case 15: + if (curChar != 36) { + break; + } + if (kind > 55) { + kind = 55; + } { + jjCheckNAdd(16); + } + break; + case 16: + if ((0x3ff00100fffc1ffL & l) == 0L) { + break; + } + if (kind > 55) { + kind = 55; + } { + jjCheckNAdd(16); + } + break; + case 17: if ((0x3ff000000000000L & l) == 0L) { break; } @@ -1004,106 +864,76 @@ jjCheckNAddStates(18, 22); } break; - case 16: + case 18: if ((0x3ff000000000000L & l) == 0L) { break; } if (kind > 10) { kind = 10; } { - jjCheckNAdd(16); + jjCheckNAdd(18); } break; - case 17: + case 19: if ((0x3ff000000000000L & l) != 0L) { - jjCheckNAddTwoStates(17, 18); + jjCheckNAddTwoStates(19, 20); } break; - case 18: + case 20: if (curChar != 46) { break; } if (kind > 11) { kind = 11; } { - jjCheckNAddTwoStates(19, 20); + jjCheckNAddTwoStates(21, 22); } break; - case 19: + case 21: if ((0x3ff000000000000L & l) == 0L) { break; } if (kind > 11) { kind = 11; } { - jjCheckNAddTwoStates(19, 20); + jjCheckNAddTwoStates(21, 22); } break; - case 21: + case 23: if ((0x280000000000L & l) != 0L) { - jjCheckNAdd(22); + jjCheckNAdd(24); } break; - case 22: + case 24: if ((0x3ff000000000000L & l) == 0L) { break; } if (kind > 11) { kind = 11; } { - jjCheckNAdd(22); + jjCheckNAdd(24); } break; - case 23: + case 25: if ((0x3ff000000000000L & l) != 0L) { - jjCheckNAddTwoStates(23, 24); + jjCheckNAddTwoStates(25, 26); } break; - case 25: + case 27: if ((0x280000000000L & l) != 0L) { - jjCheckNAdd(26); + jjCheckNAdd(28); } break; - case 26: + case 28: if ((0x3ff000000000000L & l) == 0L) { break; } if (kind > 11) { kind = 11; } { - jjCheckNAdd(26); - } - break; - case 27: - if ((0x1800000000L & l) == 0L) { - break; - } - if (kind > 56) { - kind = 56; - } { - jjCheckNAddTwoStates(28, 29); - } - break; - case 28: - if ((0x3ff00100fffc1ffL & l) == 0L) { - break; - } - if (kind > 56) { - kind = 56; - } { jjCheckNAdd(28); } break; - case 29: - if ((0x3ff00100fffc1ffL & l) == 0L) { - break; - } - if (kind > 57) { - kind = 57; - } { - jjCheckNAdd(29); - } - break; default: break; } @@ -1116,30 +946,12 @@ if ((0x7fffffe87fffffeL & l) == 0L) { break; } - if (kind > 56) { - kind = 56; + if (kind > 55) { + kind = 55; } { - jjCheckNAddTwoStates(28, 29); + jjCheckNAdd(16); } break; - case 30: - if ((0x87fffffe87fffffeL & l) != 0L) { - if (kind > 57) { - kind = 57; - } - { - jjCheckNAdd(29); - } - } - if ((0x87fffffe87fffffeL & l) != 0L) { - if (kind > 56) { - kind = 56; - } - { - jjCheckNAdd(28); - } - } - break; case 2: if ((0x2000000020L & l) != 0L) { jjAddStates(29, 30); @@ -1175,35 +987,25 @@ jjCheckNAddStates(23, 25); } break; - case 20: - if ((0x2000000020L & l) != 0L) { - jjAddStates(31, 32); - } - break; - case 24: - if ((0x2000000020L & l) != 0L) { - jjAddStates(33, 34); - } - break; - case 28: + case 16: if ((0x87fffffe87fffffeL & l) == 0L) { break; } - if (kind > 56) { - kind = 56; + if (kind > 55) { + kind = 55; } { - jjCheckNAdd(28); + jjCheckNAdd(16); } break; - case 29: - if ((0x87fffffe87fffffeL & l) == 0L) { - break; + case 22: + if ((0x2000000020L & l) != 0L) { + jjAddStates(31, 32); + } + break; + case 26: + if ((0x2000000020L & l) != 0L) { + jjAddStates(33, 34); } - if (kind > 57) { - kind = 57; - } { - jjCheckNAdd(29); - } break; default: break; @@ -1221,30 +1023,12 @@ if (!jjCanMove_1(hiByte, i1, i2, l1, l2)) { break; } - if (kind > 56) { - kind = 56; + if (kind > 55) { + kind = 55; } { - jjCheckNAddTwoStates(28, 29); + jjCheckNAdd(16); } break; - case 30: - if (jjCanMove_2(hiByte, i1, i2, l1, l2)) { - if (kind > 56) { - kind = 56; - } - { - jjCheckNAdd(28); - } - } - if (jjCanMove_2(hiByte, i1, i2, l1, l2)) { - if (kind > 57) { - kind = 57; - } - { - jjCheckNAdd(29); - } - } - break; case 6: if (jjCanMove_0(hiByte, i1, i2, l1, l2)) { jjAddStates(26, 28); @@ -1255,24 +1039,14 @@ jjAddStates(23, 25); } break; - case 28: - if (!jjCanMove_2(hiByte, i1, i2, l1, l2)) { - break; - } - if (kind > 56) { - kind = 56; - } { - jjCheckNAdd(28); - } - break; - case 29: + case 16: if (!jjCanMove_2(hiByte, i1, i2, l1, l2)) { break; } - if (kind > 57) { - kind = 57; + if (kind > 55) { + kind = 55; } { - jjCheckNAdd(29); + jjCheckNAdd(16); } break; default: @@ -1290,7 +1064,7 @@ kind = 0x7fffffff; } ++curPos; - if ((i = jjnewStateCnt) == (startsAt = 30 - (jjnewStateCnt = startsAt))) { + if ((i = jjnewStateCnt) == (startsAt = 29 - (jjnewStateCnt = startsAt))) { return curPos; } try { @@ -1307,77 +1081,39 @@ if ((active0 & 0x20000L) != 0L) { return 1; } - if ((active0 & 0x141d555401c000L) != 0L) { - jjmatchedKind = 56; - return 30; + if ((active0 & 0xa0d555401c000L) != 0L) { + jjmatchedKind = 55; + return 16; } return -1; case 1: - if ((active0 & 0x41554000000L) != 0L) { - return 30; - } - if ((active0 & 0x1419400001c000L) != 0L) { - jjmatchedKind = 56; + if ((active0 & 0xa09400001c000L) != 0L) { + jjmatchedKind = 55; jjmatchedPos = 1; - return 30; + return 16; + } + if ((active0 & 0x41554000000L) != 0L) { + return 16; } return -1; case 2: - if ((active0 & 0x14014000000000L) != 0L) { - return 30; + if ((active0 & 0xa014000000000L) != 0L) { + return 16; } - if ((active0 & 0x18000001c000L) != 0L) { - jjmatchedKind = 56; + if ((active0 & 0x8000001c000L) != 0L) { + jjmatchedKind = 55; jjmatchedPos = 2; - return 30; + return 16; } return -1; case 3: if ((active0 & 0x14000L) != 0L) { - return 30; + return 16; } - if ((active0 & 0x180000008000L) != 0L) { - jjmatchedKind = 56; - jjmatchedPos = 3; - return 30; - } - return -1; - case 4: if ((active0 & 0x80000008000L) != 0L) { - return 30; - } - if ((active0 & 0x100000000000L) != 0L) { - jjmatchedKind = 56; - jjmatchedPos = 4; - return 30; - } - return -1; - case 5: - if ((active0 & 0x100000000000L) != 0L) { - jjmatchedKind = 56; - jjmatchedPos = 5; - return 30; - } - return -1; - case 6: - if ((active0 & 0x100000000000L) != 0L) { - jjmatchedKind = 56; - jjmatchedPos = 6; - return 30; - } - return -1; - case 7: - if ((active0 & 0x100000000000L) != 0L) { - jjmatchedKind = 56; - jjmatchedPos = 7; - return 30; - } - return -1; - case 8: - if ((active0 & 0x100000000000L) != 0L) { - jjmatchedKind = 56; - jjmatchedPos = 8; - return 30; + jjmatchedKind = 55; + jjmatchedPos = 3; + return 16; } return -1; default: @@ -1395,7 +1131,7 @@ jjmatchedKind = 37; return jjMoveStringLiteralDfa1_1(0x800000000L); case 37: - return jjStopAtPos(0, 51); + return jjStopAtPos(0, 50); case 38: return jjMoveStringLiteralDfa1_1(0x8000000000L); case 40: @@ -1403,19 +1139,19 @@ case 41: return jjStopAtPos(0, 19); case 42: - return jjStopAtPos(0, 45); + return jjStopAtPos(0, 44); case 43: - jjmatchedKind = 46; - return jjMoveStringLiteralDfa1_1(0x20000000000000L); + jjmatchedKind = 45; + return jjMoveStringLiteralDfa1_1(0x10000000000000L); case 44: return jjStopAtPos(0, 24); case 45: - jjmatchedKind = 47; - return jjMoveStringLiteralDfa1_1(0x80000000000000L); + jjmatchedKind = 46; + return jjMoveStringLiteralDfa1_1(0x40000000000000L); case 46: return jjStartNfaWithStates_1(0, 17, 1); case 47: - return jjStopAtPos(0, 49); + return jjStopAtPos(0, 48); case 58: return jjStopAtPos(0, 22); case 59: @@ -1424,13 +1160,13 @@ jjmatchedKind = 27; return jjMoveStringLiteralDfa1_1(0x80000000L); case 61: - jjmatchedKind = 54; + jjmatchedKind = 53; return jjMoveStringLiteralDfa1_1(0x200000000L); case 62: jjmatchedKind = 25; return jjMoveStringLiteralDfa1_1(0x20000000L); case 63: - return jjStopAtPos(0, 48); + return jjStopAtPos(0, 47); case 91: return jjStopAtPos(0, 20); case 93: @@ -1438,19 +1174,17 @@ case 97: return jjMoveStringLiteralDfa1_1(0x10000000000L); case 100: - return jjMoveStringLiteralDfa1_1(0x4000000000000L); + return jjMoveStringLiteralDfa1_1(0x2000000000000L); case 101: return jjMoveStringLiteralDfa1_1(0x80400000000L); case 102: return jjMoveStringLiteralDfa1_1(0x8000L); case 103: return jjMoveStringLiteralDfa1_1(0x44000000L); - case 105: - return jjMoveStringLiteralDfa1_1(0x100000000000L); case 108: return jjMoveStringLiteralDfa1_1(0x110000000L); case 109: - return jjMoveStringLiteralDfa1_1(0x10000000000000L); + return jjMoveStringLiteralDfa1_1(0x8000000000000L); case 110: return jjMoveStringLiteralDfa1_1(0x5000010000L); case 111: @@ -1490,49 +1224,49 @@ return jjStopAtPos(1, 33); } else if ((active0 & 0x800000000L) != 0L) { return jjStopAtPos(1, 35); - } else if ((active0 & 0x20000000000000L) != 0L) { - return jjStopAtPos(1, 53); + } else if ((active0 & 0x10000000000000L) != 0L) { + return jjStopAtPos(1, 52); } break; case 62: - if ((active0 & 0x80000000000000L) != 0L) { - return jjStopAtPos(1, 55); + if ((active0 & 0x40000000000000L) != 0L) { + return jjStopAtPos(1, 54); } break; case 97: return jjMoveStringLiteralDfa2_1(active0, 0x8000L); case 101: if ((active0 & 0x40000000L) != 0L) { - return jjStartNfaWithStates_1(1, 30, 30); + return jjStartNfaWithStates_1(1, 30, 16); } else if ((active0 & 0x100000000L) != 0L) { - return jjStartNfaWithStates_1(1, 32, 30); + return jjStartNfaWithStates_1(1, 32, 16); } else if ((active0 & 0x1000000000L) != 0L) { - return jjStartNfaWithStates_1(1, 36, 30); + return jjStartNfaWithStates_1(1, 36, 16); } break; case 105: - return jjMoveStringLiteralDfa2_1(active0, 0x4000000000000L); + return jjMoveStringLiteralDfa2_1(active0, 0x2000000000000L); case 109: return jjMoveStringLiteralDfa2_1(active0, 0x80000000000L); case 110: - return jjMoveStringLiteralDfa2_1(active0, 0x110000000000L); + return jjMoveStringLiteralDfa2_1(active0, 0x10000000000L); case 111: - return jjMoveStringLiteralDfa2_1(active0, 0x10004000000000L); + return jjMoveStringLiteralDfa2_1(active0, 0x8004000000000L); case 113: if ((active0 & 0x400000000L) != 0L) { - return jjStartNfaWithStates_1(1, 34, 30); + return jjStartNfaWithStates_1(1, 34, 16); } break; case 114: if ((active0 & 0x40000000000L) != 0L) { - return jjStartNfaWithStates_1(1, 42, 30); + return jjStartNfaWithStates_1(1, 42, 16); } return jjMoveStringLiteralDfa2_1(active0, 0x4000L); case 116: if ((active0 & 0x4000000L) != 0L) { - return jjStartNfaWithStates_1(1, 26, 30); + return jjStartNfaWithStates_1(1, 26, 16); } else if ((active0 & 0x10000000L) != 0L) { - return jjStartNfaWithStates_1(1, 28, 30); + return jjStartNfaWithStates_1(1, 28, 16); } break; case 117: @@ -1561,27 +1295,25 @@ switch (curChar) { case 100: if ((active0 & 0x10000000000L) != 0L) { - return jjStartNfaWithStates_1(2, 40, 30); - } else if ((active0 & 0x10000000000000L) != 0L) { - return jjStartNfaWithStates_1(2, 52, 30); + return jjStartNfaWithStates_1(2, 40, 16); + } else if ((active0 & 0x8000000000000L) != 0L) { + return jjStartNfaWithStates_1(2, 51, 16); } break; case 108: return jjMoveStringLiteralDfa3_1(active0, 0x18000L); case 112: return jjMoveStringLiteralDfa3_1(active0, 0x80000000000L); - case 115: - return jjMoveStringLiteralDfa3_1(active0, 0x100000000000L); case 116: if ((active0 & 0x4000000000L) != 0L) { - return jjStartNfaWithStates_1(2, 38, 30); + return jjStartNfaWithStates_1(2, 38, 16); } break; case 117: return jjMoveStringLiteralDfa3_1(active0, 0x4000L); case 118: - if ((active0 & 0x4000000000000L) != 0L) { - return jjStartNfaWithStates_1(2, 50, 30); + if ((active0 & 0x2000000000000L) != 0L) { + return jjStartNfaWithStates_1(2, 49, 16); } break; default: @@ -1603,18 +1335,18 @@ switch (curChar) { case 101: if ((active0 & 0x4000L) != 0L) { - return jjStartNfaWithStates_1(3, 14, 30); + return jjStartNfaWithStates_1(3, 14, 16); } break; case 108: if ((active0 & 0x10000L) != 0L) { - return jjStartNfaWithStates_1(3, 16, 30); + return jjStartNfaWithStates_1(3, 16, 16); } break; case 115: return jjMoveStringLiteralDfa4_1(active0, 0x8000L); case 116: - return jjMoveStringLiteralDfa4_1(active0, 0x180000000000L); + return jjMoveStringLiteralDfa4_1(active0, 0x80000000000L); default: break; } @@ -1632,16 +1364,14 @@ return 4; } switch (curChar) { - case 97: - return jjMoveStringLiteralDfa5_1(active0, 0x100000000000L); case 101: if ((active0 & 0x8000L) != 0L) { - return jjStartNfaWithStates_1(4, 15, 30); + return jjStartNfaWithStates_1(4, 15, 16); } break; case 121: if ((active0 & 0x80000000000L) != 0L) { - return jjStartNfaWithStates_1(4, 43, 30); + return jjStartNfaWithStates_1(4, 43, 16); } break; default: @@ -1650,104 +1380,6 @@ return jjStartNfa_1(3, active0); } - private int jjMoveStringLiteralDfa5_1(long old0, long active0) { - if (((active0 &= old0)) == 0L) { - return jjStartNfa_1(3, old0); - } - try { - curChar = input_stream.readChar(); - } catch (java.io.IOException e) { - jjStopStringLiteralDfa_1(4, active0); - return 5; - } - switch (curChar) { - case 110: - return jjMoveStringLiteralDfa6_1(active0, 0x100000000000L); - default: - break; - } - return jjStartNfa_1(4, active0); - } - - private int jjMoveStringLiteralDfa6_1(long old0, long active0) { - if (((active0 &= old0)) == 0L) { - return jjStartNfa_1(4, old0); - } - try { - curChar = input_stream.readChar(); - } catch (java.io.IOException e) { - jjStopStringLiteralDfa_1(5, active0); - return 6; - } - switch (curChar) { - case 99: - return jjMoveStringLiteralDfa7_1(active0, 0x100000000000L); - default: - break; - } - return jjStartNfa_1(5, active0); - } - - private int jjMoveStringLiteralDfa7_1(long old0, long active0) { - if (((active0 &= old0)) == 0L) { - return jjStartNfa_1(5, old0); - } - try { - curChar = input_stream.readChar(); - } catch (java.io.IOException e) { - jjStopStringLiteralDfa_1(6, active0); - return 7; - } - switch (curChar) { - case 101: - return jjMoveStringLiteralDfa8_1(active0, 0x100000000000L); - default: - break; - } - return jjStartNfa_1(6, active0); - } - - private int jjMoveStringLiteralDfa8_1(long old0, long active0) { - if (((active0 &= old0)) == 0L) { - return jjStartNfa_1(6, old0); - } - try { - curChar = input_stream.readChar(); - } catch (java.io.IOException e) { - jjStopStringLiteralDfa_1(7, active0); - return 8; - } - switch (curChar) { - case 111: - return jjMoveStringLiteralDfa9_1(active0, 0x100000000000L); - default: - break; - } - return jjStartNfa_1(7, active0); - } - - private int jjMoveStringLiteralDfa9_1(long old0, long active0) { - if (((active0 &= old0)) == 0L) { - return jjStartNfa_1(7, old0); - } - try { - curChar = input_stream.readChar(); - } catch (java.io.IOException e) { - jjStopStringLiteralDfa_1(8, active0); - return 9; - } - switch (curChar) { - case 102: - if ((active0 & 0x100000000000L) != 0L) { - return jjStartNfaWithStates_1(9, 44, 30); - } - break; - default: - break; - } - return jjStartNfa_1(8, active0); - } - private int jjStartNfaWithStates_1(int pos, int kind, int state) { jjmatchedKind = kind; jjmatchedPos = pos; @@ -1761,7 +1393,7 @@ private int jjMoveNfa_1(int startState, int curPos) { int startsAt = 0; - jjnewStateCnt = 30; + jjnewStateCnt = 29; int i = 1; jjstateSet[0] = startState; int kind = 0x7fffffff; @@ -1781,12 +1413,12 @@ { jjCheckNAddStates(18, 22); } - } else if ((0x1800000000L & l) != 0L) { - if (kind > 56) { - kind = 56; + } else if (curChar == 36) { + if (kind > 55) { + kind = 55; } { - jjCheckNAddTwoStates(28, 29); + jjCheckNAdd(16); } } else if (curChar == 39) { jjCheckNAddStates(23, 25); @@ -1796,24 +1428,6 @@ jjCheckNAdd(1); } break; - case 30: - if ((0x3ff00100fffc1ffL & l) != 0L) { - if (kind > 57) { - kind = 57; - } - { - jjCheckNAdd(29); - } - } - if ((0x3ff00100fffc1ffL & l) != 0L) { - if (kind > 56) { - kind = 56; - } - { - jjCheckNAdd(28); - } - } - break; case 1: if ((0x3ff000000000000L & l) == 0L) { break; @@ -1880,6 +1494,26 @@ } break; case 15: + if (curChar != 36) { + break; + } + if (kind > 55) { + kind = 55; + } { + jjCheckNAdd(16); + } + break; + case 16: + if ((0x3ff00100fffc1ffL & l) == 0L) { + break; + } + if (kind > 55) { + kind = 55; + } { + jjCheckNAdd(16); + } + break; + case 17: if ((0x3ff000000000000L & l) == 0L) { break; } @@ -1889,106 +1523,76 @@ jjCheckNAddStates(18, 22); } break; - case 16: + case 18: if ((0x3ff000000000000L & l) == 0L) { break; } if (kind > 10) { kind = 10; } { - jjCheckNAdd(16); + jjCheckNAdd(18); } break; - case 17: + case 19: if ((0x3ff000000000000L & l) != 0L) { - jjCheckNAddTwoStates(17, 18); + jjCheckNAddTwoStates(19, 20); } break; - case 18: + case 20: if (curChar != 46) { break; } if (kind > 11) { kind = 11; } { - jjCheckNAddTwoStates(19, 20); + jjCheckNAddTwoStates(21, 22); } break; - case 19: + case 21: if ((0x3ff000000000000L & l) == 0L) { break; } if (kind > 11) { kind = 11; } { - jjCheckNAddTwoStates(19, 20); + jjCheckNAddTwoStates(21, 22); } break; - case 21: + case 23: if ((0x280000000000L & l) != 0L) { - jjCheckNAdd(22); + jjCheckNAdd(24); } break; - case 22: + case 24: if ((0x3ff000000000000L & l) == 0L) { break; } if (kind > 11) { kind = 11; } { - jjCheckNAdd(22); + jjCheckNAdd(24); } break; - case 23: + case 25: if ((0x3ff000000000000L & l) != 0L) { - jjCheckNAddTwoStates(23, 24); + jjCheckNAddTwoStates(25, 26); } break; - case 25: + case 27: if ((0x280000000000L & l) != 0L) { - jjCheckNAdd(26); + jjCheckNAdd(28); } break; - case 26: + case 28: if ((0x3ff000000000000L & l) == 0L) { break; } if (kind > 11) { kind = 11; } { - jjCheckNAdd(26); - } - break; - case 27: - if ((0x1800000000L & l) == 0L) { - break; - } - if (kind > 56) { - kind = 56; - } { - jjCheckNAddTwoStates(28, 29); - } - break; - case 28: - if ((0x3ff00100fffc1ffL & l) == 0L) { - break; - } - if (kind > 56) { - kind = 56; - } { jjCheckNAdd(28); } break; - case 29: - if ((0x3ff00100fffc1ffL & l) == 0L) { - break; - } - if (kind > 57) { - kind = 57; - } { - jjCheckNAdd(29); - } - break; default: break; } @@ -2001,30 +1605,12 @@ if ((0x7fffffe87fffffeL & l) == 0L) { break; } - if (kind > 56) { - kind = 56; + if (kind > 55) { + kind = 55; } { - jjCheckNAddTwoStates(28, 29); + jjCheckNAdd(16); } break; - case 30: - if ((0x87fffffe87fffffeL & l) != 0L) { - if (kind > 57) { - kind = 57; - } - { - jjCheckNAdd(29); - } - } - if ((0x87fffffe87fffffeL & l) != 0L) { - if (kind > 56) { - kind = 56; - } - { - jjCheckNAdd(28); - } - } - break; case 2: if ((0x2000000020L & l) != 0L) { jjAddStates(29, 30); @@ -2060,35 +1646,25 @@ jjCheckNAddStates(23, 25); } break; - case 20: - if ((0x2000000020L & l) != 0L) { - jjAddStates(31, 32); - } - break; - case 24: - if ((0x2000000020L & l) != 0L) { - jjAddStates(33, 34); - } - break; - case 28: + case 16: if ((0x87fffffe87fffffeL & l) == 0L) { break; } - if (kind > 56) { - kind = 56; + if (kind > 55) { + kind = 55; } { - jjCheckNAdd(28); + jjCheckNAdd(16); } break; - case 29: - if ((0x87fffffe87fffffeL & l) == 0L) { - break; + case 22: + if ((0x2000000020L & l) != 0L) { + jjAddStates(31, 32); + } + break; + case 26: + if ((0x2000000020L & l) != 0L) { + jjAddStates(33, 34); } - if (kind > 57) { - kind = 57; - } { - jjCheckNAdd(29); - } break; default: break; @@ -2106,30 +1682,12 @@ if (!jjCanMove_1(hiByte, i1, i2, l1, l2)) { break; } - if (kind > 56) { - kind = 56; + if (kind > 55) { + kind = 55; } { - jjCheckNAddTwoStates(28, 29); + jjCheckNAdd(16); } break; - case 30: - if (jjCanMove_2(hiByte, i1, i2, l1, l2)) { - if (kind > 56) { - kind = 56; - } - { - jjCheckNAdd(28); - } - } - if (jjCanMove_2(hiByte, i1, i2, l1, l2)) { - if (kind > 57) { - kind = 57; - } - { - jjCheckNAdd(29); - } - } - break; case 6: if (jjCanMove_0(hiByte, i1, i2, l1, l2)) { jjAddStates(26, 28); @@ -2140,24 +1698,14 @@ jjAddStates(23, 25); } break; - case 28: - if (!jjCanMove_2(hiByte, i1, i2, l1, l2)) { - break; - } - if (kind > 56) { - kind = 56; - } { - jjCheckNAdd(28); - } - break; - case 29: + case 16: if (!jjCanMove_2(hiByte, i1, i2, l1, l2)) { break; } - if (kind > 57) { - kind = 57; + if (kind > 55) { + kind = 55; } { - jjCheckNAdd(29); + jjCheckNAdd(16); } break; default: @@ -2175,7 +1723,7 @@ kind = 0x7fffffff; } ++curPos; - if ((i = jjnewStateCnt) == (startsAt = 30 - (jjnewStateCnt = startsAt))) { + if ((i = jjnewStateCnt) == (startsAt = 29 - (jjnewStateCnt = startsAt))) { return curPos; } try { @@ -2191,9 +1739,8 @@ "\175", null, null, null, null, "\164\162\165\145", "\146\141\154\163\145", "\156\165\154\154", "\56", "\50", "\51", "\133", "\135", "\72", "\73", "\54", "\76", "\147\164", "\74", "\154\164", "\76\75", "\147\145", "\74\75", "\154\145", "\75\75", "\145\161", "\41\75", "\156\145", "\41", "\156\157\164", - "\46\46", "\141\156\144", "\174\174", "\157\162", "\145\155\160\164\171", - "\151\156\163\164\141\156\143\145\157\146", "\52", "\53", "\55", "\77", "\57", "\144\151\166", "\45", - "\155\157\144", "\53\75", "\75", "\55\76", null, null, null, null, null, null, }; + "\46\46", "\141\156\144", "\174\174", "\157\162", "\145\155\160\164\171", "\52", "\53", "\55", "\77", "\57", + "\144\151\166", "\45", "\155\157\144", "\53\75", "\75", "\55\76", null, null, null, null, }; protected Token jjFillToken() { final Token t; @@ -2218,8 +1765,8 @@ return t; } - static final int[] jjnextStates = { 0, 1, 3, 4, 2, 0, 1, 4, 2, 0, 1, 4, 5, 2, 0, 1, 2, 6, 16, 17, 18, 23, 24, 11, - 12, 14, 6, 7, 9, 3, 4, 21, 22, 25, 26, }; + static final int[] jjnextStates = { 0, 1, 3, 4, 2, 0, 1, 4, 2, 0, 1, 4, 5, 2, 0, 1, 2, 6, 18, 19, 20, 25, 26, 11, + 12, 14, 6, 7, 9, 3, 4, 23, 24, 27, 28, }; private static final boolean jjCanMove_0(int hiByte, int i1, int i2, long l1, long l2) { switch (hiByte) { @@ -2465,7 +2012,8 @@ Token matchedToken; int curPos = 0; - EOFLoop: for (;;) { + EOFLoop: + for (;;) { try { curChar = input_stream.BeginToken(); } catch (Exception e) { @@ -2496,8 +2044,8 @@ jjmatchedKind = 0x7fffffff; jjmatchedPos = 0; curPos = jjMoveStringLiteralDfa0_1(); - if (jjmatchedPos == 0 && jjmatchedKind > 61) { - jjmatchedKind = 61; + if (jjmatchedPos == 0 && jjmatchedKind > 58) { + jjmatchedKind = 58; } break; case 2: @@ -2512,8 +2060,8 @@ jjmatchedKind = 0x7fffffff; jjmatchedPos = 0; curPos = jjMoveStringLiteralDfa0_2(); - if (jjmatchedPos == 0 && jjmatchedKind > 61) { - jjmatchedKind = 61; + if (jjmatchedPos == 0 && jjmatchedKind > 58) { + jjmatchedKind = 58; } break; } @@ -2657,7 +2205,7 @@ private void ReInitRounds() { int i; jjround = 0x80000001; - for (i = 30; i-- > 0;) { + for (i = 29; i-- > 0;) { jjrounds[i] = 0x80000000; } } @@ -2687,15 +2235,15 @@ /** Lex State array. */ public static final int[] jjnewLexState = { -1, -1, 1, 1, -1, -1, -1, -1, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, }; - static final long[] jjtoToken = { 0x23ffffffffffef0fL, }; + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, }; + static final long[] jjtoToken = { 0x4ffffffffffef0fL, }; static final long[] jjtoSkip = { 0xf0L, }; static final long[] jjtoSpecial = { 0x0L, }; static final long[] jjtoMore = { 0x0L, }; protected SimpleCharStream input_stream; - private final int[] jjrounds = new int[30]; - private final int[] jjstateSet = new int[2 * 30]; + private final int[] jjrounds = new int[29]; + private final int[] jjstateSet = new int[2 * 29]; private final StringBuilder jjimage = new StringBuilder(); private StringBuilder image = jjimage; private int jjimageLen; diff -Nru tomcat10-10.1.40/java/org/apache/el/parser/Node.java tomcat10-10.1.52/java/org/apache/el/parser/Node.java --- tomcat10-10.1.40/java/org/apache/el/parser/Node.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/el/parser/Node.java 2026-01-23 19:33:36.000000000 +0000 @@ -28,10 +28,6 @@ /* All AST nodes must implement this interface. It provides basic machinery for constructing the parent and child relationships between nodes. */ - -/** - * @author Jacob Hookom [jacob@hookom.net] - */ @SuppressWarnings("all") // Ignore warnings in generated code public interface Node { diff -Nru tomcat10-10.1.40/java/org/apache/el/parser/NodeVisitor.java tomcat10-10.1.52/java/org/apache/el/parser/NodeVisitor.java --- tomcat10-10.1.40/java/org/apache/el/parser/NodeVisitor.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/el/parser/NodeVisitor.java 2026-01-23 19:33:36.000000000 +0000 @@ -16,9 +16,6 @@ */ package org.apache.el.parser; -/** - * @author Jacob Hookom [jacob@hookom.net] - */ public interface NodeVisitor { void visit(Node node) throws Exception; diff -Nru tomcat10-10.1.40/java/org/apache/el/parser/SimpleNode.java tomcat10-10.1.52/java/org/apache/el/parser/SimpleNode.java --- tomcat10-10.1.40/java/org/apache/el/parser/SimpleNode.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/el/parser/SimpleNode.java 2026-01-23 19:33:36.000000000 +0000 @@ -28,9 +28,6 @@ import org.apache.el.lang.EvaluationContext; import org.apache.el.util.MessageFactory; -/** - * @author Jacob Hookom [jacob@hookom.net] - */ public abstract class SimpleNode implements Node { /* diff -Nru tomcat10-10.1.40/java/org/apache/el/util/MessageFactory.java tomcat10-10.1.52/java/org/apache/el/util/MessageFactory.java --- tomcat10-10.1.40/java/org/apache/el/util/MessageFactory.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/el/util/MessageFactory.java 2026-01-23 19:33:36.000000000 +0000 @@ -22,9 +22,6 @@ import java.util.MissingResourceException; import java.util.ResourceBundle; -/** - * @author Jacob Hookom [jacob@hookom.net] - */ public final class MessageFactory { private static final ResourceBundle DEFAULT_BUNDLE = ResourceBundle.getBundle("org.apache.el.LocalStrings"); diff -Nru tomcat10-10.1.40/java/org/apache/el/util/ReflectionUtil.java tomcat10-10.1.52/java/org/apache/el/util/ReflectionUtil.java --- tomcat10-10.1.40/java/org/apache/el/util/ReflectionUtil.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/el/util/ReflectionUtil.java 2026-01-23 19:33:36.000000000 +0000 @@ -32,11 +32,8 @@ import org.apache.el.lang.ELSupport; import org.apache.el.lang.EvaluationContext; - /** - * Utilities for Managing Serialization and Reflection - * - * @author Jacob Hookom [jacob@hookom.net] + * Utilities for Managing Serialization and Reflection. */ public class ReflectionUtil { @@ -155,12 +152,20 @@ // Fast path: when no arguments exist, there can only be one matching method and no need for coercion. if (paramCount == 0) { + Method result = null; + Throwable t = null; try { Method method = clazz.getMethod(methodName, paramTypes); - return getMethod(clazz, base, method); + result = getMethod(clazz, base, method); } catch (NoSuchMethodException | SecurityException e) { - // Fall through to broader, slower logic + // Fall through + t = e; + } + if (result == null) { + throw new MethodNotFoundException( + MessageFactory.get("error.method.notfound", base, property, paramString(paramTypes)), t); } + return result; } Method[] methods = clazz.getMethods(); diff -Nru tomcat10-10.1.40/java/org/apache/jasper/Constants.java tomcat10-10.1.52/java/org/apache/jasper/Constants.java --- tomcat10-10.1.40/java/org/apache/jasper/Constants.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/jasper/Constants.java 2026-01-23 19:33:36.000000000 +0000 @@ -20,11 +20,6 @@ /** * Some constants and other global data that are used by the compiler and the runtime. - * - * @author Anil K. Vijendran - * @author Harish Prabandham - * @author Shawn Bayern - * @author Mark Roth */ public class Constants { diff -Nru tomcat10-10.1.40/java/org/apache/jasper/EmbeddedServletOptions.java tomcat10-10.1.52/java/org/apache/jasper/EmbeddedServletOptions.java --- tomcat10-10.1.40/java/org/apache/jasper/EmbeddedServletOptions.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/jasper/EmbeddedServletOptions.java 2026-01-23 19:33:36.000000000 +0000 @@ -35,10 +35,6 @@ /** * A class to hold all init parameters specific to the JSP engine. - * - * @author Anil K. Vijendran - * @author Hans Bergsten - * @author Pierre Delisle */ public final class EmbeddedServletOptions implements Options { @@ -223,6 +219,8 @@ private boolean useInstanceManagerForTags = false; + private String useNonstandardTagOptimizations; + public String getProperty(String name) { return settings.getProperty(name); } @@ -470,6 +468,11 @@ return useInstanceManagerForTags; } + @Override + public String getUseNonstandardTagOptimizations() { + return useNonstandardTagOptimizations; + } + /** * Create an EmbeddedServletOptions object using data available from ServletConfig and ServletContext. * @@ -652,6 +655,11 @@ this.classpath = classpath; } + String useNonstandardTagOptimizations = config.getInitParameter("useNonstandardTagOptimizations"); + if (useNonstandardTagOptimizations != null) { + this.useNonstandardTagOptimizations = useNonstandardTagOptimizations; + } + /* * scratchdir */ diff -Nru tomcat10-10.1.40/java/org/apache/jasper/JasperException.java tomcat10-10.1.52/java/org/apache/jasper/JasperException.java --- tomcat10-10.1.40/java/org/apache/jasper/JasperException.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/jasper/JasperException.java 2026-01-23 19:33:36.000000000 +0000 @@ -18,8 +18,6 @@ /** * Base class for all exceptions generated by the JSP engine. Makes it convenient to catch just this at the top-level. - * - * @author Anil K. Vijendran */ public class JasperException extends jakarta.servlet.ServletException { diff -Nru tomcat10-10.1.40/java/org/apache/jasper/JspC.java tomcat10-10.1.52/java/org/apache/jasper/JspC.java --- tomcat10-10.1.40/java/org/apache/jasper/JspC.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/jasper/JspC.java 2026-01-23 19:33:36.000000000 +0000 @@ -86,11 +86,6 @@ * webXmlFragment="${build.dir}/generated_web.xml" * outputDir="${webapp.dir}/${webapp.name}/WEB-INF/src/my/package" /> * - * - * @author Danno Ferrin - * @author Pierre Delisle - * @author Costin Manolache - * @author Yoav Shapira */ public class JspC extends Task implements Options { @@ -268,6 +263,8 @@ protected boolean fullstop = false; protected String[] args; + protected String useNonstandardTagOptimizations; + public static void main(String[] arg) { if (arg.length == 0) { System.out.println(Localizer.getMessage("jspc.usage")); @@ -787,7 +784,7 @@ } try { uriRoot = resolveFile(s).getCanonicalPath(); - } catch (Exception ex) { + } catch (Exception e) { uriRoot = s; } } @@ -996,6 +993,15 @@ } /** + * Sets the set of custom tags to use nonstandard optimizations. + * + * @param useNonstandardTagOptimizations which tags to override + */ + public void setUseNonstandardTagOptimizations(String useNonstandardTagOptimizations) { + this.useNonstandardTagOptimizations = useNonstandardTagOptimizations; + } + + /** * @return true if an exception will be thrown in case of a compilation error. */ public boolean getFailOnError() { @@ -1403,7 +1409,7 @@ errorCount++; log.error(Localizer.getMessage("jspc.error.compilation"), e); } - } catch (InterruptedException e) { + } catch (InterruptedException ignore) { // Ignore } } @@ -1507,8 +1513,8 @@ mapout.write(Localizer.getMessage("jspc.webinc.footer")); } mapout.close(); - } catch (IOException ioe) { - // nothing to do if it fails since we are done with it + } catch (IOException ignore) { + // Nothing to do if it fails since we are done with it. } } } @@ -1680,7 +1686,7 @@ uriRoot = froot.getCanonicalPath(); } } - } catch (IOException ioe) { + } catch (IOException ignore) { // Missing uriRoot will be handled in the caller. } } @@ -1706,9 +1712,9 @@ FileInputStream fis = new FileInputStream(file); try { return webxmlEncoding != null ? new InputStreamReader(fis, webxmlEncoding) : new InputStreamReader(fis); - } catch (IOException ex) { + } catch (IOException ioe) { fis.close(); - throw ex; + throw ioe; } } @@ -1716,12 +1722,17 @@ FileOutputStream fos = new FileOutputStream(file); try { return webxmlEncoding != null ? new OutputStreamWriter(fos, webxmlEncoding) : new OutputStreamWriter(fos); - } catch (IOException ex) { + } catch (IOException ioe) { fos.close(); - throw ex; + throw ioe; } } + @Override + public String getUseNonstandardTagOptimizations() { + return useNonstandardTagOptimizations; + } + private class ProcessFile implements Callable { private final String file; diff -Nru tomcat10-10.1.40/java/org/apache/jasper/JspCompilationContext.java tomcat10-10.1.52/java/org/apache/jasper/JspCompilationContext.java --- tomcat10-10.1.40/java/org/apache/jasper/JspCompilationContext.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/jasper/JspCompilationContext.java 2026-01-23 19:33:36.000000000 +0000 @@ -46,12 +46,6 @@ * A placeholder for various things that are used throughout the JSP engine. This is a per-request/per-context data * structure. Some of the instance variables are set at different points. Most of the path-related stuff is here - * mangling names, versions, dirs, loading resources and dealing with uris. - * - * @author Anil K. Vijendran - * @author Harish Prabandham - * @author Pierre Delisle - * @author Costin Manolache - * @author Kin-man Chung */ public class JspCompilationContext { @@ -392,17 +386,17 @@ result = uc.getLastModified(); } } - } catch (IOException e) { + } catch (IOException ioe) { if (log.isDebugEnabled()) { - log.debug(Localizer.getMessage("jsp.error.lastModified", getJspFile()), e); + log.debug(Localizer.getMessage("jsp.error.lastModified", getJspFile()), ioe); } } finally { if (uc != null) { try { uc.getInputStream().close(); - } catch (IOException e) { + } catch (IOException ioe) { if (log.isDebugEnabled()) { - log.debug(Localizer.getMessage("jsp.error.lastModified", getJspFile()), e); + log.debug(Localizer.getMessage("jsp.error.lastModified", getJspFile()), ioe); } result = -1; } @@ -590,7 +584,6 @@ jspCompiler.removeGeneratedFiles(); jspLoader = null; jspCompiler.compile(); - jsw.setReload(true); jsw.setCompilationException(null); } catch (JasperException ex) { // Cache compilation exception @@ -603,11 +596,13 @@ } catch (FileNotFoundException fnfe) { // Re-throw to let caller handle this - will result in a 404 throw fnfe; - } catch (Exception ex) { - JasperException je = new JasperException(Localizer.getMessage("jsp.error.unable.compile"), ex); + } catch (Exception e) { + JasperException je = new JasperException(Localizer.getMessage("jsp.error.unable.compile"), e); // Cache compilation exception jsw.setCompilationException(je); throw je; + } finally { + jsw.setReload(true); } } } @@ -622,8 +617,8 @@ servletClass = jspLoader.loadClass(name); } catch (ClassNotFoundException cex) { throw new JasperException(Localizer.getMessage("jsp.error.unable.load"), cex); - } catch (Exception ex) { - throw new JasperException(Localizer.getMessage("jsp.error.unable.compile"), ex); + } catch (Exception e) { + throw new JasperException(Localizer.getMessage("jsp.error.unable.compile"), e); } removed = false; return servletClass; diff -Nru tomcat10-10.1.40/java/org/apache/jasper/Options.java tomcat10-10.1.52/java/org/apache/jasper/Options.java --- tomcat10-10.1.40/java/org/apache/jasper/Options.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/jasper/Options.java 2026-01-23 19:33:36.000000000 +0000 @@ -27,10 +27,6 @@ /** * A class to hold all init parameters specific to the JSP engine. - * - * @author Anil K. Vijendran - * @author Hans Bergsten - * @author Pierre Delisle */ public interface Options { @@ -342,4 +338,12 @@ default boolean getGeneratedJavaAddTimestamp() { return true; } + + /** + * A string containing a comma-separated list of names to which custom tag implementations should be applied. + * Unknown or unused tag entries are harmless. Generally defined via an init parameter on the JspServlet. + * + * @return which tags to use + */ + String getUseNonstandardTagOptimizations(); } diff -Nru tomcat10-10.1.40/java/org/apache/jasper/compiler/AntCompiler.java tomcat10-10.1.52/java/org/apache/jasper/compiler/AntCompiler.java --- tomcat10-10.1.40/java/org/apache/jasper/compiler/AntCompiler.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/jasper/compiler/AntCompiler.java 2026-01-23 19:33:36.000000000 +0000 @@ -37,13 +37,6 @@ /** * Main JSP compiler class. This class uses Ant for compiling. - * - * @author Anil K. Vijendran - * @author Mandar Raje - * @author Pierre Delisle - * @author Kin-man Chung - * @author Remy Maucherat - * @author Mark Roth */ public class AntCompiler extends Compiler { diff -Nru tomcat10-10.1.40/java/org/apache/jasper/compiler/BeanRepository.java tomcat10-10.1.52/java/org/apache/jasper/compiler/BeanRepository.java --- tomcat10-10.1.40/java/org/apache/jasper/compiler/BeanRepository.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/jasper/compiler/BeanRepository.java 2026-01-23 19:33:36.000000000 +0000 @@ -23,9 +23,6 @@ /** * Repository of {page, request, session, application}-scoped beans - * - * @author Mandar Raje - * @author Remy Maucherat */ public class BeanRepository { diff -Nru tomcat10-10.1.40/java/org/apache/jasper/compiler/Collector.java tomcat10-10.1.52/java/org/apache/jasper/compiler/Collector.java --- tomcat10-10.1.40/java/org/apache/jasper/compiler/Collector.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/jasper/compiler/Collector.java 2026-01-23 19:33:36.000000000 +0000 @@ -20,11 +20,7 @@ /** * Collect info about the page and nodes, and make them available through the PageInfo object. - * - * @author Kin-man Chung - * @author Mark Roth */ - class Collector { /** diff -Nru tomcat10-10.1.40/java/org/apache/jasper/compiler/Compiler.java tomcat10-10.1.52/java/org/apache/jasper/compiler/Compiler.java --- tomcat10-10.1.40/java/org/apache/jasper/compiler/Compiler.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/jasper/compiler/Compiler.java 2026-01-23 19:33:36.000000000 +0000 @@ -41,13 +41,6 @@ /** * Main JSP compiler class. This class uses Ant for compiling. - * - * @author Anil K. Vijendran - * @author Mandar Raje - * @author Pierre Delisle - * @author Kin-man Chung - * @author Remy Maucherat - * @author Mark Roth */ public abstract class Compiler { @@ -427,8 +420,8 @@ if (jsw != null && (ctxt.getOptions().getModificationTestInterval() > 0)) { - if (jsw.getLastModificationTest() + - (ctxt.getOptions().getModificationTestInterval() * 1000L) > System.currentTimeMillis()) { + if (jsw.getLastModificationTest() + (ctxt.getOptions().getModificationTestInterval() * 1000L) > System + .currentTimeMillis()) { return false; } jsw.setLastModificationTest(System.currentTimeMillis()); diff -Nru tomcat10-10.1.40/java/org/apache/jasper/compiler/DefaultErrorHandler.java tomcat10-10.1.52/java/org/apache/jasper/compiler/DefaultErrorHandler.java --- tomcat10-10.1.40/java/org/apache/jasper/compiler/DefaultErrorHandler.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/jasper/compiler/DefaultErrorHandler.java 2026-01-23 19:33:36.000000000 +0000 @@ -20,8 +20,6 @@ /** * Default implementation of ErrorHandler interface. - * - * @author Jan Luehe */ class DefaultErrorHandler implements ErrorHandler { diff -Nru tomcat10-10.1.40/java/org/apache/jasper/compiler/ELFunctionMapper.java tomcat10-10.1.52/java/org/apache/jasper/compiler/ELFunctionMapper.java --- tomcat10-10.1.40/java/org/apache/jasper/compiler/ELFunctionMapper.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/jasper/compiler/ELFunctionMapper.java 2026-01-23 19:33:36.000000000 +0000 @@ -34,8 +34,6 @@ /** * This class generates functions mappers for the EL expressions in the page. Instead of a global mapper, a mapper is * used for each call to EL evaluator, thus avoiding the prefix overlapping and redefinition issues. - * - * @author Kin-man Chung */ public class ELFunctionMapper { @@ -198,7 +196,8 @@ // Generate declaration for the map statically decName = getMapName(); - ss.append("private static org.apache.jasper.runtime.ProtectedFunctionMapper ").append(decName).append(";\n"); + ss.append("private static org.apache.jasper.runtime.ProtectedFunctionMapper ").append(decName) + .append(";\n"); ds.append(" ").append(decName).append("= "); ds.append("org.apache.jasper.runtime.ProtectedFunctionMapper"); diff -Nru tomcat10-10.1.40/java/org/apache/jasper/compiler/ELNode.java tomcat10-10.1.52/java/org/apache/jasper/compiler/ELNode.java --- tomcat10-10.1.40/java/org/apache/jasper/compiler/ELNode.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/jasper/compiler/ELNode.java 2026-01-23 19:33:36.000000000 +0000 @@ -27,10 +27,7 @@ /** * This class defines internal representation for an EL Expression. It currently only defines functions. It can be * expanded to define all the components of an EL expression, if need to. - * - * @author Kin-man Chung */ - public abstract class ELNode { public abstract void accept(Visitor v) throws JasperException; diff -Nru tomcat10-10.1.40/java/org/apache/jasper/compiler/ELParser.java tomcat10-10.1.52/java/org/apache/jasper/compiler/ELParser.java --- tomcat10-10.1.40/java/org/apache/jasper/compiler/ELParser.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/jasper/compiler/ELParser.java 2026-01-23 19:33:36.000000000 +0000 @@ -25,10 +25,7 @@ /** * This class implements a parser for EL expressions. It takes strings of the form xxx${..}yyy${..}zzz etc, and turn it * into a ELNode.Nodes. Currently, it only handles text outside ${..} and functions in ${ ..}. - * - * @author Kin-man Chung */ - public class ELParser { private Token curToken; // current token diff -Nru tomcat10-10.1.40/java/org/apache/jasper/compiler/ErrorDispatcher.java tomcat10-10.1.52/java/org/apache/jasper/compiler/ErrorDispatcher.java --- tomcat10-10.1.40/java/org/apache/jasper/compiler/ErrorDispatcher.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/jasper/compiler/ErrorDispatcher.java 2026-01-23 19:33:36.000000000 +0000 @@ -36,9 +36,6 @@ *

          * In the case of a Java compilation error, the compiler error message is parsed into an array of JavacErrorDetail * instances, which is passed on to the configured error handler. - * - * @author Jan Luehe - * @author Kin-man Chung */ public class ErrorDispatcher { diff -Nru tomcat10-10.1.40/java/org/apache/jasper/compiler/ErrorHandler.java tomcat10-10.1.52/java/org/apache/jasper/compiler/ErrorHandler.java --- tomcat10-10.1.40/java/org/apache/jasper/compiler/ErrorHandler.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/jasper/compiler/ErrorHandler.java 2026-01-23 19:33:36.000000000 +0000 @@ -22,14 +22,14 @@ * Interface for handling JSP parse and javac compilation errors. An implementation of this interface may be registered * with the ErrorDispatcher by setting the XXX initialization parameter in the JSP page compiler and execution servlet * in Catalina's web.xml file to the implementation's fully qualified class name. - * - * @author Jan Luehe - * @author Kin-man Chung */ public interface ErrorHandler { /** * Processes the given JSP parse error. + *

          + * It is expected (and Jasper is coded based on this) that calls to this method will always result in a + * {@code JasperException} being thrown. * * @param fname Name of the JSP file in which the parse error occurred * @param line Parse error line number @@ -43,6 +43,9 @@ /** * Processes the given JSP parse error. + *

          + * It is expected (and Jasper is coded based on this) that calls to this method will always result in a + * {@code JasperException} being thrown. * * @param msg Parse error message * @param exception Parse exception @@ -53,6 +56,9 @@ /** * Processes the given javac compilation errors. + *

          + * It is expected (and Jasper is coded based on this) that calls to this method will always result in a + * {@code JasperException} being thrown. * * @param details Array of JavacErrorDetail instances corresponding to the compilation errors * @@ -62,6 +68,9 @@ /** * Processes the given javac error report and exception. + *

          + * It is expected (and Jasper is coded based on this) that calls to this method will always result in a + * {@code JasperException} being thrown. * * @param errorReport Compilation error report * @param exception Compilation exception diff -Nru tomcat10-10.1.40/java/org/apache/jasper/compiler/Generator.java tomcat10-10.1.52/java/org/apache/jasper/compiler/Generator.java --- tomcat10-10.1.40/java/org/apache/jasper/compiler/Generator.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/jasper/compiler/Generator.java 2026-01-23 19:33:36.000000000 +0000 @@ -51,6 +51,7 @@ import org.apache.jasper.JspCompilationContext; import org.apache.jasper.TrimSpacesOption; import org.apache.jasper.compiler.Node.ChildInfoBase; +import org.apache.jasper.compiler.Node.JspAttribute; import org.apache.jasper.compiler.Node.NamedAttribute; import org.apache.jasper.runtime.JspRuntimeLibrary; import org.apache.juli.logging.Log; @@ -58,11 +59,7 @@ import org.xml.sax.Attributes; /** - * Generate Java source from Nodes - * - * @author Anil K. Vijendran, Danno Ferrin, Mandar Raje, Rajiv Mordani, Pierre Delisle - * @author Tomcat 4.1.x and Tomcat 5: Kin-man Chung, Jan Luehe, Shawn Bayern, Mark Roth, Denis Benoit - * @author Tomcat 6.x: Jacob Hookom, Remy Maucherat + * Generate Java source from Nodes. */ class Generator { @@ -74,6 +71,8 @@ private static final Pattern BLANK_LINE_PATTERN = Pattern.compile("(\\s*(\\n|\\r)+\\s*)"); + private static final String CORE_LIBS_URI = "http://java.sun.com/jsp/jstl/core"; + private final ServletWriter out; private final ArrayList methodsBuffered; @@ -106,6 +105,8 @@ private final ELInterpreter elInterpreter; + private final Set nonstandardCustomTagNames; + private final StringInterpreter stringInterpreter; /** @@ -1499,6 +1500,9 @@ @Override public void visit(Node.CustomTag n) throws JasperException { + if (visitPotentiallyNonstandardCustomTag(n)) { + return; + } // Use plugin to generate more efficient code if there is one. if (n.useTagPlugin()) { @@ -1755,7 +1759,7 @@ nvp = " + \" " + jspAttribute.getName() + "=\\\"\" + " + value + " + \"\\\"\""; } else { nvp = " + (java.lang.Boolean.valueOf(" + omit + ")?\"\":\" " + jspAttribute.getName() + - "=\\\"\" + " + value + " + \"\\\"\")"; + "=\\\"\" + " + value + " + \"\\\"\")"; } } else { value = attributeValue(jspAttribute, false, Object.class); @@ -2106,6 +2110,10 @@ writeNewInstance(tagHandlerVar, tagHandlerClass); } + // Wrap use of tag in try/finally to ensure clean-up takes place + out.printil("try {"); + out.pushIndent(); + // includes setting the context generateSetters(n, tagHandlerVar, handlerInfo, false); @@ -2285,13 +2293,15 @@ out.pushIndent(); out.printin(tagHandlerVar); out.println(".doFinally();"); - } - - if (n.implementsTryCatchFinally()) { out.popIndent(); out.printil("}"); } + // Ensure clean-up takes place + out.popIndent(); + out.printil("} finally {"); + out.pushIndent(); + if (usePooling(n)) { // Print tag reuse out.printin(n.getTagHandlerPoolName()); @@ -2304,6 +2314,8 @@ out.print(tagHandlerVar); out.println(", _jsp_getInstanceManager());"); } + out.popIndent(); + out.printil("}"); // Declare and synchronize AT_END scripting variables (must do this // outside the try/catch/finally block) @@ -3048,6 +3060,216 @@ return varName; } + + /** + * Determines whether a tag should be handled via nonstandard code (typically faster). Considers both + * configuration and level of support within Tomcat. + *

          + * Note that Tomcat is free to ignore any case it cannot handle, as long as it reports it accurately to the + * caller by returning false. For example, the initial implementation for c:set excludes support for body + * content. c:set tags with body content will be generated with the standard code and tags without body content + * will be generated via non-standard code. + * + * @param n tag + * @param jspAttributes jsp attributes + * + * @return whether code was generated + * + * @throws JasperException unexpected error + */ + private boolean visitPotentiallyNonstandardCustomTag(Node.CustomTag n) throws JasperException { + if (!nonstandardCustomTagNames.contains(n.getQName())) { + // tag is not configured, move along + return false; + } + + // collect the attributes into one Map for further checks + Map jspAttributes = new HashMap<>(); + if (n.getJspAttributes() != null) { + for (JspAttribute jspAttr : n.getJspAttributes()) { + jspAttributes.put(jspAttr.getLocalName(), jspAttr); + } + } + switch (n.qName) { + case "c:set": + // requires var and value, scope is optional, body is prohibited, value cannot be deferred + if (n.hasEmptyBody() && jspAttributes.containsKey("var") && jspAttributes.containsKey("value") && + CORE_LIBS_URI.equals(n.getURI())) { + // verify value is not a deferred expression + String valueText = jspAttributes.get("value").getValue(); + if (valueText.startsWith("#")) { + return false; + } else if (jspAttributes.size() == 2 || + (jspAttributes.size() == 3 && jspAttributes.containsKey("scope"))) { + generateNonstandardSetLogic(n, jspAttributes); + return true; + } + } + break; + case "c:remove": + // requires var, scope is optional, body is prohibited + if (n.hasEmptyBody() && jspAttributes.containsKey("var") && CORE_LIBS_URI.equals(n.getURI()) && + (jspAttributes.size() == 1 || + (jspAttributes.size() == 2 && jspAttributes.containsKey("scope")))) { + generateNonstandardRemoveLogic(n, jspAttributes); + return true; + + } + break; + default: + // This indicates someone configured a tag with no non-standard implementation. + // Harmless, fall back to the standard implementation. + } + return false; + } + + private void generateNonstandardSetLogic(Node.CustomTag n, Map jspAttributes) + throws JasperException { + String baseVar = createTagVarName(n.getQName(), n.getPrefix(), n.getLocalName()); + String tagMethod = "_jspx_meth_" + baseVar; + ServletWriter outSave = out; + + // generate method call + out.printin(tagMethod); + out.print("("); + out.print("_jspx_page_context"); + out.println(");"); + GenBuffer genBuffer = new GenBuffer(n, n.getBody()); + methodsBuffered.add(genBuffer); + out = genBuffer.getOut(); + + // Generate code for method declaration + methodNesting++; + out.println(); + out.pushIndent(); + out.printin("private void "); + out.print(tagMethod); + out.println("(jakarta.servlet.jsp.PageContext _jspx_page_context)"); + out.printil(" throws java.lang.Throwable {"); + out.pushIndent(); + // Generated body of method + out.printil("// " + n.getQName()); + + JspAttribute varAttribute = jspAttributes.get("var"); + Mark m = n.getStart(); + out.printil("// " + m.getFile() + "(" + m.getLineNumber() + "," + m.getColumnNumber() + ") " + + varAttribute.getTagAttributeInfo()); + + JspAttribute valueAttribute = jspAttributes.get("value"); + m = n.getStart(); + out.printil("// " + m.getFile() + "(" + m.getLineNumber() + "," + m.getColumnNumber() + ") " + + valueAttribute.getTagAttributeInfo()); + + String varValue = varAttribute.getValue(); + + // get the scope constant at compile-time, where blank means page + String scopeValue = translateScopeToConstant(jspAttributes); + + // translates the specified value attributes into EL-interpretation code using standard logic + String evaluatedAttribute = evaluateAttribute(getTagHandlerInfo(n), valueAttribute, n, null); + + // call the multi-line logic equivalent of SetTag + out.printil("org.apache.jasper.runtime.JspRuntimeLibrary.nonstandardSetTag(_jspx_page_context, \"" + + varValue + "\", " + evaluatedAttribute + ", " + scopeValue + ");"); + + // Generate end of method + out.popIndent(); + out.printil("}"); + out.popIndent(); + + methodNesting--; + // restore previous writer + out = outSave; + } + + /** + * Compile-time translation of the scope variable into the constant equivalent. Avoids runtime evaluation as + * performed by SetTag. Unspecified scope means page. + * + * @param jspAttributes attributes + * + * @return equivalent constant from PageContext + */ + private String translateScopeToConstant(Map jspAttributes) { + String scopeValue; + JspAttribute scopeAttribute = jspAttributes.get("scope"); + if (scopeAttribute == null) { + scopeValue = "jakarta.servlet.jsp.PageContext.PAGE_SCOPE"; + } else { + switch (scopeAttribute.getValue()) { + case "": + case "page": + scopeValue = "jakarta.servlet.jsp.PageContext.PAGE_SCOPE"; + break; + case "request": + scopeValue = "jakarta.servlet.jsp.PageContext.REQUEST_SCOPE"; + break; + case "session": + scopeValue = "jakarta.servlet.jsp.PageContext.SESSION_SCOPE"; + break; + case "application": + scopeValue = "jakarta.servlet.jsp.PageContext.APPLICATION_SCOPE"; + break; + default: + throw new IllegalArgumentException(Localizer.getMessage("jsp.error.page.invalid.scope")); + } + } + return scopeValue; + } + + /** + * Generates the code for a non-standard remove. Note that removes w/o a specified scope will remove from all + * scopes. + * + * @param n tag + * @param jspAttributes attributes + * + * @throws JasperException unspecified error + */ + private void generateNonstandardRemoveLogic(Node.CustomTag n, Map jspAttributes) + throws JasperException { + String baseVar = createTagVarName(n.getQName(), n.getPrefix(), n.getLocalName()); + String tagMethod = "_jspx_meth_" + baseVar; + ServletWriter outSave = out; + + // generate method call + out.printin(tagMethod); + out.print("("); + out.print("_jspx_page_context"); + out.println(");"); + GenBuffer genBuffer = new GenBuffer(n, n.getBody()); + methodsBuffered.add(genBuffer); + out = genBuffer.getOut(); + + // Generate code for method declaration + methodNesting++; + out.println(); + out.pushIndent(); + out.printin("private void "); + out.print(tagMethod); + out.println("(jakarta.servlet.jsp.PageContext pageContext)"); + out.printil(" throws java.lang.Throwable {"); + out.pushIndent(); + // Generated body of method + String varValue = jspAttributes.get("var").getValue(); + JspAttribute scope = jspAttributes.get("scope"); + if (scope == null) { + // c:remove without a scope means remove from all scopes + out.printil("pageContext.removeAttribute(\"" + varValue + "\");"); + } else { + // c:remove with a scope means remove only from the specified scope + String scopeValue = translateScopeToConstant(jspAttributes); + out.printil("pageContext.removeAttribute(\"" + varValue + "\", " + scopeValue + ");"); + } + // Generate end of method + out.popIndent(); + out.printil("}"); + out.popIndent(); + + methodNesting--; + // restore previous writer + out = outSave; + } } private static void generateLocalVariables(ServletWriter out, ChildInfoBase n) { @@ -3190,6 +3412,12 @@ } timestampFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); timestampFormat.setTimeZone(TimeZone.getTimeZone("UTC")); + String nonstandardOptionsList = ctxt.getOptions().getUseNonstandardTagOptimizations(); + if (nonstandardOptionsList == null) { + nonstandardCustomTagNames = Collections.emptySet(); + } else { + nonstandardCustomTagNames = new HashSet<>(Arrays.asList(nonstandardOptionsList.split(","))); + } } /** diff -Nru tomcat10-10.1.40/java/org/apache/jasper/compiler/ImplicitTagLibraryInfo.java tomcat10-10.1.52/java/org/apache/jasper/compiler/ImplicitTagLibraryInfo.java --- tomcat10-10.1.40/java/org/apache/jasper/compiler/ImplicitTagLibraryInfo.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/jasper/compiler/ImplicitTagLibraryInfo.java 2026-01-23 19:33:36.000000000 +0000 @@ -44,8 +44,6 @@ /** * Class responsible for generating an implicit tag library containing tag handlers corresponding to the tag files in * "/WEB-INF/tags/" or a subdirectory of it. - * - * @author Jan Luehe */ class ImplicitTagLibraryInfo extends TagLibraryInfo { diff -Nru tomcat10-10.1.40/java/org/apache/jasper/compiler/JDTCompiler.java tomcat10-10.1.52/java/org/apache/jasper/compiler/JDTCompiler.java --- tomcat10-10.1.40/java/org/apache/jasper/compiler/JDTCompiler.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/jasper/compiler/JDTCompiler.java 2026-01-23 19:33:36.000000000 +0000 @@ -35,6 +35,7 @@ import java.util.StringTokenizer; import org.apache.jasper.JasperException; +import org.apache.jasper.runtime.ExceptionUtils; import org.apache.juli.logging.Log; import org.apache.juli.logging.LogFactory; import org.eclipse.jdt.core.compiler.IProblem; @@ -58,8 +59,6 @@ /** * JDT class compiler. This compiler will load source dependencies from the context classloader, reducing dramatically * disk access during the compilation process. Based on code from Cocoon2. - * - * @author Remy Maucherat */ public class JDTCompiler extends org.apache.jasper.compiler.Compiler { @@ -113,8 +112,8 @@ } result = new char[buf.length()]; buf.getChars(0, result.length, result, 0); - } catch (IOException e) { - log.error(Localizer.getMessage("jsp.error.compilation.source", sourceFile), e); + } catch (IOException ioe) { + log.error(Localizer.getMessage("jsp.error.compilation.source", sourceFile), ioe); } return result; } @@ -220,13 +219,20 @@ if (result.equals(targetClassName) || result.startsWith(targetClassName + '$')) { return false; } - String resourceName = result.replace('.', '/') + ".class"; - try (InputStream is = classLoader.getResourceAsStream(resourceName)) { - return is == null; - } catch (IOException e) { - // we are here, since close on is failed. That means it was not null - return false; + /* + * This might look heavy-weight but, with only the ClassLoader API available, trying to load the + * resource as a class is the only reliable way found so far to differentiate between a class and a + * package. Other options, such as getResource(), fail for some edge cases on case insensitive file + * systems. As this code is only called at compile time, the performance impact is not a significant + * concern. + */ + try { + classLoader.loadClass(result); + } catch (Throwable t) { + ExceptionUtils.handleThrowable(t); + return true; } + return false; } @Override @@ -500,8 +506,8 @@ } } } - } catch (IOException exc) { - log.error(Localizer.getMessage("jsp.error.compilation.jdt"), exc); + } catch (IOException ioe) { + log.error(Localizer.getMessage("jsp.error.compilation.jdt"), ioe); } } }; diff -Nru tomcat10-10.1.40/java/org/apache/jasper/compiler/JavaCompiler.java tomcat10-10.1.52/java/org/apache/jasper/compiler/JavaCompiler.java --- tomcat10-10.1.40/java/org/apache/jasper/compiler/JavaCompiler.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/jasper/compiler/JavaCompiler.java 2026-01-23 19:33:36.000000000 +0000 @@ -42,7 +42,7 @@ private final Log log = LogFactory.getLog(JavaCompiler.class); // must not be static @Override - protected void generateClass(Map smaps) throws JasperException, IOException { + protected void generateClass(Map smaps) throws JasperException, IOException { long t1 = 0; if (log.isDebugEnabled()) { @@ -51,14 +51,13 @@ javax.tools.JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); DiagnosticCollector diagnostics = new DiagnosticCollector<>(); - StandardJavaFileManager fileManager = - compiler.getStandardFileManager(diagnostics, null, Charset.forName(ctxt.getOptions().getJavaEncoding())); + StandardJavaFileManager fileManager = compiler.getStandardFileManager(diagnostics, null, + Charset.forName(ctxt.getOptions().getJavaEncoding())); Iterable compilationUnits = fileManager.getJavaFileObjectsFromFiles(List.of(new File(ctxt.getServletJavaFileName()))); // Perform Java compilation using the appropriate options - List compilerOptions = - List.of("-classpath", ctxt.getClassPath(), "-source", ctxt.getOptions().getCompilerSourceVM(), - "-target", ctxt.getOptions().getCompilerTargetVM()); + List compilerOptions = List.of("-classpath", ctxt.getClassPath(), "-source", + ctxt.getOptions().getCompilerSourceVM(), "-target", ctxt.getOptions().getCompilerTargetVM()); Boolean result = compiler.getTask(null, fileManager, diagnostics, compilerOptions, null, compilationUnits).call(); diff -Nru tomcat10-10.1.40/java/org/apache/jasper/compiler/JavacErrorDetail.java tomcat10-10.1.52/java/org/apache/jasper/compiler/JavacErrorDetail.java --- tomcat10-10.1.40/java/org/apache/jasper/compiler/JavacErrorDetail.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/jasper/compiler/JavacErrorDetail.java 2026-01-23 19:33:36.000000000 +0000 @@ -29,9 +29,6 @@ /** * Class providing details about a javac compilation error. - * - * @author Jan Luehe - * @author Kin-man Chung */ public class JavacErrorDetail { diff -Nru tomcat10-10.1.40/java/org/apache/jasper/compiler/JspConfig.java tomcat10-10.1.52/java/org/apache/jasper/compiler/JspConfig.java --- tomcat10-10.1.40/java/org/apache/jasper/compiler/JspConfig.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/jasper/compiler/JspConfig.java 2026-01-23 19:33:36.000000000 +0000 @@ -30,11 +30,7 @@ /** * Handles the jsp-config element in WEB_INF/web.xml. This is used for specifying the JSP configuration information on a * JSP page - * - * @author Kin-man Chung - * @author Remy Maucherat */ - public class JspConfig { // Logger diff -Nru tomcat10-10.1.40/java/org/apache/jasper/compiler/JspDocumentParser.java tomcat10-10.1.52/java/org/apache/jasper/compiler/JspDocumentParser.java --- tomcat10-10.1.40/java/org/apache/jasper/compiler/JspDocumentParser.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/jasper/compiler/JspDocumentParser.java 2026-01-23 19:33:36.000000000 +0000 @@ -50,11 +50,7 @@ /** * Class implementing a parser for a JSP document, that is, a JSP page in XML syntax. - * - * @author Jan Luehe - * @author Kin-man Chung */ - class JspDocumentParser extends DefaultHandler2 implements TagConstants { private static final String LEXICAL_HANDLER_PROPERTY = "http://xml.org/sax/properties/lexical-handler"; @@ -171,7 +167,7 @@ jspDocParser.isValidating = true; try { source.getByteStream().close(); - } catch (IOException e2) { + } catch (IOException ioe) { // ignore } source = JspUtil.getInputSource(path, jar, jspDocParser.ctxt); @@ -179,7 +175,7 @@ } finally { try { source.getByteStream().close(); - } catch (IOException e) { + } catch (IOException ioe) { // ignore } } @@ -364,8 +360,8 @@ * * The SAX does not call this method with all of the template text, but may invoke this method with chunks of it. * This is a problem when we try to determine if the text contains only whitespaces, or when we are looking for an - * EL expression string. Therefore, it is necessary to buffer and concatenate the chunks and process the concatenated - * text later (at beginTag and endTag) + * EL expression string. Therefore, it is necessary to buffer and concatenate the chunks and process the + * concatenated text later (at beginTag and endTag) * * @param buf The characters * diff -Nru tomcat10-10.1.40/java/org/apache/jasper/compiler/JspReader.java tomcat10-10.1.52/java/org/apache/jasper/compiler/JspReader.java --- tomcat10-10.1.40/java/org/apache/jasper/compiler/JspReader.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/jasper/compiler/JspReader.java 2026-01-23 19:33:36.000000000 +0000 @@ -31,18 +31,7 @@ /** * JspReader is an input buffer for the JSP parser. It should allow unlimited lookahead and pushback. It also has a * bunch of parsing utility methods for understanding html style content. - * - * @author Anil K. Vijendran - * @author Anselm Baird-Smith - * @author Harish Prabandham - * @author Rajiv Mordani - * @author Mandar Raje - * @author Danno Ferrin - * @author Kin-man Chung - * @author Shawn Bayern - * @author Mark Roth */ - class JspReader { /** @@ -116,9 +105,9 @@ if (reader != null) { try { reader.close(); - } catch (Exception any) { + } catch (Exception e) { if (log.isDebugEnabled()) { - log.debug(Localizer.getMessage("jsp.error.file.close"), any); + log.debug(Localizer.getMessage("jsp.error.file.close"), e); } } } @@ -405,7 +394,8 @@ Boolean result; Mark restart = null; - skip: while ((result = indexOf(firstChar, ret)) != null) { + skip: + while ((result = indexOf(firstChar, ret)) != null) { if (result.booleanValue()) { if (restart != null) { restart.init(current, true); @@ -442,7 +432,8 @@ int ch; int prev = 'x'; // Doesn't matter char firstChar = limit.charAt(0); - skip: for (ch = nextChar(ret); ch != -1; prev = ch, ch = nextChar(ret)) { + skip: + for (ch = nextChar(ret); ch != -1; prev = ch, ch = nextChar(ret)) { if (ch == '\\' && prev == '\\') { ch = 0; // Double \ is not an escape char anymore } else if (prev == '\\') { diff -Nru tomcat10-10.1.40/java/org/apache/jasper/compiler/JspRuntimeContext.java tomcat10-10.1.52/java/org/apache/jasper/compiler/JspRuntimeContext.java --- tomcat10-10.1.40/java/org/apache/jasper/compiler/JspRuntimeContext.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/jasper/compiler/JspRuntimeContext.java 2026-01-23 19:33:36.000000000 +0000 @@ -50,8 +50,6 @@ * Class for tracking JSP compile time file dependencies when the >%@include file="..."%< directive is used. A * background thread periodically checks the files a JSP page is dependent upon. If a dependent file changes the JSP * page which included it is recompiled. Only used if a web application context is a directory. - * - * @author Glenn L. Nielsen */ public final class JspRuntimeContext { diff -Nru tomcat10-10.1.40/java/org/apache/jasper/compiler/JspUtil.java tomcat10-10.1.52/java/org/apache/jasper/compiler/JspUtil.java --- tomcat10-10.1.40/java/org/apache/jasper/compiler/JspUtil.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/jasper/compiler/JspUtil.java 2026-01-23 19:33:36.000000000 +0000 @@ -33,13 +33,6 @@ /** * This class has all the utility method(s). Ideally should move all the bean containers here. - * - * @author Mandar Raje. - * @author Rajiv Mordani. - * @author Danno Ferrin - * @author Pierre Delisle - * @author Shawn Bayern - * @author Mark Roth */ public class JspUtil { @@ -803,7 +796,7 @@ } catch (IOException ioe) { try { in.close(); - } catch (IOException e) { + } catch (IOException ignore) { // Ignore } throw ioe; diff -Nru tomcat10-10.1.40/java/org/apache/jasper/compiler/Localizer.java tomcat10-10.1.52/java/org/apache/jasper/compiler/Localizer.java --- tomcat10-10.1.40/java/org/apache/jasper/compiler/Localizer.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/jasper/compiler/Localizer.java 2026-01-23 19:33:36.000000000 +0000 @@ -24,8 +24,6 @@ /** * Class responsible for converting error codes to corresponding localized error messages. - * - * @author Jan Luehe */ public class Localizer { diff -Nru tomcat10-10.1.40/java/org/apache/jasper/compiler/Mark.java tomcat10-10.1.52/java/org/apache/jasper/compiler/Mark.java --- tomcat10-10.1.40/java/org/apache/jasper/compiler/Mark.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/jasper/compiler/Mark.java 2026-01-23 19:33:36.000000000 +0000 @@ -23,8 +23,6 @@ /** * Mark represents a point in the JSP input. - * - * @author Anil K. Vijendran */ public final class Mark { diff -Nru tomcat10-10.1.40/java/org/apache/jasper/compiler/Node.java tomcat10-10.1.52/java/org/apache/jasper/compiler/Node.java --- tomcat10-10.1.40/java/org/apache/jasper/compiler/Node.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/jasper/compiler/Node.java 2026-01-23 19:33:36.000000000 +0000 @@ -42,13 +42,7 @@ /** * An internal data representation of a JSP page or a JSP document (XML). Also included here is a visitor class for * traversing nodes. - * - * @author Kin-man Chung - * @author Jan Luehe - * @author Shawn Bayern - * @author Mark Roth */ - public abstract class Node implements TagConstants { private static final VariableInfo[] ZERO_VARIABLE_INFO = {}; @@ -346,8 +340,8 @@ } /** - * Selects and invokes a method in the visitor class based on the node type. This is abstract and should be overridden - * by the extending classes. + * Selects and invokes a method in the visitor class based on the node type. This is abstract and should be + * overridden by the extending classes. * * @param v The visitor class */ diff -Nru tomcat10-10.1.40/java/org/apache/jasper/compiler/PageDataImpl.java tomcat10-10.1.52/java/org/apache/jasper/compiler/PageDataImpl.java --- tomcat10-10.1.40/java/org/apache/jasper/compiler/PageDataImpl.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/jasper/compiler/PageDataImpl.java 2026-01-23 19:33:36.000000000 +0000 @@ -36,8 +36,6 @@ * the XML view. This pass ignores any nodes other than JspRoot and TaglibDirective. During the second pass, the * SecondPassVisitor produces the XML view, using the combined jsp:root attributes determined in the first pass and any * remaining pages nodes (this pass ignores any JspRoot and TaglibDirective nodes). - * - * @author Jan Luehe */ class PageDataImpl extends PageData implements TagConstants { diff -Nru tomcat10-10.1.40/java/org/apache/jasper/compiler/PageInfo.java tomcat10-10.1.52/java/org/apache/jasper/compiler/PageInfo.java --- tomcat10-10.1.40/java/org/apache/jasper/compiler/PageInfo.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/jasper/compiler/PageInfo.java 2026-01-23 19:33:36.000000000 +0000 @@ -35,10 +35,7 @@ /** * A repository for various info about the translation unit under compilation. - * - * @author Kin-man Chung */ - public class PageInfo { private final List imports; @@ -530,8 +527,7 @@ /* * isThreadSafe */ - public void setIsThreadSafe(String value, Node n, ErrorDispatcher err) - throws JasperException { + public void setIsThreadSafe(String value, Node n, ErrorDispatcher err) throws JasperException { if ("true".equalsIgnoreCase(value)) { isThreadSafe = true; diff -Nru tomcat10-10.1.40/java/org/apache/jasper/compiler/Parser.java tomcat10-10.1.52/java/org/apache/jasper/compiler/Parser.java --- tomcat10-10.1.40/java/org/apache/jasper/compiler/Parser.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/jasper/compiler/Parser.java 2026-01-23 19:33:36.000000000 +0000 @@ -36,12 +36,7 @@ /** * This class implements a parser for a JSP page (non-xml view). JSP page grammar is included here for reference. The * token '#' that appears in the production indicates the current input token location in the production. - * - * @author Kin-man Chung - * @author Shawn Bayern - * @author Mark Roth */ - class Parser implements TagConstants { private final ParserController parserController; @@ -247,8 +242,8 @@ buf.append(ch); reader.nextChar(); ch = (char) reader.peekChar(); - } while (Character.isLetter(ch) || Character.isDigit(ch) || - ch == '.' || ch == '_' || ch == '-' || ch == ':'); + } while (Character.isLetter(ch) || Character.isDigit(ch) || ch == '.' || ch == '_' || ch == '-' || + ch == ':'); return buf.toString(); } return null; @@ -330,8 +325,8 @@ } } catch (FileNotFoundException ex) { err.jspError(start, "jsp.error.file.not.found", file); - } catch (Exception ex) { - err.jspError(start, ex.getMessage()); + } catch (Exception e) { + err.jspError(start, e.getMessage()); } } @@ -907,11 +902,8 @@ } /* - * <<<<<<< HEAD Parses OptionalBody, but also reused to parse bodies for plugin and param since the syntax is - * identical (the only thing that differs substantially is how to process the body, and thus we accept the body type - * as a parameter). ======= Parses OptionalBody, but also reused to parse bodies for param since the syntax is - * identical (the only thing that differs substantially is how to process the body, and thus we accept the body type - * as a parameter). >>>>>>> 76d2ad0a5d (Code clean-up. Formatting. No functional change.) + * Parses OptionalBody, but also reused to parse bodies for plugin and param since the syntax is identical (the only + * thing that differs substantially is how to process the body, and thus we accept the body type as a parameter). * * OptionalBody ::= EmptyBody | ActionBody * @@ -987,8 +979,8 @@ } /* - * <<<<<<< HEAD Params ::= `>' S? ( ( `' ( ( S? Param+ S? `' ) | ) ) | - * Param+ ) '' + * Params ::= `>' S? ( ( `' ( ( S? Param+ S? `' ) | ) ) | Param+ ) + * '' */ private void parseJspParams(Node parent) throws JasperException { Node jspParamsNode = new Node.ParamsAction(start, parent); diff -Nru tomcat10-10.1.40/java/org/apache/jasper/compiler/ParserController.java tomcat10-10.1.52/java/org/apache/jasper/compiler/ParserController.java --- tomcat10-10.1.40/java/org/apache/jasper/compiler/ParserController.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/jasper/compiler/ParserController.java 2026-01-23 19:33:36.000000000 +0000 @@ -36,9 +36,6 @@ * The same ParserController instance is used for a JSP page and any JSP segments included by it (via an include * directive), where each segment may be provided in standard or XML syntax. This class selects and invokes the * appropriate parser for the JSP page and its included segments. - * - * @author Pierre Delisle - * @author Jan Luehe */ public class ParserController implements TagConstants { diff -Nru tomcat10-10.1.40/java/org/apache/jasper/compiler/ScriptingVariabler.java tomcat10-10.1.52/java/org/apache/jasper/compiler/ScriptingVariabler.java --- tomcat10-10.1.40/java/org/apache/jasper/compiler/ScriptingVariabler.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/jasper/compiler/ScriptingVariabler.java 2026-01-23 19:33:36.000000000 +0000 @@ -28,8 +28,6 @@ /** * Class responsible for determining the scripting variables that every custom action needs to declare. - * - * @author Jan Luehe */ class ScriptingVariabler { diff -Nru tomcat10-10.1.40/java/org/apache/jasper/compiler/ServletWriter.java tomcat10-10.1.52/java/org/apache/jasper/compiler/ServletWriter.java --- tomcat10-10.1.40/java/org/apache/jasper/compiler/ServletWriter.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/jasper/compiler/ServletWriter.java 2026-01-23 19:33:36.000000000 +0000 @@ -20,9 +20,6 @@ /** * This is what is used to generate servlets. - * - * @author Anil K. Vijendran - * @author Kin-man Chung */ public class ServletWriter implements AutoCloseable { diff -Nru tomcat10-10.1.40/java/org/apache/jasper/compiler/SmapStratum.java tomcat10-10.1.52/java/org/apache/jasper/compiler/SmapStratum.java --- tomcat10-10.1.40/java/org/apache/jasper/compiler/SmapStratum.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/jasper/compiler/SmapStratum.java 2026-01-23 19:33:36.000000000 +0000 @@ -21,9 +21,6 @@ /** * Represents the line and file mappings associated with a JSR-045 "stratum". - * - * @author Jayson Falkner - * @author Shawn Bayern */ public class SmapStratum { diff -Nru tomcat10-10.1.40/java/org/apache/jasper/compiler/SmapUtil.java tomcat10-10.1.52/java/org/apache/jasper/compiler/SmapUtil.java --- tomcat10-10.1.40/java/org/apache/jasper/compiler/SmapUtil.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/jasper/compiler/SmapUtil.java 2026-01-23 19:33:36.000000000 +0000 @@ -39,12 +39,6 @@ /** * Contains static utilities for generating SMAP data based on the current version of Jasper. - * - * @author Jayson Falkner - * @author Shawn Bayern - * @author Robert Field (inner SDEInstaller class) - * @author Mark Roth - * @author Kin-man Chung */ public class SmapUtil { diff -Nru tomcat10-10.1.40/java/org/apache/jasper/compiler/TagFileProcessor.java tomcat10-10.1.52/java/org/apache/jasper/compiler/TagFileProcessor.java --- tomcat10-10.1.40/java/org/apache/jasper/compiler/TagFileProcessor.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/jasper/compiler/TagFileProcessor.java 2026-01-23 19:33:36.000000000 +0000 @@ -42,10 +42,7 @@ /** * 1. Processes and extracts the directive info in a tag file. 2. Compiles and loads tag files used in a JSP file. - * - * @author Kin-man Chung */ - public class TagFileProcessor { private List tempVector; @@ -441,7 +438,7 @@ Node.Nodes page = null; try { page = pc.parseTagFileDirectives(path, jar); - } catch (IOException e) { + } catch (IOException ioe) { err.jspError("jsp.error.file.not.found", path); } diff -Nru tomcat10-10.1.40/java/org/apache/jasper/compiler/TagLibraryInfoImpl.java tomcat10-10.1.52/java/org/apache/jasper/compiler/TagLibraryInfoImpl.java --- tomcat10-10.1.40/java/org/apache/jasper/compiler/TagLibraryInfoImpl.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/jasper/compiler/TagLibraryInfoImpl.java 2026-01-23 19:33:36.000000000 +0000 @@ -55,12 +55,6 @@ /** * Implementation of the TagLibraryInfo class from the JSP spec. - * - * @author Anil K. Vijendran - * @author Mandar Raje - * @author Pierre Delisle - * @author Kin-man Chung - * @author Jan Luehe */ class TagLibraryInfoImpl extends TagLibraryInfo implements TagConstants { @@ -152,7 +146,7 @@ if (urlConn != null) { try { urlConn.getInputStream().close(); - } catch (IOException e) { + } catch (IOException ignore) { // Ignore } } @@ -275,8 +269,8 @@ if (url.getProtocol().equals("war") && uri.endsWith(".jar")) { url = UriUtil.warToJar(url); } - } catch (Exception ex) { - err.jspError("jsp.error.tld.unable_to_get_jar", uri, ex.toString()); + } catch (Exception e) { + err.jspError("jsp.error.tld.unable_to_get_jar", uri, e.toString()); } if (uri.endsWith(".jar")) { if (url == null) { diff -Nru tomcat10-10.1.40/java/org/apache/jasper/compiler/TagPluginManager.java tomcat10-10.1.52/java/org/apache/jasper/compiler/TagPluginManager.java --- tomcat10-10.1.40/java/org/apache/jasper/compiler/TagPluginManager.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/jasper/compiler/TagPluginManager.java 2026-01-23 19:33:36.000000000 +0000 @@ -36,8 +36,6 @@ /** * Manages tag plugin optimizations. - * - * @author Kin-man Chung */ public class TagPluginManager { diff -Nru tomcat10-10.1.40/java/org/apache/jasper/compiler/TldCache.java tomcat10-10.1.52/java/org/apache/jasper/compiler/TldCache.java --- tomcat10-10.1.40/java/org/apache/jasper/compiler/TldCache.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/jasper/compiler/TldCache.java 2026-01-23 19:33:36.000000000 +0000 @@ -138,7 +138,7 @@ result[1] = jar.getLastModified(tldResourcePath.getEntryName()); } } - } catch (IOException e) { + } catch (IOException ignore) { // Ignore (shouldn't happen) } return result; diff -Nru tomcat10-10.1.40/java/org/apache/jasper/compiler/Validator.java tomcat10-10.1.52/java/org/apache/jasper/compiler/Validator.java --- tomcat10-10.1.40/java/org/apache/jasper/compiler/Validator.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/jasper/compiler/Validator.java 2026-01-23 19:33:36.000000000 +0000 @@ -50,11 +50,6 @@ /** * Performs validation on the page elements. Attributes are checked for mandatory presence, entry value validity, and * consistency. As a side effect, some page global value (such as those from page directives) are stored, for later use. - * - * @author Kin-man Chung - * @author Jan Luehe - * @author Shawn Bayern - * @author Mark Roth */ class Validator { @@ -1025,7 +1020,7 @@ } for (int j = 0; tldAttrs != null && j < tldAttrs.length; j++) { if (attrs.getLocalName(i).equals(tldAttrs[j].getName()) && (attrs.getURI(i) == null || - attrs.getURI(i).isEmpty() || attrs.getURI(i).equals(n.getURI()))) { + attrs.getURI(i).isEmpty() || attrs.getURI(i).equals(n.getURI()))) { TagAttributeInfo tldAttr = tldAttrs[j]; if (tldAttr.canBeRequestTime() || tldAttr.isDeferredMethod() || tldAttr.isDeferredValue()) { // JSP diff -Nru tomcat10-10.1.40/java/org/apache/jasper/compiler/tagplugin/TagPluginContext.java tomcat10-10.1.52/java/org/apache/jasper/compiler/tagplugin/TagPluginContext.java --- tomcat10-10.1.40/java/org/apache/jasper/compiler/tagplugin/TagPluginContext.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/jasper/compiler/tagplugin/TagPluginContext.java 2026-01-23 19:33:36.000000000 +0000 @@ -81,8 +81,8 @@ String getConstantAttribute(String attribute); /** - * Generate codes to evaluate value of an attribute in the custom tag The codes is a Java expression. NOTE: Currently - * cannot handle attributes that are fragments. + * Generate codes to evaluate value of an attribute in the custom tag The codes is a Java expression. NOTE: + * Currently cannot handle attributes that are fragments. * * @param attribute The specified attribute */ diff -Nru tomcat10-10.1.40/java/org/apache/jasper/el/ELContextImpl.java tomcat10-10.1.52/java/org/apache/jasper/el/ELContextImpl.java --- tomcat10-10.1.40/java/org/apache/jasper/el/ELContextImpl.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/jasper/el/ELContextImpl.java 2026-01-23 19:33:36.000000000 +0000 @@ -38,9 +38,7 @@ import org.apache.jasper.Constants; /** - * Implementation of ELContext - * - * @author Jacob Hookom + * Implementation of ELContext. */ public class ELContextImpl extends ELContext { diff -Nru tomcat10-10.1.40/java/org/apache/jasper/el/ELContextWrapper.java tomcat10-10.1.52/java/org/apache/jasper/el/ELContextWrapper.java --- tomcat10-10.1.40/java/org/apache/jasper/el/ELContextWrapper.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/jasper/el/ELContextWrapper.java 2026-01-23 19:33:36.000000000 +0000 @@ -25,8 +25,6 @@ /** * Simple ELContextWrapper for runtime evaluation of EL w/ dynamic FunctionMappers - * - * @author jhook */ public final class ELContextWrapper extends ELContext { diff -Nru tomcat10-10.1.40/java/org/apache/jasper/el/JasperELResolver.java tomcat10-10.1.52/java/org/apache/jasper/el/JasperELResolver.java --- tomcat10-10.1.40/java/org/apache/jasper/el/JasperELResolver.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/jasper/el/JasperELResolver.java 2026-01-23 19:33:36.000000000 +0000 @@ -203,8 +203,8 @@ try { method.setAccessible(true); value = method.invoke(base, (Object[]) null); - } catch (Exception ex) { - Throwable thr = ExceptionUtils.unwrapInvocationTargetException(ex); + } catch (Exception e) { + Throwable thr = ExceptionUtils.unwrapInvocationTargetException(e); ExceptionUtils.handleThrowable(thr); } } @@ -222,8 +222,8 @@ context.setPropertyResolved(base, property); try { method.invoke(base, value); - } catch (Exception ex) { - Throwable thr = ExceptionUtils.unwrapInvocationTargetException(ex); + } catch (Exception e) { + Throwable thr = ExceptionUtils.unwrapInvocationTargetException(e); ExceptionUtils.handleThrowable(thr); } } diff -Nru tomcat10-10.1.40/java/org/apache/jasper/el/JspValueExpression.java tomcat10-10.1.52/java/org/apache/jasper/el/JspValueExpression.java --- tomcat10-10.1.40/java/org/apache/jasper/el/JspValueExpression.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/jasper/el/JspValueExpression.java 2026-01-23 19:33:36.000000000 +0000 @@ -28,9 +28,7 @@ import jakarta.el.ValueExpression; /** - * Wrapper for providing context to ValueExpressions - * - * @author Jacob Hookom + * Wrapper for providing context to ValueExpressions. */ public final class JspValueExpression extends ValueExpression implements Externalizable { diff -Nru tomcat10-10.1.40/java/org/apache/jasper/optimizations/ELInterpreterTagSetters.java tomcat10-10.1.52/java/org/apache/jasper/optimizations/ELInterpreterTagSetters.java --- tomcat10-10.1.40/java/org/apache/jasper/optimizations/ELInterpreterTagSetters.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/jasper/optimizations/ELInterpreterTagSetters.java 2026-01-23 19:33:36.000000000 +0000 @@ -110,7 +110,9 @@ BigDecimal unused = new BigDecimal(m.group(2)); result = "new java.math.BigDecimal(\"" + m.group(2) + "\")"; } catch (NumberFormatException e) { - log.debug(Localizer.getMessage("jsp.error.typeConversion", m.group(2), "BigDecimal"), e); + if (log.isDebugEnabled()) { + log.debug(Localizer.getMessage("jsp.error.typeConversion", m.group(2), "BigDecimal"), e); + } // Continue and resolve the value at runtime } } @@ -128,7 +130,9 @@ result = "Long.valueOf(\"" + m.group(2) + "\")"; } } catch (NumberFormatException e) { - log.debug(Localizer.getMessage("jsp.error.typeConversion", m.group(2), "Long"), e); + if (log.isDebugEnabled()) { + log.debug(Localizer.getMessage("jsp.error.typeConversion", m.group(2), "Long"), e); + } // Continue and resolve the value at runtime } } @@ -145,7 +149,9 @@ result = "Integer.valueOf(\"" + m.group(2) + "\")"; } } catch (NumberFormatException e) { - log.debug(Localizer.getMessage("jsp.error.typeConversion", m.group(2), "Integer"), e); + if (log.isDebugEnabled()) { + log.debug(Localizer.getMessage("jsp.error.typeConversion", m.group(2), "Integer"), e); + } // Continue and resolve the value at runtime } } @@ -163,7 +169,9 @@ result = "Short.valueOf(\"" + m.group(2) + "\")"; } } catch (NumberFormatException e) { - log.debug(Localizer.getMessage("jsp.error.typeConversion", m.group(2), "Short"), e); + if (log.isDebugEnabled()) { + log.debug(Localizer.getMessage("jsp.error.typeConversion", m.group(2), "Short"), e); + } // Continue and resolve the value at runtime } } @@ -181,7 +189,9 @@ result = "Byte.valueOf(\"" + m.group(2) + "\")"; } } catch (NumberFormatException e) { - log.debug(Localizer.getMessage("jsp.error.typeConversion", m.group(2), "Byte"), e); + if (log.isDebugEnabled()) { + log.debug(Localizer.getMessage("jsp.error.typeConversion", m.group(2), "Byte"), e); + } // Continue and resolve the value at runtime } } @@ -198,7 +208,9 @@ result = "Double.valueOf(\"" + m.group(2) + "\")"; } } catch (NumberFormatException e) { - log.debug(Localizer.getMessage("jsp.error.typeConversion", m.group(2), "Double"), e); + if (log.isDebugEnabled()) { + log.debug(Localizer.getMessage("jsp.error.typeConversion", m.group(2), "Double"), e); + } // Continue and resolve the value at runtime } } @@ -216,7 +228,9 @@ result = "Float.valueOf(\"" + m.group(2) + "\")"; } } catch (NumberFormatException e) { - log.debug(Localizer.getMessage("jsp.error.typeConversion", m.group(2), "Float"), e); + if (log.isDebugEnabled()) { + log.debug(Localizer.getMessage("jsp.error.typeConversion", m.group(2), "Float"), e); + } // Continue and resolve the value at runtime } } @@ -229,7 +243,9 @@ BigInteger unused = new BigInteger(m.group(2)); result = "new java.math.BigInteger(\"" + m.group(2) + "\")"; } catch (NumberFormatException e) { - log.debug(Localizer.getMessage("jsp.error.typeConversion", m.group(2), "BigInteger"), e); + if (log.isDebugEnabled()) { + log.debug(Localizer.getMessage("jsp.error.typeConversion", m.group(2), "BigInteger"), e); + } // Continue and resolve the value at runtime } } @@ -242,8 +258,10 @@ Enum enumValue = Enum.valueOf((Class) expectedType, m.group(2)); result = expectedType.getName() + "." + enumValue.name(); } catch (IllegalArgumentException iae) { - log.debug(Localizer.getMessage("jsp.error.typeConversion", m.group(2), - "Enum[" + expectedType.getName() + "]"), iae); + if (log.isDebugEnabled()) { + log.debug(Localizer.getMessage("jsp.error.typeConversion", m.group(2), + "Enum[" + expectedType.getName() + "]"), iae); + } // Continue and resolve the value at runtime } } diff -Nru tomcat10-10.1.40/java/org/apache/jasper/optimizations/StringInterpreterEnum.java tomcat10-10.1.52/java/org/apache/jasper/optimizations/StringInterpreterEnum.java --- tomcat10-10.1.40/java/org/apache/jasper/optimizations/StringInterpreterEnum.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/jasper/optimizations/StringInterpreterEnum.java 2026-01-23 19:33:36.000000000 +0000 @@ -37,7 +37,9 @@ Enum enumValue = Enum.valueOf((Class) c, s); return c.getName() + "." + enumValue.name(); } catch (IllegalArgumentException iae) { - log.debug(Localizer.getMessage("jsp.error.typeConversion", s, "Enum[" + c.getName() + "]"), iae); + if (log.isDebugEnabled()) { + log.debug(Localizer.getMessage("jsp.error.typeConversion", s, "Enum[" + c.getName() + "]"), iae); + } // Continue and resolve the value at runtime } } diff -Nru tomcat10-10.1.40/java/org/apache/jasper/runtime/BodyContentImpl.java tomcat10-10.1.52/java/org/apache/jasper/runtime/BodyContentImpl.java --- tomcat10-10.1.40/java/org/apache/jasper/runtime/BodyContentImpl.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/jasper/runtime/BodyContentImpl.java 2026-01-23 19:33:36.000000000 +0000 @@ -27,11 +27,8 @@ import org.apache.jasper.compiler.Localizer; /** - * Write text to a character-output stream, buffering characters to provide efficient writing of single - * characters, arrays, and strings. Provide support for discarding the output that has been buffered. - * - * @author Rajiv Mordani - * @author Jan Luehe + * Write text to a character-output stream, buffering characters to provide efficient writing of single characters, + * arrays, and strings. Provide support for discarding the output that has been buffered. */ public class BodyContentImpl extends BodyContent { @@ -370,7 +367,7 @@ this.writer = null; try { this.clear(); - } catch (IOException ex) { + } catch (IOException ignore) { // ignore } } diff -Nru tomcat10-10.1.40/java/org/apache/jasper/runtime/HttpJspBase.java tomcat10-10.1.52/java/org/apache/jasper/runtime/HttpJspBase.java --- tomcat10-10.1.40/java/org/apache/jasper/runtime/HttpJspBase.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/jasper/runtime/HttpJspBase.java 2026-01-23 19:33:36.000000000 +0000 @@ -30,8 +30,6 @@ /** * This is the super class of all JSP-generated servlets. - * - * @author Anil K. Vijendran */ public abstract class HttpJspBase extends HttpServlet implements HttpJspPage { diff -Nru tomcat10-10.1.40/java/org/apache/jasper/runtime/JspApplicationContextImpl.java tomcat10-10.1.52/java/org/apache/jasper/runtime/JspApplicationContextImpl.java --- tomcat10-10.1.40/java/org/apache/jasper/runtime/JspApplicationContextImpl.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/jasper/runtime/JspApplicationContextImpl.java 2026-01-23 19:33:36.000000000 +0000 @@ -36,9 +36,7 @@ import org.apache.jasper.el.JasperELResolver; /** - * Implementation of JspApplicationContext - * - * @author Jacob Hookom + * Implementation of JspApplicationContext. */ public class JspApplicationContextImpl implements JspApplicationContext { diff -Nru tomcat10-10.1.40/java/org/apache/jasper/runtime/JspContextWrapper.java tomcat10-10.1.52/java/org/apache/jasper/runtime/JspContextWrapper.java --- tomcat10-10.1.40/java/org/apache/jasper/runtime/JspContextWrapper.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/jasper/runtime/JspContextWrapper.java 2026-01-23 19:33:36.000000000 +0000 @@ -60,10 +60,6 @@ * Implementation of a JSP Context Wrapper. The JSP Context Wrapper is a JspContext created and maintained by a tag * handler implementation. It wraps the Invoking JSP Context, that is, the JspContext instance passed to the tag handler * by the invoking page via setJspContext(). - * - * @author Kin-man Chung - * @author Jan Luehe - * @author Jacob Hookom */ @SuppressWarnings("deprecation") // Have to support old JSP EL API public class JspContextWrapper extends PageContext implements VariableResolver { @@ -193,7 +189,7 @@ if (getSession() != null) { try { o = rootJspCtxt.getAttribute(name, SESSION_SCOPE); - } catch (IllegalStateException ise) { + } catch (IllegalStateException ignore) { // Session has been invalidated. // Ignore and fall through to application scope. } diff -Nru tomcat10-10.1.40/java/org/apache/jasper/runtime/JspFactoryImpl.java tomcat10-10.1.52/java/org/apache/jasper/runtime/JspFactoryImpl.java --- tomcat10-10.1.40/java/org/apache/jasper/runtime/JspFactoryImpl.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/jasper/runtime/JspFactoryImpl.java 2026-01-23 19:33:36.000000000 +0000 @@ -33,8 +33,6 @@ /** * Implementation of JspFactory. - * - * @author Anil K. Vijendran */ public class JspFactoryImpl extends JspFactory { @@ -102,7 +100,7 @@ try { pc.initialize(servlet, request, response, errorPageURL, needsSession, bufferSize, autoflush); - } catch (IOException ioe) { + } catch (IOException ignore) { // Implementation never throws IOE but can't change the signature // since it is part of the JSP API } diff -Nru tomcat10-10.1.40/java/org/apache/jasper/runtime/JspFragmentHelper.java tomcat10-10.1.52/java/org/apache/jasper/runtime/JspFragmentHelper.java --- tomcat10-10.1.40/java/org/apache/jasper/runtime/JspFragmentHelper.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/jasper/runtime/JspFragmentHelper.java 2026-01-23 19:33:36.000000000 +0000 @@ -27,8 +27,6 @@ * JspFragments in a single page. *

          * The class also provides various utility methods for JspFragment implementations. - * - * @author Mark Roth */ public abstract class JspFragmentHelper extends JspFragment { diff -Nru tomcat10-10.1.40/java/org/apache/jasper/runtime/JspRuntimeLibrary.java tomcat10-10.1.52/java/org/apache/jasper/runtime/JspRuntimeLibrary.java --- tomcat10-10.1.40/java/org/apache/jasper/runtime/JspRuntimeLibrary.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/jasper/runtime/JspRuntimeLibrary.java 2026-01-23 19:33:36.000000000 +0000 @@ -25,6 +25,7 @@ import java.nio.charset.StandardCharsets; import java.util.Enumeration; +import jakarta.el.VariableMapper; import jakarta.servlet.RequestDispatcher; import jakarta.servlet.ServletException; import jakarta.servlet.ServletRequest; @@ -45,9 +46,6 @@ /** * Bunch of util methods that are used by code generated for useBean, getProperty and setProperty. - * - * @author Mandar Raje - * @author Shawn Bayern */ public class JspRuntimeLibrary { @@ -280,8 +278,8 @@ } else { return getValueFromPropertyEditorManager(t, propertyName, s); } - } catch (Exception ex) { - throw new JasperException(ex); + } catch (Exception e) { + throw new JasperException(e); } } @@ -347,10 +345,10 @@ } } } - } catch (Exception ex) { - Throwable thr = ExceptionUtils.unwrapInvocationTargetException(ex); + } catch (Exception e) { + Throwable thr = ExceptionUtils.unwrapInvocationTargetException(e); ExceptionUtils.handleThrowable(thr); - throw new JasperException(ex); + throw new JasperException(e); } if (!ignoreMethodNF && (method == null)) { if (type == null) { @@ -573,10 +571,10 @@ try { Method method = getReadMethod(o.getClass(), prop); value = method.invoke(o, (Object[]) null); - } catch (Exception ex) { - Throwable thr = ExceptionUtils.unwrapInvocationTargetException(ex); + } catch (Exception e) { + Throwable thr = ExceptionUtils.unwrapInvocationTargetException(e); ExceptionUtils.handleThrowable(thr); - throw new JasperException(ex); + throw new JasperException(e); } return value; } @@ -586,12 +584,12 @@ ProtectedFunctionMapper functionMapper) throws JasperException { try { Method method = getWriteMethod(bean.getClass(), prop); - method.invoke(bean, PageContextImpl.proprietaryEvaluate(expression, - method.getParameterTypes()[0], pageContext, functionMapper)); - } catch (Exception ex) { - Throwable thr = ExceptionUtils.unwrapInvocationTargetException(ex); + method.invoke(bean, PageContextImpl.proprietaryEvaluate(expression, method.getParameterTypes()[0], + pageContext, functionMapper)); + } catch (Exception e) { + Throwable thr = ExceptionUtils.unwrapInvocationTargetException(e); ExceptionUtils.handleThrowable(thr); - throw new JasperException(ex); + throw new JasperException(e); } } @@ -599,10 +597,10 @@ try { Method method = getWriteMethod(bean.getClass(), prop); method.invoke(bean, value); - } catch (Exception ex) { - Throwable thr = ExceptionUtils.unwrapInvocationTargetException(ex); + } catch (Exception e) { + Throwable thr = ExceptionUtils.unwrapInvocationTargetException(e); ExceptionUtils.handleThrowable(thr); - throw new JasperException(ex); + throw new JasperException(e); } } @@ -610,10 +608,10 @@ try { Method method = getWriteMethod(bean.getClass(), prop); method.invoke(bean, Integer.valueOf(value)); - } catch (Exception ex) { - Throwable thr = ExceptionUtils.unwrapInvocationTargetException(ex); + } catch (Exception e) { + Throwable thr = ExceptionUtils.unwrapInvocationTargetException(e); ExceptionUtils.handleThrowable(thr); - throw new JasperException(ex); + throw new JasperException(e); } } @@ -621,10 +619,10 @@ try { Method method = getWriteMethod(bean.getClass(), prop); method.invoke(bean, Short.valueOf(value)); - } catch (Exception ex) { - Throwable thr = ExceptionUtils.unwrapInvocationTargetException(ex); + } catch (Exception e) { + Throwable thr = ExceptionUtils.unwrapInvocationTargetException(e); ExceptionUtils.handleThrowable(thr); - throw new JasperException(ex); + throw new JasperException(e); } } @@ -632,10 +630,10 @@ try { Method method = getWriteMethod(bean.getClass(), prop); method.invoke(bean, Long.valueOf(value)); - } catch (Exception ex) { - Throwable thr = ExceptionUtils.unwrapInvocationTargetException(ex); + } catch (Exception e) { + Throwable thr = ExceptionUtils.unwrapInvocationTargetException(e); ExceptionUtils.handleThrowable(thr); - throw new JasperException(ex); + throw new JasperException(e); } } @@ -643,10 +641,10 @@ try { Method method = getWriteMethod(bean.getClass(), prop); method.invoke(bean, Double.valueOf(value)); - } catch (Exception ex) { - Throwable thr = ExceptionUtils.unwrapInvocationTargetException(ex); + } catch (Exception e) { + Throwable thr = ExceptionUtils.unwrapInvocationTargetException(e); ExceptionUtils.handleThrowable(thr); - throw new JasperException(ex); + throw new JasperException(e); } } @@ -654,10 +652,10 @@ try { Method method = getWriteMethod(bean.getClass(), prop); method.invoke(bean, Float.valueOf(value)); - } catch (Exception ex) { - Throwable thr = ExceptionUtils.unwrapInvocationTargetException(ex); + } catch (Exception e) { + Throwable thr = ExceptionUtils.unwrapInvocationTargetException(e); ExceptionUtils.handleThrowable(thr); - throw new JasperException(ex); + throw new JasperException(e); } } @@ -665,10 +663,10 @@ try { Method method = getWriteMethod(bean.getClass(), prop); method.invoke(bean, Character.valueOf(value)); - } catch (Exception ex) { - Throwable thr = ExceptionUtils.unwrapInvocationTargetException(ex); + } catch (Exception e) { + Throwable thr = ExceptionUtils.unwrapInvocationTargetException(e); ExceptionUtils.handleThrowable(thr); - throw new JasperException(ex); + throw new JasperException(e); } } @@ -676,10 +674,10 @@ try { Method method = getWriteMethod(bean.getClass(), prop); method.invoke(bean, Byte.valueOf(value)); - } catch (Exception ex) { - Throwable thr = ExceptionUtils.unwrapInvocationTargetException(ex); + } catch (Exception e) { + Throwable thr = ExceptionUtils.unwrapInvocationTargetException(e); ExceptionUtils.handleThrowable(thr); - throw new JasperException(ex); + throw new JasperException(e); } } @@ -687,10 +685,10 @@ try { Method method = getWriteMethod(bean.getClass(), prop); method.invoke(bean, Boolean.valueOf(value)); - } catch (Exception ex) { - Throwable thr = ExceptionUtils.unwrapInvocationTargetException(ex); + } catch (Exception e) { + Throwable thr = ExceptionUtils.unwrapInvocationTargetException(e); ExceptionUtils.handleThrowable(thr); - throw new JasperException(ex); + throw new JasperException(e); } } @@ -732,8 +730,8 @@ break; } } - } catch (Exception ex) { - throw new JasperException(ex); + } catch (Exception e) { + throw new JasperException(e); } } if (result == null) { @@ -770,8 +768,8 @@ break; } } - } catch (Exception ex) { - throw new JasperException(ex); + } catch (Exception e) { + throw new JasperException(e); } } if (result == null) { @@ -794,12 +792,12 @@ PropertyEditor pe = (PropertyEditor) propertyEditorClass.getConstructor().newInstance(); pe.setAsText(attrValue); return pe.getValue(); - } catch (Exception ex) { + } catch (Exception e) { if (attrValue.isEmpty()) { return null; } else { throw new JasperException(Localizer.getMessage("jsp.error.beans.property.conversion", attrValue, - attrClass.getName(), attrName, ex.getMessage())); + attrClass.getName(), attrName, e.getMessage())); } } } @@ -964,4 +962,30 @@ } } + + /** + * This method parallels the logic of {@code SetSupport.doEndTag()}. + * + * @param pageContext pageContext + * @param var name of the variable + * @param value value to store + * @param scope scope + */ + public static void nonstandardSetTag(jakarta.servlet.jsp.PageContext pageContext, String var, Object value, + int scope) { + if (value == null) { + // matches SetTag and removes the key from the specified scope + pageContext.removeAttribute(var, scope); + } else { + if (scope == PageContext.PAGE_SCOPE) { + // matches SetTag and cleans up the VariableMapper + VariableMapper vm = pageContext.getELContext().getVariableMapper(); + if (vm != null) { + vm.setVariable(var, null); + } + } + // does the all-important set of the correct scope + pageContext.setAttribute(var, value, scope); + } + } } diff -Nru tomcat10-10.1.40/java/org/apache/jasper/runtime/JspWriterImpl.java tomcat10-10.1.52/java/org/apache/jasper/runtime/JspWriterImpl.java --- tomcat10-10.1.40/java/org/apache/jasper/runtime/JspWriterImpl.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/jasper/runtime/JspWriterImpl.java 2026-01-23 19:33:36.000000000 +0000 @@ -27,11 +27,9 @@ import org.apache.jasper.compiler.Localizer; /** - * Write text to a character-output stream, buffering characters to provide efficient writing of single - * characters, arrays, and strings. Provide support for discarding the output that has been buffered. This needs - * revisiting when the buffering problems in the JSP spec are fixed -akv - * - * @author Anil K. Vijendran + * Write text to a character-output stream, buffering characters to provide efficient writing of single characters, + * arrays, and strings. Provide support for discarding the output that has been buffered. This needs revisiting when the + * buffering problems in the JSP spec are fixed -akv. */ public class JspWriterImpl extends JspWriter { @@ -54,7 +52,7 @@ * @param autoFlush true to automatically flush on buffer full, false to throw an overflow * exception in that case * - * @exception IllegalArgumentException If sz is <= 0 + * @exception IllegalArgumentException If sz is < 0 */ public JspWriterImpl(ServletResponse response, int sz, boolean autoFlush) { super(sz, autoFlush); diff -Nru tomcat10-10.1.40/java/org/apache/jasper/runtime/PageContextImpl.java tomcat10-10.1.52/java/org/apache/jasper/runtime/PageContextImpl.java --- tomcat10-10.1.40/java/org/apache/jasper/runtime/PageContextImpl.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/jasper/runtime/PageContextImpl.java 2026-01-23 19:33:36.000000000 +0000 @@ -53,14 +53,6 @@ /** * Implementation of the PageContext class from the JSP spec. Also doubles as a VariableResolver for the EL. - * - * @author Anil K. Vijendran - * @author Larry Cable - * @author Hans Bergsten - * @author Pierre Delisle - * @author Mark Roth - * @author Jan Luehe - * @author Jacob Hookom */ public class PageContextImpl extends PageContext { @@ -172,8 +164,8 @@ out = baseOut; try { ((JspWriterImpl) out).flushBuffer(); - } catch (IOException ex) { - throw new IllegalStateException(Localizer.getMessage("jsp.error.flush"), ex); + } catch (IOException ioe) { + throw new IllegalStateException(Localizer.getMessage("jsp.error.flush"), ioe); } finally { servlet = null; config = null; @@ -319,7 +311,7 @@ if (session.getAttribute(name) != null) { return SESSION_SCOPE; } - } catch (IllegalStateException ise) { + } catch (IllegalStateException ignore) { // Session has been invalidated. // Ignore and fall through to application scope. } @@ -351,7 +343,7 @@ if (session != null) { try { o = session.getAttribute(name); - } catch (IllegalStateException ise) { + } catch (IllegalStateException ignore) { // Session has been invalidated. // Ignore and fall through to application scope. } @@ -398,7 +390,7 @@ if (session != null) { try { removeAttribute(name, SESSION_SCOPE); - } catch (IllegalStateException ise) { + } catch (IllegalStateException ignore) { // Session has been invalidated. // Ignore and fall throw to application scope. } @@ -497,8 +489,8 @@ try { out.clear(); baseOut.clear(); - } catch (IOException ex) { - throw new IllegalStateException(Localizer.getMessage("jsp.error.attempt_to_clear_flushed_buffer"), ex); + } catch (IOException ioe) { + throw new IllegalStateException(Localizer.getMessage("jsp.error.attempt_to_clear_flushed_buffer"), ioe); } // Make sure that the response object is not the wrapper for include diff -Nru tomcat10-10.1.40/java/org/apache/jasper/runtime/ProtectedFunctionMapper.java tomcat10-10.1.52/java/org/apache/jasper/runtime/ProtectedFunctionMapper.java --- tomcat10-10.1.40/java/org/apache/jasper/runtime/ProtectedFunctionMapper.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/jasper/runtime/ProtectedFunctionMapper.java 2026-01-23 19:33:36.000000000 +0000 @@ -24,9 +24,6 @@ /** * Maps EL functions to their Java method counterparts. Keeps the actual Method objects protected so that JSP pages * can't indirectly do reflection. - * - * @author Mark Roth - * @author Kin-man Chung */ @SuppressWarnings("deprecation") // Have to support old JSP EL API public final class ProtectedFunctionMapper extends jakarta.el.FunctionMapper implements FunctionMapper { diff -Nru tomcat10-10.1.40/java/org/apache/jasper/runtime/ServletResponseWrapperInclude.java tomcat10-10.1.52/java/org/apache/jasper/runtime/ServletResponseWrapperInclude.java --- tomcat10-10.1.40/java/org/apache/jasper/runtime/ServletResponseWrapperInclude.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/jasper/runtime/ServletResponseWrapperInclude.java 2026-01-23 19:33:36.000000000 +0000 @@ -28,10 +28,7 @@ /** * ServletResponseWrapper used by the JSP 'include' action. This wrapper response object is passed to * RequestDispatcher.include(), so that the output of the included resource is appended to that of the including page. - * - * @author Pierre Delisle */ - public class ServletResponseWrapperInclude extends HttpServletResponseWrapper { /** diff -Nru tomcat10-10.1.40/java/org/apache/jasper/runtime/TagHandlerPool.java tomcat10-10.1.52/java/org/apache/jasper/runtime/TagHandlerPool.java --- tomcat10-10.1.40/java/org/apache/jasper/runtime/TagHandlerPool.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/jasper/runtime/TagHandlerPool.java 2026-01-23 19:33:36.000000000 +0000 @@ -27,8 +27,6 @@ /** * Pool of tag handlers that can be reused. - * - * @author Jan Luehe */ public class TagHandlerPool { @@ -69,7 +67,7 @@ if (maxSizeS != null) { try { maxSize = Integer.parseInt(maxSizeS); - } catch (Exception ex) { + } catch (Exception e) { // Ignore } } diff -Nru tomcat10-10.1.40/java/org/apache/jasper/servlet/JasperLoader.java tomcat10-10.1.52/java/org/apache/jasper/servlet/JasperLoader.java --- tomcat10-10.1.40/java/org/apache/jasper/servlet/JasperLoader.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/jasper/servlet/JasperLoader.java 2026-01-23 19:33:36.000000000 +0000 @@ -26,9 +26,6 @@ /** * Class loader for loading servlet class files (corresponding to JSP files) and tag handler class files (corresponding * to tag files). - * - * @author Anil K. Vijendran - * @author Harish Prabandham */ public class JasperLoader extends URLClassLoader { @@ -133,7 +130,7 @@ if (url != null) { try { is = url.openStream(); - } catch (IOException e) { + } catch (IOException ignore) { // Ignore } } diff -Nru tomcat10-10.1.40/java/org/apache/jasper/servlet/JspCServletContext.java tomcat10-10.1.52/java/org/apache/jasper/servlet/JspCServletContext.java --- tomcat10-10.1.40/java/org/apache/jasper/servlet/JspCServletContext.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/jasper/servlet/JspCServletContext.java 2026-01-23 19:33:36.000000000 +0000 @@ -66,10 +66,7 @@ /** * Simple ServletContext implementation without HTTP-specific methods. - * - * @author Peter Rossbach (pr@webapp.de) */ - public class JspCServletContext implements ServletContext { @@ -154,8 +151,8 @@ if (!webXmlParser.parseWebXml(url, webXml, false)) { throw new JasperException(Localizer.getMessage("jspc.error.invalidWebXml")); } - } catch (IOException e) { - throw new JasperException(e); + } catch (IOException ioe) { + throw new JasperException(ioe); } // if the application is metadata-complete then we can skip fragment processing @@ -410,8 +407,8 @@ } } } - } catch (IOException e) { - log(e.getMessage(), e); + } catch (IOException ioe) { + log(ioe.getMessage(), ioe); } } } diff -Nru tomcat10-10.1.40/java/org/apache/jasper/servlet/JspServlet.java tomcat10-10.1.52/java/org/apache/jasper/servlet/JspServlet.java --- tomcat10-10.1.40/java/org/apache/jasper/servlet/JspServlet.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/jasper/servlet/JspServlet.java 2026-01-23 19:33:36.000000000 +0000 @@ -45,16 +45,9 @@ import org.apache.tomcat.util.security.Escape; /** - * The Jasper JSP engine. The servlet container is responsible for providing a URLClassLoader for the web - * application context Jasper is being used in. Jasper will try to get the Tomcat ServletContext attribute for its - * ServletContext class loader, if that fails, it uses the parent class loader. In either case, it must be a - * URLClassLoader. - * - * @author Anil K. Vijendran - * @author Harish Prabandham - * @author Remy Maucherat - * @author Kin-man Chung - * @author Glenn Nielsen + * The Jasper JSP engine. The servlet container is responsible for providing a URLClassLoader for the web application + * context Jasper is being used in. Jasper will try to get the Tomcat ServletContext attribute for its ServletContext + * class loader, if that fails, it uses the parent class loader. In either case, it must be a URLClassLoader. */ public class JspServlet extends HttpServlet implements PeriodicEventListener { @@ -95,8 +88,8 @@ Constructor ctor = engineOptionsClass.getConstructor(ctorSig); Object[] args = { config, context }; options = (Options) ctor.newInstance(args); - } catch (Throwable e) { - Throwable throwable = ExceptionUtils.unwrapInvocationTargetException(e); + } catch (Throwable t) { + Throwable throwable = ExceptionUtils.unwrapInvocationTargetException(t); ExceptionUtils.handleThrowable(throwable); // Need to localize this. log.warn(Localizer.getMessage("jsp.warning.engineOptionsClass", engineOptionsName), throwable); @@ -126,8 +119,8 @@ } else { serviceJspFile(null, null, jspFile, true); } - } catch (IOException e) { - throw new ServletException(Localizer.getMessage("jsp.error.precompilation", jspFile), e); + } catch (IOException ioe) { + throw new ServletException(Localizer.getMessage("jsp.error.precompilation", jspFile), ioe); } catch (PrivilegedActionException e) { Throwable t = e.getCause(); if (t instanceof ServletException) { @@ -308,9 +301,9 @@ serviceJspFile(request, response, jspUri, precompile); } catch (RuntimeException | IOException | ServletException e) { throw e; - } catch (Throwable e) { - ExceptionUtils.handleThrowable(e); - throw new ServletException(e); + } catch (Throwable t) { + ExceptionUtils.handleThrowable(t); + throw new ServletException(t); } } diff -Nru tomcat10-10.1.40/java/org/apache/jasper/servlet/JspServletWrapper.java tomcat10-10.1.52/java/org/apache/jasper/servlet/JspServletWrapper.java --- tomcat10-10.1.40/java/org/apache/jasper/servlet/JspServletWrapper.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/jasper/servlet/JspServletWrapper.java 2026-01-23 19:33:36.000000000 +0000 @@ -49,17 +49,9 @@ import org.apache.tomcat.Jar; /** - * The Jasper JSP engine. The servlet container is responsible for providing a URLClassLoader for the web - * application context Jasper is being used in. Jasper will try to get the Tomcat ServletContext attribute for its - * ServletContext class loader, if that fails, it uses the parent class loader. In either case, it must be a - * URLClassLoader. - * - * @author Anil K. Vijendran - * @author Harish Prabandham - * @author Remy Maucherat - * @author Kin-man Chung - * @author Glenn Nielsen - * @author Tim Fennell + * The Jasper JSP engine. The servlet container is responsible for providing a URLClassLoader for the web application + * context Jasper is being used in. Jasper will try to get the Tomcat ServletContext attribute for its ServletContext + * class loader, if that fails, it uses the parent class loader. In either case, it must be a URLClassLoader. */ public class JspServletWrapper { @@ -402,11 +394,11 @@ throw handleJspException(ex); } throw ex; - } catch (Exception ex) { + } catch (Exception e) { if (options.getDevelopment()) { - throw handleJspException(ex); + throw handleJspException(e); } - throw new JasperException(ex); + throw new JasperException(e); } try { @@ -454,16 +446,16 @@ throw handleJspException(ex); } throw ex; - } catch (IOException ex) { + } catch (IOException ioe) { if (options.getDevelopment()) { - throw new IOException(handleJspException(ex).getMessage(), ex); + throw new IOException(handleJspException(ioe).getMessage(), ioe); } - throw ex; - } catch (Exception ex) { + throw ioe; + } catch (Exception e) { if (options.getDevelopment()) { - throw handleJspException(ex); + throw handleJspException(e); } - throw new JasperException(ex); + throw new JasperException(e); } } @@ -513,7 +505,8 @@ * Attempts to construct a JasperException that contains helpful information about what went wrong. Uses the JSP * compiler system to translate the line number in the generated servlet that originated the exception to a line * number in the JSP. Then constructs an exception containing that information, and a snippet of the JSP to help - * debugging. Please see BZ 37062 for more details. + * debugging. Please see BZ 37062 for more + * details. *

          * * @param ex the exception that was the cause of the problem. @@ -523,8 +516,12 @@ protected JasperException handleJspException(Exception ex) { try { Throwable realException = ex; + // Unwrap Servlet exception once if (ex instanceof ServletException) { - realException = ((ServletException) ex).getRootCause(); + Throwable rootCause = ((ServletException) ex).getRootCause(); + if (rootCause != null) { + realException = rootCause; + } } // Find the first stack frame that represents code generated by @@ -577,7 +574,7 @@ return new JasperException( Localizer.getMessage("jsp.exception", detail.getJspFileName(), "" + source.getLineNumber()), ex); - } catch (Exception je) { + } catch (Exception e) { // If anything goes wrong, just revert to the original behaviour if (ex instanceof JasperException) { return (JasperException) ex; diff -Nru tomcat10-10.1.40/java/org/apache/jasper/tagplugins/jstl/core/Import.java tomcat10-10.1.52/java/org/apache/jasper/tagplugins/jstl/core/Import.java --- tomcat10-10.1.40/java/org/apache/jasper/tagplugins/jstl/core/Import.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/jasper/tagplugins/jstl/core/Import.java 2026-01-23 19:33:36.000000000 +0000 @@ -158,7 +158,7 @@ ctxt.generateJavaSource(" try{"); ctxt.generateJavaSource(" " + tempReaderName + " = new java.io.InputStreamReader(" + inputStreamName + ", " + charSetName + ");"); - ctxt.generateJavaSource(" }catch(Exception ex){"); + ctxt.generateJavaSource(" }catch(Exception e){"); ctxt.generateJavaSource(" " + tempReaderName + " = new java.io.InputStreamReader(" + inputStreamName + ", org.apache.jasper.tagplugins.jstl.Util.DEFAULT_ENCODING);"); ctxt.generateJavaSource(" }"); @@ -306,8 +306,7 @@ ctxt.generateJavaSource(" try{"); ctxt.generateJavaSource(" " + tempReaderName + " = new java.io.InputStreamReader(" + inputStreamName + "," + charSetName + ");"); - ctxt.generateJavaSource(" }catch(Exception ex){"); - // ctxt.generateJavaSource(" throw new JspTagException(ex.toString());"); + ctxt.generateJavaSource(" }catch(Exception e){"); ctxt.generateJavaSource(" " + tempReaderName + " = new java.io.InputStreamReader(" + inputStreamName + ",org.apache.jasper.tagplugins.jstl.Util.DEFAULT_ENCODING);"); ctxt.generateJavaSource(" }"); diff -Nru tomcat10-10.1.40/java/org/apache/juli/AsyncFileHandler.java tomcat10-10.1.52/java/org/apache/juli/AsyncFileHandler.java --- tomcat10-10.1.40/java/org/apache/juli/AsyncFileHandler.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/juli/AsyncFileHandler.java 2026-01-23 19:33:36.000000000 +0000 @@ -55,8 +55,8 @@ public static final int MAX_RECORDS = Integer .parseInt(System.getProperty("org.apache.juli.AsyncMaxRecordCount", Integer.toString(DEFAULT_MAX_RECORDS))); - private static final LoggerExecutorService LOGGER_SERVICE = new LoggerExecutorService(OVERFLOW_DROP_TYPE, - MAX_RECORDS); + private static final LoggerExecutorService LOGGER_SERVICE = + new LoggerExecutorService(OVERFLOW_DROP_TYPE, MAX_RECORDS); private final Object closeLock = new Object(); protected volatile boolean closed = false; @@ -121,8 +121,8 @@ record.getSourceMethodName(); loggerService.execute(() -> { /* - * During Tomcat shutdown, the Handlers are closed before the executor queue is flushed therefore the - * closed flag is ignored if the executor is shutting down. + * During Tomcat shutdown, the Handlers are closed before the executor queue is flushed therefore the closed + * flag is ignored if the executor is shutting down. */ if (!closed || loggerService.isTerminating()) { publishInternal(record); diff -Nru tomcat10-10.1.40/java/org/apache/juli/ClassLoaderLogManager.java tomcat10-10.1.52/java/org/apache/juli/ClassLoaderLogManager.java --- tomcat10-10.1.40/java/org/apache/juli/ClassLoaderLogManager.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/juli/ClassLoaderLogManager.java 2026-01-23 19:33:36.000000000 +0000 @@ -83,7 +83,7 @@ * Map containing the classloader information, keyed per classloader. A weak hashmap is used to ensure no * classloader reference is leaked from application redeployment. */ - protected final Map classLoaderLoggers = new WeakHashMap<>(); // Guarded by this + protected final Map classLoaderLoggers = new WeakHashMap<>(); // Guarded by this /** @@ -352,7 +352,7 @@ for (Handler handler : clLogInfo.handlers.values()) { try { handler.close(); - } catch (Exception e) { + } catch (Exception ignore) { // Ignore } } @@ -381,7 +381,7 @@ AccessController.doPrivileged((PrivilegedAction) () -> { try { readConfiguration(classLoaderParam); - } catch (IOException e) { + } catch (IOException ignore) { // Ignore } return null; @@ -450,9 +450,9 @@ if (configFileStr != null) { try { is = new FileInputStream(replace(configFileStr)); - } catch (IOException e) { + } catch (IOException ioe) { System.err.println("Configuration error"); - e.printStackTrace(); + ioe.printStackTrace(); } } // Try the default JVM configuration @@ -460,9 +460,9 @@ File defaultFile = new File(new File(System.getProperty("java.home"), "conf"), "logging.properties"); try { is = new FileInputStream(defaultFile); - } catch (IOException e) { + } catch (IOException ioe) { System.err.println("Configuration error"); - e.printStackTrace(); + ioe.printStackTrace(); } } } @@ -515,10 +515,10 @@ try (is) { info.props.load(is); - } catch (IOException e) { + } catch (IOException ioe) { // Report error System.err.println("Configuration error"); - e.printStackTrace(); + ioe.printStackTrace(); } // Ignore @@ -663,7 +663,7 @@ protected static final class LogNode { Logger logger; - final Map children = new HashMap<>(); + final Map children = new HashMap<>(); final LogNode parent; @@ -729,8 +729,8 @@ protected static final class ClassLoaderLogInfo { final LogNode rootNode; - final Map loggers = new ConcurrentHashMap<>(); - final Map handlers = new HashMap<>(); + final Map loggers = new ConcurrentHashMap<>(); + final Map handlers = new HashMap<>(); final Properties props = new Properties(); ClassLoaderLogInfo(final LogNode rootNode) { diff -Nru tomcat10-10.1.40/java/org/apache/juli/FileHandler.java tomcat10-10.1.52/java/org/apache/juli/FileHandler.java --- tomcat10-10.1.40/java/org/apache/juli/FileHandler.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/juli/FileHandler.java 2026-01-23 19:33:36.000000000 +0000 @@ -86,8 +86,8 @@ public static final int DEFAULT_BUFFER_SIZE = -1; - private static final ExecutorService DELETE_FILES_SERVICE = Executors - .newSingleThreadExecutor(new ThreadFactory("FileHandlerLogFilesCleaner-")); + private static final ExecutorService DELETE_FILES_SERVICE = + Executors.newSingleThreadExecutor(new ThreadFactory("FileHandlerLogFilesCleaner-")); // ------------------------------------------------------------ Constructor @@ -366,7 +366,7 @@ if (encoding != null && !encoding.isEmpty()) { try { setEncoding(encoding); - } catch (UnsupportedEncodingException ex) { + } catch (UnsupportedEncodingException ignore) { // Ignore } } @@ -379,7 +379,7 @@ if (filterName != null) { try { setFilter((Filter) cl.loadClass(filterName).getConstructor().newInstance()); - } catch (Exception e) { + } catch (Exception ignore) { // Ignore } } @@ -389,7 +389,7 @@ if (formatterName != null) { try { setFormatter((Formatter) cl.loadClass(formatterName).getConstructor().newInstance()); - } catch (Exception e) { + } catch (Exception ignore) { // Ignore and fallback to defaults setFormatter(new OneLineFormatter()); } @@ -454,14 +454,14 @@ if (fos != null) { try { fos.close(); - } catch (IOException e1) { + } catch (IOException ignore) { // Ignore } } if (os != null) { try { os.close(); - } catch (IOException e1) { + } catch (IOException ignore) { // Ignore } } @@ -479,7 +479,7 @@ for (Path file : files) { Files.delete(file); } - } catch (IOException e) { + } catch (IOException ioe) { reportError("Unable to delete log files older than [" + maxDays + "] days", null, ErrorManager.GENERIC_FAILURE); } @@ -495,8 +495,8 @@ try { LocalDate dateFromFile = LocalDate.from(DateTimeFormatter.ISO_LOCAL_DATE.parse(date)); result = dateFromFile.isBefore(maxDaysOffset); - } catch (DateTimeException e) { - // no-op + } catch (DateTimeException ignore) { + // Unable to determine date from path. File will not be included. } } return result; diff -Nru tomcat10-10.1.40/java/org/apache/juli/JdkLoggerFormatter.java tomcat10-10.1.52/java/org/apache/juli/JdkLoggerFormatter.java --- tomcat10-10.1.40/java/org/apache/juli/JdkLoggerFormatter.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/juli/JdkLoggerFormatter.java 2026-01-23 19:33:36.000000000 +0000 @@ -31,8 +31,6 @@ * * * Example: 1130122891846 Http11BaseProtocol I Initializing Coyote HTTP/1.1 on http-8800 - * - * @author Costin Manolache */ public class JdkLoggerFormatter extends Formatter { @@ -96,7 +94,7 @@ buf.append(" ".repeat(Math.max(0, 8 - buf.length()))); // Append the message - buf.append(message); + buf.append(LogUtil.escape(message)); // Append stack trace if not null if (t != null) { @@ -106,7 +104,7 @@ java.io.PrintWriter pw = new java.io.PrintWriter(sw); t.printStackTrace(pw); pw.close(); - buf.append(sw); + buf.append(LogUtil.escape(sw.toString())); } buf.append(System.lineSeparator()); diff -Nru tomcat10-10.1.40/java/org/apache/juli/JsonFormatter.java tomcat10-10.1.52/java/org/apache/juli/JsonFormatter.java --- tomcat10-10.1.40/java/org/apache/juli/JsonFormatter.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/juli/JsonFormatter.java 2026-01-23 19:33:36.000000000 +0000 @@ -20,9 +20,8 @@ import java.util.logging.LogRecord; /** - * Provides the same information as the one line format but using JSON formatting. - * All the information of the LogRecord is included as a one line JSON document, - * including the full stack trace of the associated exception if any. + * Provides the same information as the one line format but using JSON formatting. All the information of the LogRecord + * is included as a one line JSON document, including the full stack trace of the associated exception if any. *

          * The LogRecord is mapped as attributes: *

            @@ -32,9 +31,9 @@ *
          • class: the class from which the log originated
          • *
          • method: the method from which the log originated
          • *
          • message: the log message
          • - *
          • throwable: the full stack trace from an exception, if present, represented as an array of string - * (the message first, then one string per stack trace element prefixed by a whitespace, - * then moving on to the cause exception if any)
          • + *
          • throwable: the full stack trace from an exception, if present, represented as an array of string (the message + * first, then one string per stack trace element prefixed by a whitespace, then moving on to the cause exception if + * any)
          • *
          */ public class JsonFormatter extends OneLineFormatter { @@ -66,14 +65,7 @@ // Thread sb.append("\"thread\": \""); - final String threadName = Thread.currentThread().getName(); - if (threadName != null && threadName.startsWith(AsyncFileHandler.THREAD_PREFIX)) { - // If using the async handler can't get the thread name from the - // current thread. - sb.append(getThreadName(record.getThreadID())); - } else { - sb.append(threadName); - } + sb.append(resolveThreadName(record)); sb.append("\", "); // Source @@ -121,15 +113,16 @@ /** - * Provides escaping of values so they can be included in a JSON document. - * Escaping is based on the definition of JSON found in - * RFC 8259. + * Provides escaping of values so they can be included in a JSON document. Escaping is based on the definition of + * JSON found in RFC 8259. */ public static class JSONFilter { /** * Escape the given string. + * * @param input the string + * * @return the escaped string */ public static String escape(String input) { @@ -138,16 +131,17 @@ /** * Escape the given char sequence. - * @param input the char sequence - * @param off the offset on which escaping will start + * + * @param input the char sequence + * @param off the offset on which escaping will start * @param length the length which should be escaped + * * @return the escaped char sequence corresponding to the specified range */ public static CharSequence escape(CharSequence input, int off, int length) { /* - * While any character MAY be escaped, only U+0000 to U+001F (control - * characters), U+0022 (quotation mark) and U+005C (reverse solidus) - * MUST be escaped. + * While any character MAY be escaped, only U+0000 to U+001F (control characters), U+0022 (quotation mark) + * and U+005C (reverse solidus) MUST be escaped. */ StringBuilder escaped = null; int lastUnescapedStart = off; diff -Nru tomcat10-10.1.40/java/org/apache/juli/LogUtil.java tomcat10-10.1.52/java/org/apache/juli/LogUtil.java --- tomcat10-10.1.40/java/org/apache/juli/LogUtil.java 1970-01-01 00:00:00.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/juli/LogUtil.java 2026-01-23 19:33:36.000000000 +0000 @@ -0,0 +1,64 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.juli; + +public class LogUtil { + + private LogUtil() { + // Utility class. Hide default constructor + } + + + /** + * Escape a string so it can be displayed in a readable format. Characters that may not be printable in some/all of + * the contexts in which log messages will be viewed will be escaped using Java \\uNNNN escaping. + *

          + * All control characters are escaped apart from horizontal tab (\\u0009), new line (\\u000a) and carriage return + * (\\u000d). + * + * @param input The string to escape + * + * @return The escaped form of the input string + */ + @SuppressWarnings("null") // sb is not null when used + public static String escape(final String input) { + final int len = input.length(); + int i = 0; + int lastControl = -1; + StringBuilder sb = null; + while (i < len) { + char c = input.charAt(i); + if (Character.getType(c) == Character.CONTROL) { + if (!(c == '\t' || c == '\n' || c == '\r')) { + if (lastControl == -1) { + sb = new StringBuilder(len + 20); + } + sb.append(input.substring(lastControl + 1, i)); + sb.append(String.format("\\u%1$04x", Integer.valueOf(c))); + lastControl = i; + } + } + i++; + } + if (lastControl == -1) { + return input; + } else { + sb.append(input.substring(lastControl + 1, len)); + return sb.toString(); + } + } +} diff -Nru tomcat10-10.1.40/java/org/apache/juli/OneLineFormatter.java tomcat10-10.1.52/java/org/apache/juli/OneLineFormatter.java --- tomcat10-10.1.40/java/org/apache/juli/OneLineFormatter.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/juli/OneLineFormatter.java 2026-01-23 19:33:36.000000000 +0000 @@ -42,8 +42,8 @@ private static final Object threadMxBeanLock = new Object(); private static volatile ThreadMXBean threadMxBean = null; private static final int THREAD_NAME_CACHE_SIZE = 10000; - private static final ThreadLocal threadNameCache = ThreadLocal - .withInitial(() -> new ThreadNameCache(THREAD_NAME_CACHE_SIZE)); + private static final ThreadLocal threadNameCache = + ThreadLocal.withInitial(() -> new ThreadNameCache(THREAD_NAME_CACHE_SIZE)); /* Timestamp format */ private static final String DEFAULT_TIME_FORMAT = "dd-MMM-yyyy HH:mm:ss.SSS"; @@ -51,12 +51,12 @@ /** * The size of our global date format cache */ - private static final int globalCacheSize = 30; + private static final int GLOBAL_CACHE_SIZE = 30; /** * The size of our thread local date format cache */ - private static final int localCacheSize = 5; + private static final int LOCAL_CACHE_SIZE = 5; /** * Thread local date format cache. @@ -100,9 +100,9 @@ cachedTimeFormat = timeFormat; } - final DateFormatCache globalDateCache = new DateFormatCache(globalCacheSize, cachedTimeFormat, null); - localDateCache = ThreadLocal - .withInitial(() -> new DateFormatCache(localCacheSize, cachedTimeFormat, globalDateCache)); + final DateFormatCache globalDateCache = new DateFormatCache(GLOBAL_CACHE_SIZE, cachedTimeFormat, null); + localDateCache = + ThreadLocal.withInitial(() -> new DateFormatCache(LOCAL_CACHE_SIZE, cachedTimeFormat, globalDateCache)); } @@ -130,14 +130,7 @@ // Thread sb.append(' '); sb.append('['); - final String threadName = Thread.currentThread().getName(); - if (threadName != null && threadName.startsWith(AsyncFileHandler.THREAD_PREFIX)) { - // If using the async handler can't get the thread name from the - // current thread. - sb.append(getThreadName(record.getThreadID())); - } else { - sb.append(threadName); - } + sb.append(resolveThreadName(record)); sb.append(']'); // Source @@ -148,7 +141,7 @@ // Message sb.append(' '); - sb.append(formatMessage(record)); + sb.append(LogUtil.escape(formatMessage(record))); // New line for next record sb.append(System.lineSeparator()); @@ -159,12 +152,23 @@ PrintWriter pw = new IndentingPrintWriter(sw); record.getThrown().printStackTrace(pw); pw.close(); - sb.append(sw.getBuffer()); + sb.append(LogUtil.escape(sw.toString())); } return sb.toString(); } + protected String resolveThreadName(LogRecord record) { + final String threadName = Thread.currentThread().getName(); + if (threadName != null && threadName.startsWith(AsyncFileHandler.THREAD_PREFIX)) { + // If using the async handler can't get the thread name from the + // current thread. + return getThreadName(record.getThreadID()); + } else { + return threadName; + } + } + protected void addTimestamp(StringBuilder buf, long timestamp) { String cachedTimeStamp = localDateCache.get().getFormat(timestamp); if (millisHandling == MillisHandling.NONE) { @@ -216,10 +220,11 @@ * resulting mess that follows. * * @param logRecordThreadId the thread id + * * @return the thread name */ protected static String getThreadName(int logRecordThreadId) { - Map cache = threadNameCache.get(); + Map cache = threadNameCache.get(); String result = cache.get(Integer.valueOf(logRecordThreadId)); if (result != null) { @@ -253,7 +258,7 @@ /* * This is an LRU cache. */ - private static class ThreadNameCache extends LinkedHashMap { + private static class ThreadNameCache extends LinkedHashMap { private static final long serialVersionUID = 1L; @@ -265,7 +270,7 @@ } @Override - protected boolean removeEldestEntry(Entry eldest) { + protected boolean removeEldestEntry(Entry eldest) { return (size() > cacheSize); } } @@ -290,6 +295,10 @@ private enum MillisHandling { - NONE, APPEND, REPLACE_S, REPLACE_SS, REPLACE_SSS, + NONE, + APPEND, + REPLACE_S, + REPLACE_SS, + REPLACE_SSS, } } diff -Nru tomcat10-10.1.40/java/org/apache/juli/VerbatimFormatter.java tomcat10-10.1.52/java/org/apache/juli/VerbatimFormatter.java --- tomcat10-10.1.40/java/org/apache/juli/VerbatimFormatter.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/juli/VerbatimFormatter.java 2026-01-23 19:33:36.000000000 +0000 @@ -20,9 +20,9 @@ import java.util.logging.LogRecord; /** - * Outputs just the log message with no additional elements. Stack traces are not logged. Log messages are separated - * by System.lineSeparator(). This is intended for use by access logs and the like that need complete - * control over the output format. + * Outputs just the log message with no additional elements and no escaping. Stack traces are not logged. Log messages + * are separated by System.lineSeparator(). This is intended for use by access logs and the like that need + * complete control over the output format. */ public class VerbatimFormatter extends Formatter { @@ -31,5 +31,4 @@ // Timestamp + New line for next record return record.getMessage() + System.lineSeparator(); } - } diff -Nru tomcat10-10.1.40/java/org/apache/juli/logging/Log.java tomcat10-10.1.52/java/org/apache/juli/logging/Log.java --- tomcat10-10.1.40/java/org/apache/juli/logging/Log.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/juli/logging/Log.java 2026-01-23 19:33:36.000000000 +0000 @@ -17,14 +17,11 @@ package org.apache.juli.logging; /** - *

          * A simple logging interface abstracting logging APIs. In order to be instantiated successfully by {@link LogFactory}, * classes that implement this interface must have a constructor that takes a single String parameter representing the * "name" of this Log. - *

          *

          * The six logging levels used by Log are (in order): - *

          *
            *
          1. trace (the least serious)
          2. *
          3. debug
          4. @@ -36,11 +33,9 @@ *

            * The mapping of these log levels to the concepts used by the underlying logging system is implementation dependent. * The implementation should ensure, though, that this ordering behaves as expected. - *

            *

            * Performance is often a logging concern. By examining the appropriate property, a component can avoid expensive * operations (producing information to be logged). - *

            *

            * For example, * if (log.isDebugEnabled()) { @@ -48,21 +43,12 @@ * log.debug(theResult); * } * - *

            *

            * Configuration of the underlying logging system will generally be done external to the Logging APIs, through whatever * mechanism is supported by that system. - *

            - * - * @author Scott Sanders - * @author Rod Waldhoff */ public interface Log { - - // ----------------------------------------------------- Logging Properties - - /** *

            * Is debug logging currently enabled? diff -Nru tomcat10-10.1.40/java/org/apache/juli/logging/LogConfigurationException.java tomcat10-10.1.52/java/org/apache/juli/logging/LogConfigurationException.java --- tomcat10-10.1.40/java/org/apache/juli/logging/LogConfigurationException.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/juli/logging/LogConfigurationException.java 2026-01-23 19:33:36.000000000 +0000 @@ -22,8 +22,6 @@ * An exception that is thrown only if a suitable LogFactory or Log instance cannot be created * by the corresponding factory methods. *

            - * - * @author Craig R. McClanahan */ public class LogConfigurationException extends RuntimeException { diff -Nru tomcat10-10.1.40/java/org/apache/juli/logging/LogFactory.java tomcat10-10.1.52/java/org/apache/juli/logging/LogFactory.java --- tomcat10-10.1.40/java/org/apache/juli/logging/LogFactory.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/juli/logging/LogFactory.java 2026-01-23 19:33:36.000000000 +0000 @@ -46,15 +46,9 @@ *

            * Factory for creating {@link Log} instances, with discovery and configuration features similar to that employed by * standard Java APIs such as JAXP. - *

            *

            * IMPLEMENTATION NOTE - This implementation is heavily based on the SAXParserFactory and * DocumentBuilderFactory implementations (corresponding to the JAXP pluggability APIs) found in Apache Xerces. - *

            - * - * @author Craig R. McClanahan - * @author Costin Manolache - * @author Richard A. Sitze */ @ServiceConsumer(value = Log.class) public class LogFactory { diff -Nru tomcat10-10.1.40/java/org/apache/naming/ContextAccessController.java tomcat10-10.1.52/java/org/apache/naming/ContextAccessController.java --- tomcat10-10.1.40/java/org/apache/naming/ContextAccessController.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/naming/ContextAccessController.java 2026-01-23 19:33:36.000000000 +0000 @@ -21,8 +21,6 @@ /** * Handles the access control on the JNDI contexts. - * - * @author Remy Maucherat */ public class ContextAccessController { @@ -45,15 +43,13 @@ /** * Set a security token for a Catalina context. Can be set only once. * - * @param name Name of the Catalina context + * @param name Name of the Catalina context * @param token Security token */ public static void setSecurityToken(Object name, Object token) { SecurityManager sm = System.getSecurityManager(); if (sm != null) { - sm.checkPermission(new RuntimePermission( - ContextAccessController.class.getName() - + ".setSecurityToken")); + sm.checkPermission(new RuntimePermission(ContextAccessController.class.getName() + ".setSecurityToken")); } if ((!securityTokens.containsKey(name)) && (token != null)) { securityTokens.put(name, token); @@ -64,7 +60,7 @@ /** * Remove a security token for a context. * - * @param name Name of the Catalina context + * @param name Name of the Catalina context * @param token Security token */ public static void unsetSecurityToken(Object name, Object token) { @@ -77,15 +73,13 @@ /** * Check a submitted security token. * - * @param name Name of the Catalina context + * @param name Name of the Catalina context * @param token Submitted security token * - * @return true if the submitted token is equal to the token - * in the repository or if no token is present in the repository. - * Otherwise, false + * @return true if the submitted token is equal to the token in the repository or if no token is + * present in the repository. Otherwise, false */ - public static boolean checkSecurityToken - (Object name, Object token) { + public static boolean checkSecurityToken(Object name, Object token) { Object refToken = securityTokens.get(name); return (refToken == null || refToken.equals(token)); } @@ -94,7 +88,7 @@ /** * Allow writing to a context. * - * @param name Name of the Catalina context + * @param name Name of the Catalina context * @param token Security token */ public static void setWritable(Object name, Object token) { diff -Nru tomcat10-10.1.40/java/org/apache/naming/ContextBindings.java tomcat10-10.1.52/java/org/apache/naming/ContextBindings.java --- tomcat10-10.1.40/java/org/apache/naming/ContextBindings.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/naming/ContextBindings.java 2026-01-23 19:33:36.000000000 +0000 @@ -29,12 +29,9 @@ *
          5. Calling thread with a NamingContext
          6. *
          7. Calling thread with object bound to the same naming context
          8. *
          9. Thread context class loader with a NamingContext
          10. - *
          11. Thread context class loader with object bound to the same - * NamingContext
          12. + *
          13. Thread context class loader with object bound to the same NamingContext
          14. *
        * The objects are typically Catalina Server or Context objects. - * - * @author Remy Maucherat */ public class ContextBindings { @@ -81,8 +78,8 @@ /** * Binds an object and a naming context. * - * @param obj Object to bind with naming context - * @param context Associated naming context instance + * @param obj Object to bind with naming context + * @param context Associated naming context instance */ public static void bindContext(Object obj, Context context) { bindContext(obj, context, null); @@ -92,9 +89,9 @@ /** * Binds an object and a naming context. * - * @param obj Object to bind with naming context - * @param context Associated naming context instance - * @param token Security token + * @param obj Object to bind with naming context + * @param context Associated naming context instance + * @param token Security token */ public static void bindContext(Object obj, Context context, Object token) { if (ContextAccessController.checkSecurityToken(obj, token)) { @@ -119,7 +116,7 @@ /** * Retrieve a naming context. * - * @param obj Object bound to the required naming context + * @param obj Object bound to the required naming context */ static Context getContext(Object obj) { return objectBindings.get(obj); @@ -132,15 +129,13 @@ * @param obj Object bound to the required naming context * @param token Security token * - * @throws NamingException If no naming context is bound to the provided - * object + * @throws NamingException If no naming context is bound to the provided object */ public static void bindThread(Object obj, Object token) throws NamingException { if (ContextAccessController.checkSecurityToken(obj, token)) { Context context = objectBindings.get(obj); if (context == null) { - throw new NamingException( - sm.getString("contextBindings.unknownContext", obj)); + throw new NamingException(sm.getString("contextBindings.unknownContext", obj)); } Thread currentThread = Thread.currentThread(); threadBindings.put(currentThread, context); @@ -169,28 +164,24 @@ * * @return The naming context bound to the current thread. * - * @throws NamingException If no naming context is bound to the current - * thread + * @throws NamingException If no naming context is bound to the current thread */ public static Context getThread() throws NamingException { Context context = threadBindings.get(Thread.currentThread()); if (context == null) { - throw new NamingException - (sm.getString("contextBindings.noContextBoundToThread")); + throw new NamingException(sm.getString("contextBindings.noContextBoundToThread")); } return context; } /** - * Retrieves the name of the object bound to the naming context that is also - * bound to the current thread. + * Retrieves the name of the object bound to the naming context that is also bound to the current thread. */ static String getThreadName() throws NamingException { Object obj = threadObjectBindings.get(Thread.currentThread()); if (obj == null) { - throw new NamingException - (sm.getString("contextBindings.noContextBoundToThread")); + throw new NamingException(sm.getString("contextBindings.noContextBoundToThread")); } return obj.toString(); } @@ -199,8 +190,7 @@ /** * Tests if current thread is bound to a naming context. * - * @return true if the current thread is bound to a naming - * context, otherwise false + * @return true if the current thread is bound to a naming context, otherwise false */ public static boolean isThreadBound() { return threadBindings.containsKey(Thread.currentThread()); @@ -210,20 +200,17 @@ /** * Binds a naming context to a class loader. * - * @param obj Object bound to the required naming context - * @param token Security token - * @param classLoader The class loader to bind to the naming context + * @param obj Object bound to the required naming context + * @param token Security token + * @param classLoader The class loader to bind to the naming context * - * @throws NamingException If no naming context is bound to the provided - * object + * @throws NamingException If no naming context is bound to the provided object */ - public static void bindClassLoader(Object obj, Object token, - ClassLoader classLoader) throws NamingException { + public static void bindClassLoader(Object obj, Object token, ClassLoader classLoader) throws NamingException { if (ContextAccessController.checkSecurityToken(obj, token)) { Context context = objectBindings.get(obj); if (context == null) { - throw new NamingException - (sm.getString("contextBindings.unknownContext", obj)); + throw new NamingException(sm.getString("contextBindings.unknownContext", obj)); } clBindings.put(classLoader, context); clObjectBindings.put(classLoader, obj); @@ -234,12 +221,11 @@ /** * Unbinds a naming context and a class loader. * - * @param obj Object bound to the required naming context - * @param token Security token - * @param classLoader The class loader bound to the naming context + * @param obj Object bound to the required naming context + * @param token Security token + * @param classLoader The class loader bound to the naming context */ - public static void unbindClassLoader(Object obj, Object token, - ClassLoader classLoader) { + public static void unbindClassLoader(Object obj, Object token, ClassLoader classLoader) { if (ContextAccessController.checkSecurityToken(obj, token)) { Object o = clObjectBindings.get(classLoader); if (o == null || !o.equals(obj)) { @@ -254,8 +240,7 @@ /** * Retrieves the naming context bound to a class loader. * - * @return the naming context bound to current class loader or one of its - * parents + * @return the naming context bound to current class loader or one of its parents * * @throws NamingException If no naming context was bound */ @@ -273,8 +258,8 @@ /** - * Retrieves the name of the object bound to the naming context that is also - * bound to the thread context class loader. + * Retrieves the name of the object bound to the naming context that is also bound to the thread context class + * loader. */ static String getClassLoaderName() throws NamingException { ClassLoader cl = Thread.currentThread().getContextClassLoader(); @@ -285,16 +270,15 @@ return obj.toString(); } } while ((cl = cl.getParent()) != null); - throw new NamingException (sm.getString("contextBindings.noContextBoundToCL")); + throw new NamingException(sm.getString("contextBindings.noContextBoundToCL")); } /** * Tests if the thread context class loader is bound to a context. * - * @return true if the thread context class loader or one of - * its parents is bound to a naming context, otherwise - * false + * @return true if the thread context class loader or one of its parents is bound to a naming context, + * otherwise false */ public static boolean isClassLoaderBound() { ClassLoader cl = Thread.currentThread().getContextClassLoader(); diff -Nru tomcat10-10.1.40/java/org/apache/naming/EjbRef.java tomcat10-10.1.52/java/org/apache/naming/EjbRef.java --- tomcat10-10.1.40/java/org/apache/naming/EjbRef.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/naming/EjbRef.java 2026-01-23 19:33:36.000000000 +0000 @@ -20,8 +20,6 @@ /** * Represents a reference address to an EJB. - * - * @author Remy Maucherat */ public class EjbRef extends AbstractRef { @@ -31,8 +29,7 @@ /** * Default factory for this reference. */ - public static final String DEFAULT_FACTORY = - org.apache.naming.factory.Constants.DEFAULT_EJB_FACTORY; + public static final String DEFAULT_FACTORY = org.apache.naming.factory.Constants.DEFAULT_EJB_FACTORY; /** @@ -57,9 +54,9 @@ * EJB Reference. * * @param ejbType EJB type - * @param home Home interface classname - * @param remote Remote interface classname - * @param link EJB link + * @param home Home interface classname + * @param remote Remote interface classname + * @param link EJB link */ public EjbRef(String ejbType, String home, String remote, String link) { this(ejbType, home, remote, link, null, null); @@ -69,16 +66,14 @@ /** * EJB Reference. * - * @param ejbType EJB type - * @param home Home interface classname - * @param remote Remote interface classname - * @param link EJB link - * @param factory The possibly null class name of the object's factory. - * @param factoryLocation The possibly null location from which to load - * the factory (e.g. URL) + * @param ejbType EJB type + * @param home Home interface classname + * @param remote Remote interface classname + * @param link EJB link + * @param factory The possibly null class name of the object's factory. + * @param factoryLocation The possibly null location from which to load the factory (e.g. URL) */ - public EjbRef(String ejbType, String home, String remote, String link, - String factory, String factoryLocation) { + public EjbRef(String ejbType, String home, String remote, String link, String factory, String factoryLocation) { super(home, factory, factoryLocation); StringRefAddr refAddr; if (ejbType != null) { diff -Nru tomcat10-10.1.40/java/org/apache/naming/HandlerRef.java tomcat10-10.1.52/java/org/apache/naming/HandlerRef.java --- tomcat10-10.1.40/java/org/apache/naming/HandlerRef.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/naming/HandlerRef.java 2026-01-23 19:33:36.000000000 +0000 @@ -20,8 +20,6 @@ /** * Represents a reference handler for a web service. - * - * @author Fabien Carrion */ public class HandlerRef extends AbstractRef { @@ -31,56 +29,55 @@ /** * Default factory for this reference. */ - public static final String DEFAULT_FACTORY = - org.apache.naming.factory.Constants.DEFAULT_HANDLER_FACTORY; + public static final String DEFAULT_FACTORY = org.apache.naming.factory.Constants.DEFAULT_HANDLER_FACTORY; /** * HandlerName address type. */ - public static final String HANDLER_NAME = "handlername"; + public static final String HANDLER_NAME = "handlername"; /** * Handler Classname address type. */ - public static final String HANDLER_CLASS = "handlerclass"; + public static final String HANDLER_CLASS = "handlerclass"; /** * Handler Classname address type. */ - public static final String HANDLER_LOCALPART = "handlerlocalpart"; + public static final String HANDLER_LOCALPART = "handlerlocalpart"; /** * Handler Classname address type. */ - public static final String HANDLER_NAMESPACE = "handlernamespace"; + public static final String HANDLER_NAMESPACE = "handlernamespace"; /** * Handler Classname address type. */ - public static final String HANDLER_PARAMNAME = "handlerparamname"; + public static final String HANDLER_PARAMNAME = "handlerparamname"; /** * Handler Classname address type. */ - public static final String HANDLER_PARAMVALUE = "handlerparamvalue"; + public static final String HANDLER_PARAMVALUE = "handlerparamvalue"; /** * Handler SoapRole address type. */ - public static final String HANDLER_SOAPROLE = "handlersoaprole"; + public static final String HANDLER_SOAPROLE = "handlersoaprole"; /** * Handler PortName address type. */ - public static final String HANDLER_PORTNAME = "handlerportname"; + public static final String HANDLER_PORTNAME = "handlerportname"; public HandlerRef(String refname, String handlerClass) { @@ -88,8 +85,7 @@ } - public HandlerRef(String refname, String handlerClass, - String factory, String factoryLocation) { + public HandlerRef(String refname, String handlerClass, String factory, String factoryLocation) { super(refname, factory, factoryLocation); StringRefAddr refAddr; if (refname != null) { diff -Nru tomcat10-10.1.40/java/org/apache/naming/LocalStrings.properties tomcat10-10.1.52/java/org/apache/naming/LocalStrings.properties --- tomcat10-10.1.40/java/org/apache/naming/LocalStrings.properties 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/naming/LocalStrings.properties 2026-01-23 19:33:36.000000000 +0000 @@ -21,8 +21,8 @@ contextBindings.unknownContext=Unknown context name : [{0}] namingContext.alreadyBound=Name [{0}] is already bound in this Context -namingContext.contextExpected=Name is not bound to a Context -namingContext.failResolvingReference=Unexpected exception resolving reference +namingContext.contextExpected=Name [{0}] is not bound to a Context +namingContext.failResolvingReference=Unexpected exception resolving reference with name [{0}] namingContext.invalidName=Name is not valid namingContext.nameNotBound=Name [{0}] is not bound in this Context. Unable to find [{1}]. namingContext.noAbsoluteName=Cannot generate an absolute name for this namespace diff -Nru tomcat10-10.1.40/java/org/apache/naming/LocalStrings_cs.properties tomcat10-10.1.52/java/org/apache/naming/LocalStrings_cs.properties --- tomcat10-10.1.40/java/org/apache/naming/LocalStrings_cs.properties 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/naming/LocalStrings_cs.properties 2026-01-23 19:33:36.000000000 +0000 @@ -16,4 +16,3 @@ # Do not edit this file directly. # To edit translations see: https://tomcat.apache.org/getinvolved.html#Translations -namingContext.contextExpected=Jméno není svázáno s kontextem diff -Nru tomcat10-10.1.40/java/org/apache/naming/LocalStrings_de.properties tomcat10-10.1.52/java/org/apache/naming/LocalStrings_de.properties --- tomcat10-10.1.40/java/org/apache/naming/LocalStrings_de.properties 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/naming/LocalStrings_de.properties 2026-01-23 19:33:36.000000000 +0000 @@ -18,7 +18,5 @@ contextBindings.unknownContext=Unbekannter Kontext-Name: [{0}] -namingContext.contextExpected=Ein Name ist nicht an den Context gebunden - selectorContext.methodUsingName=Aufruf der Methode [{0}] mit Namen [{1}] selectorContext.noJavaUrl=Auf diesen Kontext muss durch eine java:-URL zugegriffen werden diff -Nru tomcat10-10.1.40/java/org/apache/naming/LocalStrings_es.properties tomcat10-10.1.52/java/org/apache/naming/LocalStrings_es.properties --- tomcat10-10.1.40/java/org/apache/naming/LocalStrings_es.properties 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/naming/LocalStrings_es.properties 2026-01-23 19:33:36.000000000 +0000 @@ -21,8 +21,7 @@ contextBindings.unknownContext=Contexto [{0}] desconocido namingContext.alreadyBound=El nombre [{0}] este ya asociado en este Contexto -namingContext.contextExpected=El nombre no esta asociado a ningun Contexto -namingContext.failResolvingReference=Excepción inesperada resolviendo referencia +namingContext.contextExpected=El nombre [{0}] no está vinculado a un Contexto namingContext.invalidName=Nombre no valido namingContext.nameNotBound=El nombre [{0}] no este asociado a este contexto namingContext.noAbsoluteName=No se puede generar un nombre absoluto para este espacio de nombres diff -Nru tomcat10-10.1.40/java/org/apache/naming/LocalStrings_fr.properties tomcat10-10.1.52/java/org/apache/naming/LocalStrings_fr.properties --- tomcat10-10.1.40/java/org/apache/naming/LocalStrings_fr.properties 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/naming/LocalStrings_fr.properties 2026-01-23 19:33:36.000000000 +0000 @@ -21,8 +21,8 @@ contextBindings.unknownContext=Nom de Contexte inconnu : [{0}] namingContext.alreadyBound=Le Nom [{0}] est déjà lié à ce Contexte -namingContext.contextExpected=Le Nom n'est pas lié à un Contexte -namingContext.failResolvingReference=Une erreur s est produite durant la résolution de la référence +namingContext.contextExpected=Le nom [{0}] n''est pas associé à un Context +namingContext.failResolvingReference=Erreur inattendue lors de la résolution de la référence avec le nom [{0}] namingContext.invalidName=Le Nom est invalide namingContext.nameNotBound=Le Nom [{0}] n''est pas lié à ce Contexte namingContext.noAbsoluteName=Impossible de générer un nom absolu pour cet espace de nommage (namespace) diff -Nru tomcat10-10.1.40/java/org/apache/naming/LocalStrings_ja.properties tomcat10-10.1.52/java/org/apache/naming/LocalStrings_ja.properties --- tomcat10-10.1.40/java/org/apache/naming/LocalStrings_ja.properties 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/naming/LocalStrings_ja.properties 2026-01-23 19:33:36.000000000 +0000 @@ -21,8 +21,8 @@ contextBindings.unknownContext=未知のコンテキスト名です: [{0}] namingContext.alreadyBound=名前 [{0}] は既にこのコンテキストにバインドされています -namingContext.contextExpected=名前がコンテキストにバインドされていません -namingContext.failResolvingReference=参照の解決中に予測しない例外が発生しました +namingContext.contextExpected=名前 [{0}] はコンテキストにバインドされていません +namingContext.failResolvingReference=名前 [{0}] の参照を解決中に予期しない例外が発生しました namingContext.invalidName=名前は無効です namingContext.nameNotBound=名前 [{0}] はこのコンテキストにバインドされていません namingContext.noAbsoluteName=この名前空間に絶対名を生成できません diff -Nru tomcat10-10.1.40/java/org/apache/naming/LocalStrings_ko.properties tomcat10-10.1.52/java/org/apache/naming/LocalStrings_ko.properties --- tomcat10-10.1.40/java/org/apache/naming/LocalStrings_ko.properties 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/naming/LocalStrings_ko.properties 2026-01-23 19:33:36.000000000 +0000 @@ -21,8 +21,6 @@ contextBindings.unknownContext=알 수 없는 컨텍스트 이름: [{0}] namingContext.alreadyBound=Name [{0}]이(가) 이미 이 컨텍스트에 바인딩 되어 있습니다. -namingContext.contextExpected=Name이 컨텍스트에 바인딩 되지 않았습니다. -namingContext.failResolvingReference=참조를 결정하는 중 예기치 않은 예외 발생 namingContext.invalidName=Name이 유효하지 않습니다. namingContext.nameNotBound=Name [{0}]은(는) 이 컨텍스트에 바인딩되지 않았습니다. [{1}]을(를) 찾을 수 없습니다. namingContext.noAbsoluteName=이 네임스페이스를 위한 절대 이름을 생성할 수 없습니다. diff -Nru tomcat10-10.1.40/java/org/apache/naming/LocalStrings_ru.properties tomcat10-10.1.52/java/org/apache/naming/LocalStrings_ru.properties --- tomcat10-10.1.40/java/org/apache/naming/LocalStrings_ru.properties 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/naming/LocalStrings_ru.properties 2026-01-23 19:33:36.000000000 +0000 @@ -16,7 +16,5 @@ # Do not edit this file directly. # To edit translations see: https://tomcat.apache.org/getinvolved.html#Translations -namingContext.contextExpected=Имя не привязано к контексту - selectorContext.methodUsingName=Вызов метода [{0}] с именем [{1}] selectorContext.methodUsingString=Вызов метода [{0}] для строки [{1}] diff -Nru tomcat10-10.1.40/java/org/apache/naming/LocalStrings_zh_CN.properties tomcat10-10.1.52/java/org/apache/naming/LocalStrings_zh_CN.properties --- tomcat10-10.1.40/java/org/apache/naming/LocalStrings_zh_CN.properties 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/naming/LocalStrings_zh_CN.properties 2026-01-23 19:33:36.000000000 +0000 @@ -21,8 +21,7 @@ contextBindings.unknownContext=未知.上下文名:[{0}] namingContext.alreadyBound=名称[{0}]已在此上下文中绑定 -namingContext.contextExpected=上下文Context未绑定名称name -namingContext.failResolvingReference=解析引用时意外异常 +namingContext.contextExpected=名称 [{0}] 未被绑定到一个域 namingContext.invalidName=名称无效 namingContext.nameNotBound=名称[{0}]未在此上下文中绑定。找不到[{1}]。 namingContext.noAbsoluteName=无法为此命名空间生成绝对名称 diff -Nru tomcat10-10.1.40/java/org/apache/naming/NameParserImpl.java tomcat10-10.1.52/java/org/apache/naming/NameParserImpl.java --- tomcat10-10.1.40/java/org/apache/naming/NameParserImpl.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/naming/NameParserImpl.java 2026-01-23 19:33:36.000000000 +0000 @@ -23,19 +23,15 @@ /** * Parses names. - * - * @author Remy Maucherat */ -public class NameParserImpl - implements NameParser { +public class NameParserImpl implements NameParser { // ----------------------------------------------------- NameParser Methods @Override - public Name parse(String name) - throws NamingException { + public Name parse(String name) throws NamingException { return new CompositeName(name); } diff -Nru tomcat10-10.1.40/java/org/apache/naming/NamingContext.java tomcat10-10.1.52/java/org/apache/naming/NamingContext.java --- tomcat10-10.1.40/java/org/apache/naming/NamingContext.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/naming/NamingContext.java 2026-01-23 19:33:36.000000000 +0000 @@ -44,8 +44,6 @@ /** * Catalina JNDI Context implementation. - * - * @author Remy Maucherat */ public class NamingContext implements Context { @@ -68,7 +66,7 @@ /** * Builds a naming context. * - * @param env The environment to use to construct the naming context + * @param env The environment to use to construct the naming context * @param name The name of the associated Catalina Context */ public NamingContext(Hashtable env, String name) { @@ -79,17 +77,16 @@ /** * Builds a naming context. * - * @param env The environment to use to construct the naming context - * @param name The name of the associated Catalina Context + * @param env The environment to use to construct the naming context + * @param name The name of the associated Catalina Context * @param bindings The initial bindings for the naming context */ - public NamingContext(Hashtable env, String name, - HashMap bindings) { + public NamingContext(Hashtable env, String name, HashMap bindings) { this.env = new Hashtable<>(); this.name = name; // Populating the environment hashtable - if (env != null ) { + if (env != null) { Enumeration envEntries = env.keys(); while (envEntries.hasMoreElements()) { String entryName = envEntries.nextElement(); @@ -128,13 +125,14 @@ /** - * Determines if an attempt to write to a read-only context results in an - * exception or if the request is ignored. + * Determines if an attempt to write to a read-only context results in an exception or if the request is ignored. */ private boolean exceptionOnFailedWrite = true; + public boolean getExceptionOnFailedWrite() { return exceptionOnFailedWrite; } + public void setExceptionOnFailedWrite(boolean exceptionOnFailedWrite) { this.exceptionOnFailedWrite = exceptionOnFailedWrite; } @@ -143,43 +141,37 @@ // -------------------------------------------------------- Context Methods @Override - public Object lookup(Name name) - throws NamingException { + public Object lookup(Name name) throws NamingException { return lookup(name, true); } @Override - public Object lookup(String name) - throws NamingException { + public Object lookup(String name) throws NamingException { return lookup(new CompositeName(name), true); } @Override - public void bind(Name name, Object obj) - throws NamingException { + public void bind(Name name, Object obj) throws NamingException { bind(name, obj, false); } @Override - public void bind(String name, Object obj) - throws NamingException { + public void bind(String name, Object obj) throws NamingException { bind(new CompositeName(name), obj); } @Override - public void rebind(Name name, Object obj) - throws NamingException { + public void rebind(Name name, Object obj) throws NamingException { bind(name, obj, true); } @Override - public void rebind(String name, Object obj) - throws NamingException { + public void rebind(String name, Object obj) throws NamingException { rebind(new CompositeName(name), obj); } @@ -195,23 +187,20 @@ name = name.getSuffix(1); } if (name.isEmpty()) { - throw new NamingException - (sm.getString("namingContext.invalidName")); + throw new NamingException(sm.getString("namingContext.invalidName")); } NamingEntry entry = bindings.get(name.get(0)); if (entry == null) { - throw new NameNotFoundException - (sm.getString("namingContext.nameNotBound", name, name.get(0))); + throw new NameNotFoundException(sm.getString("namingContext.nameNotBound", name, name.get(0))); } if (name.size() > 1) { if (entry.type == NamingEntry.CONTEXT) { ((Context) entry.value).unbind(name.getSuffix(1)); } else { - throw new NamingException - (sm.getString("namingContext.contextExpected")); + throw new NamingException(sm.getString("namingContext.contextExpected", name.get(0))); } } else { bindings.remove(name.get(0)); @@ -221,15 +210,13 @@ @Override - public void unbind(String name) - throws NamingException { + public void unbind(String name) throws NamingException { unbind(new CompositeName(name)); } @Override - public void rename(Name oldName, Name newName) - throws NamingException { + public void rename(Name oldName, Name newName) throws NamingException { Object value = lookup(oldName); bind(newName, value); unbind(oldName); @@ -237,15 +224,13 @@ @Override - public void rename(String oldName, String newName) - throws NamingException { + public void rename(String oldName, String newName) throws NamingException { rename(new CompositeName(oldName), new CompositeName(newName)); } @Override - public NamingEnumeration list(Name name) - throws NamingException { + public NamingEnumeration list(Name name) throws NamingException { // Removing empty parts while ((!name.isEmpty()) && (name.get(0).isEmpty())) { name = name.getSuffix(1); @@ -257,28 +242,24 @@ NamingEntry entry = bindings.get(name.get(0)); if (entry == null) { - throw new NameNotFoundException - (sm.getString("namingContext.nameNotBound", name, name.get(0))); + throw new NameNotFoundException(sm.getString("namingContext.nameNotBound", name, name.get(0))); } if (entry.type != NamingEntry.CONTEXT) { - throw new NamingException - (sm.getString("namingContext.contextExpected")); + throw new NamingException(sm.getString("namingContext.contextExpected", name.get(0))); } return ((Context) entry.value).list(name.getSuffix(1)); } @Override - public NamingEnumeration list(String name) - throws NamingException { + public NamingEnumeration list(String name) throws NamingException { return list(new CompositeName(name)); } @Override - public NamingEnumeration listBindings(Name name) - throws NamingException { + public NamingEnumeration listBindings(Name name) throws NamingException { // Removing empty parts while ((!name.isEmpty()) && (name.get(0).isEmpty())) { name = name.getSuffix(1); @@ -290,21 +271,18 @@ NamingEntry entry = bindings.get(name.get(0)); if (entry == null) { - throw new NameNotFoundException - (sm.getString("namingContext.nameNotBound", name, name.get(0))); + throw new NameNotFoundException(sm.getString("namingContext.nameNotBound", name, name.get(0))); } if (entry.type != NamingEntry.CONTEXT) { - throw new NamingException - (sm.getString("namingContext.contextExpected")); + throw new NamingException(sm.getString("namingContext.contextExpected", name.get(0))); } return ((Context) entry.value).listBindings(name.getSuffix(1)); } @Override - public NamingEnumeration listBindings(String name) - throws NamingException { + public NamingEnumeration listBindings(String name) throws NamingException { return listBindings(new CompositeName(name)); } @@ -320,31 +298,27 @@ name = name.getSuffix(1); } if (name.isEmpty()) { - throw new NamingException - (sm.getString("namingContext.invalidName")); + throw new NamingException(sm.getString("namingContext.invalidName")); } NamingEntry entry = bindings.get(name.get(0)); if (entry == null) { - throw new NameNotFoundException - (sm.getString("namingContext.nameNotBound", name, name.get(0))); + throw new NameNotFoundException(sm.getString("namingContext.nameNotBound", name, name.get(0))); } if (name.size() > 1) { if (entry.type == NamingEntry.CONTEXT) { ((Context) entry.value).destroySubcontext(name.getSuffix(1)); } else { - throw new NamingException - (sm.getString("namingContext.contextExpected")); + throw new NamingException(sm.getString("namingContext.contextExpected", name.get(0))); } } else { if (entry.type == NamingEntry.CONTEXT) { ((Context) entry.value).close(); bindings.remove(name.get(0)); } else { - throw new NotContextException - (sm.getString("namingContext.contextExpected")); + throw new NotContextException(sm.getString("namingContext.contextExpected", name.get(0))); } } @@ -352,8 +326,7 @@ @Override - public void destroySubcontext(String name) - throws NamingException { + public void destroySubcontext(String name) throws NamingException { destroySubcontext(new CompositeName(name)); } @@ -374,29 +347,25 @@ @Override - public Context createSubcontext(String name) - throws NamingException { + public Context createSubcontext(String name) throws NamingException { return createSubcontext(new CompositeName(name)); } @Override - public Object lookupLink(Name name) - throws NamingException { + public Object lookupLink(Name name) throws NamingException { return lookup(name, false); } @Override - public Object lookupLink(String name) - throws NamingException { + public Object lookupLink(String name) throws NamingException { return lookup(new CompositeName(name), false); } @Override - public NameParser getNameParser(Name name) - throws NamingException { + public NameParser getNameParser(Name name) throws NamingException { while ((!name.isEmpty()) && (name.get(0).isEmpty())) { name = name.getSuffix(1); @@ -410,8 +379,7 @@ if (obj instanceof Context) { return ((Context) obj).getNameParser(name.getSuffix(1)); } else { - throw new NotContextException - (sm.getString("namingContext.contextExpected")); + throw new NotContextException(sm.getString("namingContext.contextExpected", name.get(0))); } } @@ -421,8 +389,7 @@ @Override - public NameParser getNameParser(String name) - throws NamingException { + public NameParser getNameParser(String name) throws NamingException { return getNameParser(new CompositeName(name)); } @@ -447,7 +414,7 @@ @Override - public Object removeFromEnvironment(String propName){ + public Object removeFromEnvironment(String propName) { return env.remove(propName); } @@ -468,10 +435,8 @@ @Override - public String getNameInNamespace() - throws NamingException { - throw new OperationNotSupportedException - (sm.getString("namingContext.noAbsoluteName")); + public String getNameInNamespace() throws NamingException { + throw new OperationNotSupportedException(sm.getString("namingContext.noAbsoluteName")); } @@ -496,13 +461,14 @@ /** * Retrieves the named object. * - * @param name the name of the object to look up + * @param name the name of the object to look up * @param resolveLinks If true, the links will be resolved + * * @return the object bound to name + * * @exception NamingException if a naming exception is encountered */ - protected Object lookup(Name name, boolean resolveLinks) - throws NamingException { + protected Object lookup(Name name, boolean resolveLinks) throws NamingException { // Removing empty parts while ((!name.isEmpty()) && (name.get(0).isEmpty())) { @@ -516,16 +482,14 @@ NamingEntry entry = bindings.get(name.get(0)); if (entry == null) { - throw new NameNotFoundException - (sm.getString("namingContext.nameNotBound", name, name.get(0))); + throw new NameNotFoundException(sm.getString("namingContext.nameNotBound", name, name.get(0))); } if (name.size() > 1) { // If the size of the name is greater than 1, then we go through a // number of sub contexts. if (entry.type != NamingEntry.CONTEXT) { - throw new NamingException - (sm.getString("namingContext.contextExpected")); + throw new NamingException(sm.getString("namingContext.contextExpected", name.get(0))); } return ((Context) entry.value).lookup(name.getSuffix(1)); } else { @@ -556,21 +520,20 @@ } if (entry.value instanceof ResourceRef) { boolean singleton = Boolean.parseBoolean( - (String) ((ResourceRef) entry.value).get( - ResourceRef.SINGLETON).getContent()); + (String) ((ResourceRef) entry.value).get(ResourceRef.SINGLETON).getContent()); if (singleton) { entry.type = NamingEntry.ENTRY; entry.value = obj; } } if (obj == null) { - throw new NamingException(sm.getString("namingContext.failResolvingReference")); + throw new NamingException(sm.getString("namingContext.failResolvingReference", name)); } return obj; } catch (NamingException e) { throw e; } catch (Exception e) { - String msg = sm.getString("namingContext.failResolvingReference"); + String msg = sm.getString("namingContext.failResolvingReference", name); log.warn(msg, e); NamingException ne = new NamingException(msg); ne.initCause(e); @@ -585,20 +548,18 @@ /** - * Binds a name to an object. All intermediate contexts and the target - * context (that named by all but terminal atomic component of the name) - * must already exist. + * Binds a name to an object. All intermediate contexts and the target context (that named by all but terminal + * atomic component of the name) must already exist. * - * @param name the name to bind; may not be empty - * @param obj the object to bind; possibly null + * @param name the name to bind; may not be empty + * @param obj the object to bind; possibly null * @param rebind if true, then perform a rebind (ie, overwrite) - * @exception NameAlreadyBoundException if name is already bound - * @exception javax.naming.directory.InvalidAttributesException if object - * did not supply all mandatory attributes - * @exception NamingException if a naming exception is encountered + * + * @exception NameAlreadyBoundException if name is already bound + * @exception javax.naming.directory.InvalidAttributesException if object did not supply all mandatory attributes + * @exception NamingException if a naming exception is encountered */ - protected void bind(Name name, Object obj, boolean rebind) - throws NamingException { + protected void bind(Name name, Object obj, boolean rebind) throws NamingException { if (!checkWritable()) { return; @@ -608,16 +569,14 @@ name = name.getSuffix(1); } if (name.isEmpty()) { - throw new NamingException - (sm.getString("namingContext.invalidName")); + throw new NamingException(sm.getString("namingContext.invalidName")); } NamingEntry entry = bindings.get(name.get(0)); if (name.size() > 1) { if (entry == null) { - throw new NameNotFoundException(sm.getString( - "namingContext.nameNotBound", name, name.get(0))); + throw new NameNotFoundException(sm.getString("namingContext.nameNotBound", name, name.get(0))); } if (entry.type == NamingEntry.CONTEXT) { if (rebind) { @@ -626,34 +585,26 @@ ((Context) entry.value).bind(name.getSuffix(1), obj); } } else { - throw new NamingException - (sm.getString("namingContext.contextExpected")); + throw new NamingException(sm.getString("namingContext.contextExpected", name.get(0))); } } else { if ((!rebind) && (entry != null)) { - throw new NameAlreadyBoundException - (sm.getString("namingContext.alreadyBound", name.get(0))); + throw new NameAlreadyBoundException(sm.getString("namingContext.alreadyBound", name.get(0))); } else { // Getting the type of the object and wrapping it within a new // NamingEntry - Object toBind = - NamingManager.getStateToBind(obj, name, this, env); + Object toBind = NamingManager.getStateToBind(obj, name, this, env); if (toBind instanceof Context) { - entry = new NamingEntry(name.get(0), toBind, - NamingEntry.CONTEXT); + entry = new NamingEntry(name.get(0), toBind, NamingEntry.CONTEXT); } else if (toBind instanceof LinkRef) { - entry = new NamingEntry(name.get(0), toBind, - NamingEntry.LINK_REF); + entry = new NamingEntry(name.get(0), toBind, NamingEntry.LINK_REF); } else if (toBind instanceof Reference) { - entry = new NamingEntry(name.get(0), toBind, - NamingEntry.REFERENCE); + entry = new NamingEntry(name.get(0), toBind, NamingEntry.REFERENCE); } else if (toBind instanceof Referenceable) { toBind = ((Referenceable) toBind).getReference(); - entry = new NamingEntry(name.get(0), toBind, - NamingEntry.REFERENCE); + entry = new NamingEntry(name.get(0), toBind, NamingEntry.REFERENCE); } else { - entry = new NamingEntry(name.get(0), toBind, - NamingEntry.ENTRY); + entry = new NamingEntry(name.get(0), toBind, NamingEntry.ENTRY); } bindings.put(name.get(0), entry); } @@ -672,9 +623,11 @@ /** * Throws a naming exception is Context is not writable. + * * @return true if the Context is writable - * @throws NamingException if the Context is not writable and - * exceptionOnFailedWrite is true + * + * @throws NamingException if the Context is not writable and exceptionOnFailedWrite is + * true */ protected boolean checkWritable() throws NamingException { if (isWritable()) { diff -Nru tomcat10-10.1.40/java/org/apache/naming/NamingContextBindingsEnumeration.java tomcat10-10.1.52/java/org/apache/naming/NamingContextBindingsEnumeration.java --- tomcat10-10.1.40/java/org/apache/naming/NamingContextBindingsEnumeration.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/naming/NamingContextBindingsEnumeration.java 2026-01-23 19:33:36.000000000 +0000 @@ -26,18 +26,14 @@ /** * Naming enumeration implementation. - * - * @author Remy Maucherat */ -public class NamingContextBindingsEnumeration - implements NamingEnumeration { +public class NamingContextBindingsEnumeration implements NamingEnumeration { // ----------------------------------------------------------- Constructors - public NamingContextBindingsEnumeration(Iterator entries, - Context ctx) { + public NamingContextBindingsEnumeration(Iterator entries, Context ctx) { iterator = entries; this.ctx = ctx; } @@ -61,22 +57,19 @@ @Override - public Binding next() - throws NamingException { + public Binding next() throws NamingException { return nextElementInternal(); } @Override - public boolean hasMore() - throws NamingException { + public boolean hasMore() throws NamingException { return iterator.hasNext(); } @Override - public void close() - throws NamingException { + public void close() throws NamingException { } @@ -100,8 +93,7 @@ Object value; // If the entry is a reference, resolve it - if (entry.type == NamingEntry.REFERENCE - || entry.type == NamingEntry.LINK_REF) { + if (entry.type == NamingEntry.REFERENCE || entry.type == NamingEntry.LINK_REF) { try { value = ctx.lookup(new CompositeName(entry.name)); } catch (NamingException e) { diff -Nru tomcat10-10.1.40/java/org/apache/naming/NamingContextEnumeration.java tomcat10-10.1.52/java/org/apache/naming/NamingContextEnumeration.java --- tomcat10-10.1.40/java/org/apache/naming/NamingContextEnumeration.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/naming/NamingContextEnumeration.java 2026-01-23 19:33:36.000000000 +0000 @@ -24,11 +24,8 @@ /** * Naming enumeration implementation. - * - * @author Remy Maucherat */ -public class NamingContextEnumeration - implements NamingEnumeration { +public class NamingContextEnumeration implements NamingEnumeration { // ----------------------------------------------------------- Constructors @@ -52,22 +49,19 @@ @Override - public NameClassPair next() - throws NamingException { + public NameClassPair next() throws NamingException { return nextElement(); } @Override - public boolean hasMore() - throws NamingException { + public boolean hasMore() throws NamingException { return iterator.hasNext(); } @Override - public void close() - throws NamingException { + public void close() throws NamingException { } diff -Nru tomcat10-10.1.40/java/org/apache/naming/NamingEntry.java tomcat10-10.1.52/java/org/apache/naming/NamingEntry.java --- tomcat10-10.1.40/java/org/apache/naming/NamingEntry.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/naming/NamingEntry.java 2026-01-23 19:33:36.000000000 +0000 @@ -19,8 +19,6 @@ /** * Represents a binding in a NamingContext. - * - * @author Remy Maucherat */ public class NamingEntry { @@ -38,8 +36,7 @@ /** - * The type instance variable is used to avoid using RTTI when doing - * lookups. + * The type instance variable is used to avoid using RTTI when doing lookups. */ public int type; public final String name; diff -Nru tomcat10-10.1.40/java/org/apache/naming/ResourceEnvRef.java tomcat10-10.1.52/java/org/apache/naming/ResourceEnvRef.java --- tomcat10-10.1.40/java/org/apache/naming/ResourceEnvRef.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/naming/ResourceEnvRef.java 2026-01-23 19:33:36.000000000 +0000 @@ -18,8 +18,6 @@ /** * Represents a reference address to a resource environment. - * - * @author Remy Maucherat */ public class ResourceEnvRef extends AbstractRef { @@ -29,8 +27,7 @@ /** * Default factory for this reference. */ - public static final String DEFAULT_FACTORY = - org.apache.naming.factory.Constants.DEFAULT_RESOURCE_ENV_FACTORY; + public static final String DEFAULT_FACTORY = org.apache.naming.factory.Constants.DEFAULT_RESOURCE_ENV_FACTORY; /** diff -Nru tomcat10-10.1.40/java/org/apache/naming/ResourceLinkRef.java tomcat10-10.1.52/java/org/apache/naming/ResourceLinkRef.java --- tomcat10-10.1.40/java/org/apache/naming/ResourceLinkRef.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/naming/ResourceLinkRef.java 2026-01-23 19:33:36.000000000 +0000 @@ -20,8 +20,6 @@ /** * Represents a reference address to a resource. - * - * @author Remy Maucherat */ public class ResourceLinkRef extends AbstractRef { @@ -31,8 +29,7 @@ /** * Default factory for this reference. */ - public static final String DEFAULT_FACTORY = - org.apache.naming.factory.Constants.DEFAULT_RESOURCE_LINK_FACTORY; + public static final String DEFAULT_FACTORY = org.apache.naming.factory.Constants.DEFAULT_RESOURCE_LINK_FACTORY; /** @@ -44,14 +41,12 @@ /** * ResourceLink Reference. * - * @param resourceClass Resource class - * @param globalName Global name - * @param factory The possibly null class name of the object's factory. - * @param factoryLocation The possibly null location from which to load the - * factory (e.g. URL) + * @param resourceClass Resource class + * @param globalName Global name + * @param factory The possibly null class name of the object's factory. + * @param factoryLocation The possibly null location from which to load the factory (e.g. URL) */ - public ResourceLinkRef(String resourceClass, String globalName, - String factory, String factoryLocation) { + public ResourceLinkRef(String resourceClass, String globalName, String factory, String factoryLocation) { super(resourceClass, factory, factoryLocation); if (globalName != null) { add(new StringRefAddr(GLOBALNAME, globalName)); diff -Nru tomcat10-10.1.40/java/org/apache/naming/ResourceRef.java tomcat10-10.1.52/java/org/apache/naming/ResourceRef.java --- tomcat10-10.1.40/java/org/apache/naming/ResourceRef.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/naming/ResourceRef.java 2026-01-23 19:33:36.000000000 +0000 @@ -20,8 +20,6 @@ /** * Represents a reference address to a resource. - * - * @author Remy Maucherat */ public class ResourceRef extends AbstractRef { @@ -31,8 +29,7 @@ /** * Default factory for this reference. */ - public static final String DEFAULT_FACTORY = - org.apache.naming.factory.Constants.DEFAULT_RESOURCE_FACTORY; + public static final String DEFAULT_FACTORY = org.apache.naming.factory.Constants.DEFAULT_RESOURCE_FACTORY; /** @@ -63,14 +60,13 @@ * Resource Reference. * * @param resourceClass Resource class - * @param description Description of the resource - * @param scope Resource scope - * @param auth Resource authentication - * @param singleton Is this resource a singleton (every lookup should return - * the same instance rather than a new instance)? + * @param description Description of the resource + * @param scope Resource scope + * @param auth Resource authentication + * @param singleton Is this resource a singleton (every lookup should return the same instance rather than a new + * instance)? */ - public ResourceRef(String resourceClass, String description, - String scope, String auth, boolean singleton) { + public ResourceRef(String resourceClass, String description, String scope, String auth, boolean singleton) { this(resourceClass, description, scope, auth, singleton, null, null); } @@ -78,19 +74,17 @@ /** * Resource Reference. * - * @param resourceClass Resource class - * @param description Description of the resource - * @param scope Resource scope - * @param auth Resource authentication - * @param singleton Is this resource a singleton (every lookup should return - * the same instance rather than a new instance)? - * @param factory The possibly null class name of the object's factory. - * @param factoryLocation The possibly null location from which to load the - * factory (e.g. URL) - */ - public ResourceRef(String resourceClass, String description, - String scope, String auth, boolean singleton, - String factory, String factoryLocation) { + * @param resourceClass Resource class + * @param description Description of the resource + * @param scope Resource scope + * @param auth Resource authentication + * @param singleton Is this resource a singleton (every lookup should return the same instance rather than a + * new instance)? + * @param factory The possibly null class name of the object's factory. + * @param factoryLocation The possibly null location from which to load the factory (e.g. URL) + */ + public ResourceRef(String resourceClass, String description, String scope, String auth, boolean singleton, + String factory, String factoryLocation) { super(resourceClass, factory, factoryLocation); StringRefAddr refAddr; if (description != null) { diff -Nru tomcat10-10.1.40/java/org/apache/naming/SelectorContext.java tomcat10-10.1.52/java/org/apache/naming/SelectorContext.java --- tomcat10-10.1.40/java/org/apache/naming/SelectorContext.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/naming/SelectorContext.java 2026-01-23 19:33:36.000000000 +0000 @@ -31,8 +31,6 @@ /** * Catalina JNDI Context implementation. - * - * @author Remy Maucherat */ public class SelectorContext implements Context { @@ -65,6 +63,7 @@ /** * Builds a Catalina selector context using the given environment. + * * @param env The environment */ public SelectorContext(Hashtable env) { @@ -75,12 +74,11 @@ /** * Builds a Catalina selector context using the given environment. - * @param env The environment - * @param initialContext true if this is the main - * initial context + * + * @param env The environment + * @param initialContext true if this is the main initial context */ - public SelectorContext(Hashtable env, - boolean initialContext) { + public SelectorContext(Hashtable env, boolean initialContext) { this.env = env; this.initialContext = initialContext; } @@ -114,12 +112,10 @@ @Override - public Object lookup(Name name) - throws NamingException { + public Object lookup(Name name) throws NamingException { if (log.isTraceEnabled()) { - log.trace(sm.getString("selectorContext.methodUsingName", "lookup", - name)); + log.trace(sm.getString("selectorContext.methodUsingName", "lookup", name)); } // Strip the URL header @@ -130,12 +126,10 @@ @Override - public Object lookup(String name) - throws NamingException { + public Object lookup(String name) throws NamingException { if (log.isTraceEnabled()) { - log.trace(sm.getString("selectorContext.methodUsingString", "lookup", - name)); + log.trace(sm.getString("selectorContext.methodUsingString", "lookup", name)); } // Strip the URL header @@ -146,68 +140,58 @@ @Override - public void bind(Name name, Object obj) - throws NamingException { + public void bind(Name name, Object obj) throws NamingException { getBoundContext().bind(parseName(name), obj); } @Override - public void bind(String name, Object obj) - throws NamingException { + public void bind(String name, Object obj) throws NamingException { getBoundContext().bind(parseName(name), obj); } @Override - public void rebind(Name name, Object obj) - throws NamingException { + public void rebind(Name name, Object obj) throws NamingException { getBoundContext().rebind(parseName(name), obj); } @Override - public void rebind(String name, Object obj) - throws NamingException { + public void rebind(String name, Object obj) throws NamingException { getBoundContext().rebind(parseName(name), obj); } @Override - public void unbind(Name name) - throws NamingException { + public void unbind(Name name) throws NamingException { getBoundContext().unbind(parseName(name)); } @Override - public void unbind(String name) - throws NamingException { + public void unbind(String name) throws NamingException { getBoundContext().unbind(parseName(name)); } @Override - public void rename(Name oldName, Name newName) - throws NamingException { + public void rename(Name oldName, Name newName) throws NamingException { getBoundContext().rename(parseName(oldName), parseName(newName)); } @Override - public void rename(String oldName, String newName) - throws NamingException { + public void rename(String oldName, String newName) throws NamingException { getBoundContext().rename(parseName(oldName), parseName(newName)); } @Override - public NamingEnumeration list(Name name) - throws NamingException { + public NamingEnumeration list(Name name) throws NamingException { if (log.isTraceEnabled()) { - log.trace(sm.getString("selectorContext.methodUsingName", "list", - name)); + log.trace(sm.getString("selectorContext.methodUsingName", "list", name)); } return getBoundContext().list(parseName(name)); @@ -215,12 +199,10 @@ @Override - public NamingEnumeration list(String name) - throws NamingException { + public NamingEnumeration list(String name) throws NamingException { if (log.isTraceEnabled()) { - log.trace(sm.getString("selectorContext.methodUsingString", "list", - name)); + log.trace(sm.getString("selectorContext.methodUsingString", "list", name)); } return getBoundContext().list(parseName(name)); @@ -228,12 +210,10 @@ @Override - public NamingEnumeration listBindings(Name name) - throws NamingException { + public NamingEnumeration listBindings(Name name) throws NamingException { if (log.isTraceEnabled()) { - log.trace(sm.getString("selectorContext.methodUsingName", - "listBindings", name)); + log.trace(sm.getString("selectorContext.methodUsingName", "listBindings", name)); } return getBoundContext().listBindings(parseName(name)); @@ -241,12 +221,10 @@ @Override - public NamingEnumeration listBindings(String name) - throws NamingException { + public NamingEnumeration listBindings(String name) throws NamingException { if (log.isTraceEnabled()) { - log.trace(sm.getString("selectorContext.methodUsingString", - "listBindings", name)); + log.trace(sm.getString("selectorContext.methodUsingString", "listBindings", name)); } return getBoundContext().listBindings(parseName(name)); @@ -254,40 +232,34 @@ @Override - public void destroySubcontext(Name name) - throws NamingException { + public void destroySubcontext(Name name) throws NamingException { getBoundContext().destroySubcontext(parseName(name)); } @Override - public void destroySubcontext(String name) - throws NamingException { + public void destroySubcontext(String name) throws NamingException { getBoundContext().destroySubcontext(parseName(name)); } @Override - public Context createSubcontext(Name name) - throws NamingException { + public Context createSubcontext(Name name) throws NamingException { return getBoundContext().createSubcontext(parseName(name)); } @Override - public Context createSubcontext(String name) - throws NamingException { + public Context createSubcontext(String name) throws NamingException { return getBoundContext().createSubcontext(parseName(name)); } @Override - public Object lookupLink(Name name) - throws NamingException { + public Object lookupLink(Name name) throws NamingException { if (log.isTraceEnabled()) { - log.trace(sm.getString("selectorContext.methodUsingName", - "lookupLink", name)); + log.trace(sm.getString("selectorContext.methodUsingName", "lookupLink", name)); } return getBoundContext().lookupLink(parseName(name)); @@ -295,12 +267,10 @@ @Override - public Object lookupLink(String name) - throws NamingException { + public Object lookupLink(String name) throws NamingException { if (log.isTraceEnabled()) { - log.trace(sm.getString("selectorContext.methodUsingString", - "lookupLink", name)); + log.trace(sm.getString("selectorContext.methodUsingString", "lookupLink", name)); } return getBoundContext().lookupLink(parseName(name)); @@ -308,65 +278,56 @@ @Override - public NameParser getNameParser(Name name) - throws NamingException { + public NameParser getNameParser(Name name) throws NamingException { return getBoundContext().getNameParser(parseName(name)); } @Override - public NameParser getNameParser(String name) - throws NamingException { + public NameParser getNameParser(String name) throws NamingException { return getBoundContext().getNameParser(parseName(name)); } @Override - public Name composeName(Name name, Name prefix) - throws NamingException { + public Name composeName(Name name, Name prefix) throws NamingException { Name prefixClone = (Name) prefix.clone(); return prefixClone.addAll(name); } @Override - public String composeName(String name, String prefix) - throws NamingException { + public String composeName(String name, String prefix) throws NamingException { return prefix + "/" + name; } @Override - public Object addToEnvironment(String propName, Object propVal) - throws NamingException { + public Object addToEnvironment(String propName, Object propVal) throws NamingException { return getBoundContext().addToEnvironment(propName, propVal); } @Override - public Object removeFromEnvironment(String propName) - throws NamingException { + public Object removeFromEnvironment(String propName) throws NamingException { return getBoundContext().removeFromEnvironment(propName); } @Override - public Hashtable getEnvironment() - throws NamingException { + public Hashtable getEnvironment() throws NamingException { return getBoundContext().getEnvironment(); } @Override - public void close() - throws NamingException { + public void close() throws NamingException { getBoundContext().close(); } @Override - public String getNameInNamespace() - throws NamingException { + public String getNameInNamespace() throws NamingException { return prefix; } @@ -376,12 +337,12 @@ /** * Get the bound context. - * @return the Context bound with either the current thread or - * the current classloader + * + * @return the Context bound with either the current thread or the current classloader + * * @throws NamingException Bindings exception */ - protected Context getBoundContext() - throws NamingException { + protected Context getBoundContext() throws NamingException { if (initialContext) { String ICName = IC_PREFIX; @@ -411,13 +372,14 @@ /** * Strips the URL header. + * * @param name The name + * * @return the parsed name - * @throws NamingException if there is no "java:" header or if no - * naming context has been bound to this thread + * + * @throws NamingException if there is no "java:" header or if no naming context has been bound to this thread */ - protected String parseName(String name) - throws NamingException { + protected String parseName(String name) throws NamingException { if ((!initialContext) && (name.startsWith(prefix))) { return name.substring(prefixLength); @@ -425,8 +387,7 @@ if (initialContext) { return name; } else { - throw new NamingException - (sm.getString("selectorContext.noJavaUrl")); + throw new NamingException(sm.getString("selectorContext.noJavaUrl")); } } @@ -435,16 +396,16 @@ /** * Strips the URL header. + * * @param name The name + * * @return the parsed name - * @throws NamingException if there is no "java:" header or if no - * naming context has been bound to this thread + * + * @throws NamingException if there is no "java:" header or if no naming context has been bound to this thread */ - protected Name parseName(Name name) - throws NamingException { + protected Name parseName(Name name) throws NamingException { - if (!initialContext && !name.isEmpty() && - name.get(0).startsWith(prefix)) { + if (!initialContext && !name.isEmpty() && name.get(0).startsWith(prefix)) { if (name.get(0).equals(prefix)) { return name.getSuffix(1); } else { @@ -456,8 +417,7 @@ if (initialContext) { return name; } else { - throw new NamingException( - sm.getString("selectorContext.noJavaUrl")); + throw new NamingException(sm.getString("selectorContext.noJavaUrl")); } } diff -Nru tomcat10-10.1.40/java/org/apache/naming/ServiceRef.java tomcat10-10.1.52/java/org/apache/naming/ServiceRef.java --- tomcat10-10.1.40/java/org/apache/naming/ServiceRef.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/naming/ServiceRef.java 2026-01-23 19:33:36.000000000 +0000 @@ -23,8 +23,6 @@ /** * Represents a reference web service. - * - * @author Fabien Carrion */ public class ServiceRef extends AbstractRef { @@ -34,20 +32,19 @@ /** * Default factory for this reference. */ - public static final String DEFAULT_FACTORY = - org.apache.naming.factory.Constants.DEFAULT_SERVICE_FACTORY; + public static final String DEFAULT_FACTORY = org.apache.naming.factory.Constants.DEFAULT_SERVICE_FACTORY; /** * Service Classname address type. */ - public static final String SERVICE_INTERFACE = "serviceInterface"; + public static final String SERVICE_INTERFACE = "serviceInterface"; /** * ServiceQname address type. */ - public static final String SERVICE_NAMESPACE = "service namespace"; + public static final String SERVICE_NAMESPACE = "service namespace"; public static final String SERVICE_LOCAL_PART = "service local part"; @@ -76,23 +73,19 @@ /** - * The list to save the handler Reference objects, because they can't be - * saved in the addrs vector. + * The list to save the handler Reference objects, because they can't be saved in the addrs vector. */ private final List handlers = new CopyOnWriteArrayList<>(); - public ServiceRef(String refname, String serviceInterface, String[] serviceQname, - String wsdl, String jaxrpcmapping) { - this(refname, serviceInterface, serviceQname, wsdl, jaxrpcmapping, - null, null); + public ServiceRef(String refname, String serviceInterface, String[] serviceQname, String wsdl, + String jaxrpcmapping) { + this(refname, serviceInterface, serviceQname, wsdl, jaxrpcmapping, null, null); } - public ServiceRef(@SuppressWarnings("unused") String refname, - String serviceInterface, String[] serviceQname, - String wsdl, String jaxrpcmapping, - String factory, String factoryLocation) { + public ServiceRef(@SuppressWarnings("unused") String refname, String serviceInterface, String[] serviceQname, + String wsdl, String jaxrpcmapping, String factory, String factoryLocation) { super(serviceInterface, factory, factoryLocation); StringRefAddr refAddr; if (serviceInterface != null) { @@ -120,6 +113,7 @@ /** * Add and Get Handlers classes. + * * @return the handler */ public HandlerRef getHandler() { diff -Nru tomcat10-10.1.40/java/org/apache/naming/StringManager.java tomcat10-10.1.52/java/org/apache/naming/StringManager.java --- tomcat10-10.1.40/java/org/apache/naming/StringManager.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/naming/StringManager.java 2026-01-23 19:33:36.000000000 +0000 @@ -24,27 +24,18 @@ import java.util.ResourceBundle; /** - * An internationalization / localization helper class which reduces - * the bother of handling ResourceBundles and takes care of the - * common cases of message formatting which otherwise require the - * creation of Object arrays and such. + * An internationalization / localization helper class which reduces the bother of handling ResourceBundles and takes + * care of the common cases of message formatting which otherwise require the creation of Object arrays and such. + *

        + * The StringManager operates on a package basis. One StringManager per package can be created and accessed via the + * getManager method call. + *

        + * The StringManager will look for a ResourceBundle named by the package name given plus the suffix of "LocalStrings". + * In practice, this means that the localized information will be contained in a LocalStrings.properties file located in + * the package directory of the classpath. + *

        + * Please see the documentation for java.util.ResourceBundle for more information. * - *

        The StringManager operates on a package basis. One StringManager - * per package can be created and accessed via the getManager method - * call. - * - *

        The StringManager will look for a ResourceBundle named by - * the package name given plus the suffix of "LocalStrings". In - * practice, this means that the localized information will be contained - * in a LocalStrings.properties file located in the package - * directory of the classpath. - * - *

        Please see the documentation for java.util.ResourceBundle for - * more information. - * - * @author James Duncan Davidson [duncan@eng.sun.com] - * @author James Todd [gonzo@eng.sun.com] - * @author Mel Martinez [mmartinez@g1440.com] * @see java.util.ResourceBundle */ public class StringManager { @@ -56,10 +47,8 @@ private final Locale locale; /** - * Creates a new StringManager for a given package. This is a - * private method and all access to it is arbitrated by the - * static getManager method call so that only one StringManager - * per package will be created. + * Creates a new StringManager for a given package. This is a private method and all access to it is arbitrated by + * the static getManager method call so that only one StringManager per package will be created. * * @param packageName Name of package to create StringManager for. */ @@ -75,9 +64,8 @@ ClassLoader cl = Thread.currentThread().getContextClassLoader(); if (cl != null) { try { - tempBundle = ResourceBundle.getBundle( - bundleName, Locale.getDefault(), cl); - } catch (MissingResourceException ex2) { + tempBundle = ResourceBundle.getBundle(bundleName, Locale.getDefault(), cl); + } catch (MissingResourceException ignore) { // Ignore } } @@ -92,19 +80,17 @@ } /** - * Get a string from the underlying resource bundle or return - * null if the String is not found. + * Get a string from the underlying resource bundle or return null if the String is not found. * - * @param key to desired resource String - * @return resource String matching key from underlying - * bundle or null if not found. - * @throws IllegalArgumentException if key is null. + * @param key to desired resource String + * + * @return resource String matching key from underlying bundle or null if not found. + * + * @throws IllegalArgumentException if key is null. */ public String getString(String key) { if (key == null) { - String msg = "key may not have a null value"; - - throw new IllegalArgumentException(msg); + throw new IllegalArgumentException("key may not have a null value"); } String str = null; @@ -114,17 +100,17 @@ if (bundle != null) { str = bundle.getString(key); } - } catch (MissingResourceException mre) { - //bad: shouldn't mask an exception the following way: - // str = "[cannot find message associated with key '" + key + "' due to " + mre + "]"; - // because it hides the fact that the String was missing - // from the calling code. - //good: could just throw the exception (or wrap it in another) - // but that would probably cause much havoc on existing - // code. - //better: consistent with container pattern to - // simply return null. Calling code can then do - // a null check. + } catch (MissingResourceException ignore) { + // bad: shouldn't mask an exception the following way: + // str = "[cannot find message associated with key '" + key + "' due to " + mre + "]"; + // because it hides the fact that the String was missing + // from the calling code. + // good: could just throw the exception (or wrap it in another) + // but that would probably cause much havoc on existing + // code. + // better: consistent with container pattern to + // simply return null. Calling code can then do + // a null check. // str is already set to null } @@ -132,14 +118,12 @@ } /** - * Get a string from the underlying resource bundle and format - * it with the given set of arguments. + * Get a string from the underlying resource bundle and format it with the given set of arguments. * * @param key The key for the required message * @param args The values to insert into the message * - * @return The request string formatted with the provided arguments or the - * key if the key was not found. + * @return The request string formatted with the provided arguments or the key if the key was not found. */ public String getString(final String key, final Object... args) { String value = getString(key); @@ -156,12 +140,11 @@ // STATIC SUPPORT METHODS // -------------------------------------------------------------- - private static final Map managers = new HashMap<>(); + private static final Map managers = new HashMap<>(); /** - * Get the StringManager for a particular package. If a manager for - * a package already exists, it will be reused, else a new - * StringManager will be created and returned. + * Get the StringManager for a particular package. If a manager for a package already exists, it will be reused, + * else a new StringManager will be created and returned. * * @param packageName The package name * diff -Nru tomcat10-10.1.40/java/org/apache/naming/TransactionRef.java tomcat10-10.1.52/java/org/apache/naming/TransactionRef.java --- tomcat10-10.1.40/java/org/apache/naming/TransactionRef.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/naming/TransactionRef.java 2026-01-23 19:33:36.000000000 +0000 @@ -18,8 +18,6 @@ /** * Represents a reference address to a transaction. - * - * @author Remy Maucherat */ public class TransactionRef extends AbstractRef { @@ -29,8 +27,7 @@ /** * Default factory for this reference. */ - public static final String DEFAULT_FACTORY = - org.apache.naming.factory.Constants.DEFAULT_TRANSACTION_FACTORY; + public static final String DEFAULT_FACTORY = org.apache.naming.factory.Constants.DEFAULT_TRANSACTION_FACTORY; /** @@ -44,7 +41,7 @@ /** * Resource Reference. * - * @param factory The factory class + * @param factory The factory class * @param factoryLocation The factory location */ public TransactionRef(String factory, String factoryLocation) { diff -Nru tomcat10-10.1.40/java/org/apache/naming/factory/BeanFactory.java tomcat10-10.1.52/java/org/apache/naming/factory/BeanFactory.java --- tomcat10-10.1.40/java/org/apache/naming/factory/BeanFactory.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/naming/factory/BeanFactory.java 2026-01-23 19:33:36.000000000 +0000 @@ -37,10 +37,11 @@ /** * Object factory for any Resource conforming to the JavaBean spec. + *

        + * This factory can be configured in a <Context> element in your conf/server.xml + * configuration file. An example of factory configuration is: + *

        * - *

        This factory can be configured in a <Context> element - * in your conf/server.xml - * configuration file. An example of factory configuration is:

        *
          * <Resource name="jdbc/myDataSource"
          *           auth="SERVLET"
        @@ -56,8 +57,6 @@
          *           maxLimit="5"
          *           />
          * 
        - * - * @author Aner Perez [aner at ncstech.com] */ public class BeanFactory implements ObjectFactory { @@ -68,11 +67,13 @@ /** * Create a new Bean instance. * - * @param obj The reference object describing the Bean - * @param name the bound name - * @param nameCtx unused + * @param obj The reference object describing the Bean + * @param name the bound name + * @param nameCtx unused * @param environment unused + * * @return the object instance + * * @throws NamingException if an error occur creating the instance */ @Override @@ -92,7 +93,7 @@ } else { beanClass = Class.forName(beanClassName); } - } catch(ClassNotFoundException cnfe) { + } catch (ClassNotFoundException cnfe) { NamingException ne = new NamingException(sm.getString("beanFactory.classNotFound", beanClassName)); ne.initCause(cnfe); throw ne; @@ -117,14 +118,12 @@ ra = e.nextElement(); String propName = ra.getType(); - if (propName.equals(Constants.FACTORY) || - propName.equals("scope") || propName.equals("auth") || - propName.equals("forceString") || - propName.equals("singleton")) { + if (propName.equals(Constants.FACTORY) || propName.equals("scope") || propName.equals("auth") || + propName.equals("forceString") || propName.equals("singleton")) { continue; } - value = (String)ra.getContent(); + value = (String) ra.getContent(); Object[] valueArray = new Object[1]; @@ -162,12 +161,12 @@ setProp = bean.getClass().getMethod(setterName, String.class); valueArray[0] = value; } catch (NoSuchMethodException nsme) { - throw new NamingException(sm.getString( - "beanFactory.noStringConversion", propName, propType.getName())); + throw new NamingException(sm.getString("beanFactory.noStringConversion", propName, + propType.getName())); } } else { - throw new NamingException(sm.getString( - "beanFactory.noStringConversion", propName, propType.getName())); + throw new NamingException( + sm.getString("beanFactory.noStringConversion", propName, propType.getName())); } if (setProp != null) { diff -Nru tomcat10-10.1.40/java/org/apache/naming/factory/Constants.java tomcat10-10.1.52/java/org/apache/naming/factory/Constants.java --- tomcat10-10.1.40/java/org/apache/naming/factory/Constants.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/naming/factory/Constants.java 2026-01-23 19:33:36.000000000 +0000 @@ -37,8 +37,7 @@ public static final String DEFAULT_HANDLER_FACTORY = Package + ".HandlerFactory"; - public static final String DBCP_DATASOURCE_FACTORY = - "org.apache.tomcat.dbcp.dbcp2.BasicDataSourceFactory"; + public static final String DBCP_DATASOURCE_FACTORY = "org.apache.tomcat.dbcp.dbcp2.BasicDataSourceFactory"; public static final String OPENEJB_EJB_FACTORY = Package + ".OpenEjbFactory"; diff -Nru tomcat10-10.1.40/java/org/apache/naming/factory/DataSourceLinkFactory.java tomcat10-10.1.52/java/org/apache/naming/factory/DataSourceLinkFactory.java --- tomcat10-10.1.40/java/org/apache/naming/factory/DataSourceLinkFactory.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/naming/factory/DataSourceLinkFactory.java 2026-01-23 19:33:36.000000000 +0000 @@ -31,10 +31,10 @@ import javax.sql.DataSource; - /** - *

        Object factory for resource links for shared data sources.

        - * + *

        + * Object factory for resource links for shared data sources. + *

        */ public class DataSourceLinkFactory extends ResourceLinkFactory { @@ -46,14 +46,15 @@ @Override public Object getObjectInstance(Object obj, Name name, Context nameCtx, Hashtable environment) - throws NamingException { + throws NamingException { Object result = super.getObjectInstance(obj, name, nameCtx, environment); // Can we process this request? - if (result!=null) { + if (result != null) { Reference ref = (Reference) obj; RefAddr userAttr = ref.get("username"); RefAddr passAttr = ref.get("password"); - if (userAttr != null && passAttr != null && userAttr.getContent() != null && passAttr.getContent() != null) { + if (userAttr != null && passAttr != null && userAttr.getContent() != null && + passAttr.getContent() != null) { result = wrapDataSource(result, userAttr.getContent().toString(), passAttr.getContent().toString()); } } @@ -62,13 +63,12 @@ protected Object wrapDataSource(Object datasource, String username, String password) throws NamingException { try { - DataSourceHandler handler = - new DataSourceHandler((DataSource)datasource, username, password); - return Proxy.newProxyInstance(datasource.getClass().getClassLoader(), - datasource.getClass().getInterfaces(), handler); - }catch (Exception x) { - if (x instanceof InvocationTargetException) { - Throwable cause = x.getCause(); + DataSourceHandler handler = new DataSourceHandler((DataSource) datasource, username, password); + return Proxy.newProxyInstance(datasource.getClass().getClassLoader(), datasource.getClass().getInterfaces(), + handler); + } catch (Exception e) { + if (e instanceof InvocationTargetException) { + Throwable cause = e.getCause(); if (cause instanceof ThreadDeath) { throw (ThreadDeath) cause; } @@ -76,22 +76,22 @@ throw (VirtualMachineError) cause; } if (cause instanceof Exception) { - x = (Exception) cause; + e = (Exception) cause; } } - if (x instanceof NamingException) { - throw (NamingException)x; + if (e instanceof NamingException) { + throw (NamingException) e; } else { - NamingException nx = new NamingException(x.getMessage()); - nx.initCause(x); + NamingException nx = new NamingException(e.getMessage()); + nx.initCause(e); throw nx; } } } /** - * Simple wrapper class that will allow a user to configure a ResourceLink for a data source - * so that when {@link javax.sql.DataSource#getConnection()} is called, it will invoke + * Simple wrapper class that will allow a user to configure a ResourceLink for a data source so that when + * {@link javax.sql.DataSource#getConnection()} is called, it will invoke * {@link javax.sql.DataSource#getConnection(String, String)} with the preconfigured username and password. */ public static class DataSourceHandler implements InvocationHandler { @@ -99,6 +99,7 @@ private final String username; private final String password; private final Method getConnection; + public DataSourceHandler(DataSource ds, String username, String password) throws Exception { this.ds = ds; this.username = username; @@ -109,17 +110,16 @@ @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { - if ("getConnection".equals(method.getName()) && (args==null || args.length==0)) { - args = new String[] {username,password}; + if ("getConnection".equals(method.getName()) && (args == null || args.length == 0)) { + args = new String[] { username, password }; method = getConnection; } else if ("unwrap".equals(method.getName())) { - return unwrap((Class)args[0]); + return unwrap((Class) args[0]); } try { - return method.invoke(ds,args); - }catch (Throwable t) { - if (t instanceof InvocationTargetException - && t.getCause() != null) { + return method.invoke(ds, args); + } catch (Throwable t) { + if (t instanceof InvocationTargetException && t.getCause() != null) { throw t.getCause(); } else { throw t; @@ -138,7 +138,5 @@ } - - } diff -Nru tomcat10-10.1.40/java/org/apache/naming/factory/EjbFactory.java tomcat10-10.1.52/java/org/apache/naming/factory/EjbFactory.java --- tomcat10-10.1.40/java/org/apache/naming/factory/EjbFactory.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/naming/factory/EjbFactory.java 2026-01-23 19:33:36.000000000 +0000 @@ -27,8 +27,6 @@ /** * Object factory for EJBs. - * - * @author Remy Maucherat */ public class EjbFactory extends FactoryBase { @@ -43,12 +41,10 @@ protected ObjectFactory getDefaultFactory(Reference ref) throws NamingException { ObjectFactory factory; - String javaxEjbFactoryClassName = System.getProperty( - "jakarta.ejb.Factory", Constants.OPENEJB_EJB_FACTORY); + String javaxEjbFactoryClassName = System.getProperty("jakarta.ejb.Factory", Constants.OPENEJB_EJB_FACTORY); try { - factory = (ObjectFactory) - Class.forName(javaxEjbFactoryClassName).getConstructor().newInstance(); - } catch(Throwable t) { + factory = (ObjectFactory) Class.forName(javaxEjbFactoryClassName).getConstructor().newInstance(); + } catch (Throwable t) { if (t instanceof NamingException) { throw (NamingException) t; } diff -Nru tomcat10-10.1.40/java/org/apache/naming/factory/FactoryBase.java tomcat10-10.1.52/java/org/apache/naming/factory/FactoryBase.java --- tomcat10-10.1.40/java/org/apache/naming/factory/FactoryBase.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/naming/factory/FactoryBase.java 2026-01-23 19:33:36.000000000 +0000 @@ -28,16 +28,16 @@ import org.apache.naming.StringManager; /** - * Abstract base class that provides common functionality required by - * subclasses. This class exists primarily to reduce code duplication. + * Abstract base class that provides common functionality required by subclasses. This class exists primarily to reduce + * code duplication. */ public abstract class FactoryBase implements ObjectFactory { private static final StringManager sm = StringManager.getManager(FactoryBase.class); @Override - public final Object getObjectInstance(Object obj, Name name, Context nameCtx, - Hashtable environment) throws Exception { + public final Object getObjectInstance(Object obj, Name name, Context nameCtx, Hashtable environment) + throws Exception { if (isReferenceTypeSupported(obj)) { Reference ref = (Reference) obj; @@ -61,14 +61,14 @@ } else { factoryClass = Class.forName(factoryClassName); } - } catch(ClassNotFoundException e) { + } catch (ClassNotFoundException e) { NamingException ex = new NamingException(sm.getString("factoryBase.factoryClassError")); ex.initCause(e); throw ex; } try { factory = (ObjectFactory) factoryClass.getConstructor().newInstance(); - } catch(Throwable t) { + } catch (Throwable t) { if (t instanceof NamingException) { throw (NamingException) t; } @@ -99,37 +99,33 @@ /** - * Determines if this factory supports processing the provided reference - * object. + * Determines if this factory supports processing the provided reference object. * - * @param obj The object to be processed + * @param obj The object to be processed * - * @return true if this factory can process the object, - * otherwise false + * @return true if this factory can process the object, otherwise false */ protected abstract boolean isReferenceTypeSupported(Object obj); /** - * If a default factory is available for the given reference type, create - * the default factory. + * If a default factory is available for the given reference type, create the default factory. * - * @param ref The reference object to be processed + * @param ref The reference object to be processed * - * @return The default factory for the given reference object or - * null if no default factory exists. + * @return The default factory for the given reference object or null if no default factory exists. * - * @throws NamingException If the default factory cannot be created + * @throws NamingException If the default factory cannot be created */ - protected abstract ObjectFactory getDefaultFactory(Reference ref) - throws NamingException; + protected abstract ObjectFactory getDefaultFactory(Reference ref) throws NamingException; /** * If this reference is a link to another JNDI object, obtain that object. * - * @param ref The reference object to be processed + * @param ref The reference object to be processed + * + * @return The linked object or null if linked objects are not supported by or not configured for this + * reference object * - * @return The linked object or null if linked objects are - * not supported by or not configured for this reference object * @throws NamingException Error accessing linked object */ protected abstract Object getLinked(Reference ref) throws NamingException; diff -Nru tomcat10-10.1.40/java/org/apache/naming/factory/LookupFactory.java tomcat10-10.1.52/java/org/apache/naming/factory/LookupFactory.java --- tomcat10-10.1.40/java/org/apache/naming/factory/LookupFactory.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/naming/factory/LookupFactory.java 2026-01-23 19:33:36.000000000 +0000 @@ -25,7 +25,6 @@ import javax.naming.Name; import javax.naming.NamingException; import javax.naming.RefAddr; -import javax.naming.Reference; import javax.naming.spi.ObjectFactory; import org.apache.juli.logging.Log; @@ -46,22 +45,24 @@ /** * Create a new Resource env instance. * - * @param obj The reference object describing the DataSource - * @param name the bound name - * @param nameCtx unused + * @param obj The reference object describing the DataSource + * @param name the bound name + * @param nameCtx unused * @param environment unused + * * @return the object instance + * * @throws Exception if an error occur creating the instance */ @Override - public Object getObjectInstance(Object obj, Name name, Context nameCtx, - Hashtable environment) throws Exception { + public Object getObjectInstance(Object obj, Name name, Context nameCtx, Hashtable environment) + throws Exception { String lookupName = null; Object result = null; if (obj instanceof LookupRef) { - Reference ref = (Reference) obj; + LookupRef ref = (LookupRef) obj; ObjectFactory factory = null; RefAddr lookupNameRefAddr = ref.get(LookupRef.LOOKUP_NAME); if (lookupNameRefAddr != null) { @@ -88,8 +89,7 @@ try { factoryClass = tcl.loadClass(factoryClassName); } catch (ClassNotFoundException e) { - NamingException ex = new NamingException( - sm.getString("lookupFactory.loadFailed")); + NamingException ex = new NamingException(sm.getString("lookupFactory.loadFailed")); ex.initCause(e); throw ex; } @@ -97,8 +97,7 @@ try { factoryClass = Class.forName(factoryClassName); } catch (ClassNotFoundException e) { - NamingException ex = new NamingException( - sm.getString("lookupFactory.loadFailed")); + NamingException ex = new NamingException(sm.getString("lookupFactory.loadFailed")); ex.initCause(e); throw ex; } @@ -107,8 +106,7 @@ try { factory = (ObjectFactory) factoryClass.getConstructor().newInstance(); } catch (Throwable t) { - NamingException ex = new NamingException( - sm.getString("lookupFactory.createFailed")); + NamingException ex = new NamingException(sm.getString("lookupFactory.createFailed")); ex.initCause(t); throw ex; } @@ -127,8 +125,8 @@ Class clazz = Class.forName(ref.getClassName()); if (result != null && !clazz.isAssignableFrom(result.getClass())) { - String msg = sm.getString("lookupFactory.typeMismatch", - name, ref.getClassName(), lookupName, result.getClass().getName()); + String msg = sm.getString("lookupFactory.typeMismatch", name, ref.getClassName(), lookupName, + result.getClass().getName()); NamingException ne = new NamingException(msg); log.warn(msg, ne); // Close the resource we no longer need if we know how to do so diff -Nru tomcat10-10.1.40/java/org/apache/naming/factory/MailSessionFactory.java tomcat10-10.1.52/java/org/apache/naming/factory/MailSessionFactory.java --- tomcat10-10.1.40/java/org/apache/naming/factory/MailSessionFactory.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/naming/factory/MailSessionFactory.java 2026-01-23 19:33:36.000000000 +0000 @@ -33,19 +33,20 @@ import jakarta.mail.Session; /** - *

        Factory class that creates a JNDI named JavaMail Session factory, - * which can be used for managing inbound and outbound electronic mail - * messages via JavaMail APIs. All messaging environment properties - * described in the JavaMail Specification may be passed to the Session - * factory; however the following properties are the most commonly used:

        + *

        + * Factory class that creates a JNDI named JavaMail Session factory, which can be used for managing inbound and outbound + * electronic mail messages via JavaMail APIs. All messaging environment properties described in the JavaMail + * Specification may be passed to the Session factory; however the following properties are the most commonly used: + *

        *
          - *
        • mail.smtp.host - Hostname for outbound transport - * connections. Defaults to localhost if not specified.
        • + *
        • mail.smtp.host - Hostname for outbound transport connections. Defaults to localhost + * if not specified.
        • *
        + *

        + * This factory can be configured in a <Context> element in your conf/server.xml + * configuration file. An example of factory configuration is: + *

        * - *

        This factory can be configured in a - * <Context> element in your conf/server.xml - * configuration file. An example of factory configuration is:

        *
          * <Resource name="mail/smtp"
          *           auth="CONTAINER"
        @@ -53,8 +54,6 @@
          *           mail.smtp.host="mail.mycompany.com"
          *           />
          * 
        - * - * @author Craig R. McClanahan */ public class MailSessionFactory implements ObjectFactory { @@ -66,8 +65,7 @@ @Override - public Object getObjectInstance(Object refObj, Name name, Context context, - Hashtable env) throws Exception { + public Object getObjectInstance(Object refObj, Name name, Context context, Hashtable env) throws Exception { // Return null if we cannot create an object of the requested type final Reference ref = (Reference) refObj; @@ -107,25 +105,23 @@ Authenticator auth = null; if (password != null) { String user = props.getProperty("mail.smtp.user"); - if(user == null) { + if (user == null) { user = props.getProperty("mail.user"); } - if(user != null) { + if (user != null) { final PasswordAuthentication pa = new PasswordAuthentication(user, password); auth = new Authenticator() { - @Override - protected PasswordAuthentication getPasswordAuthentication() { - return pa; - } - }; + @Override + protected PasswordAuthentication getPasswordAuthentication() { + return pa; + } + }; } } // Create and return the new Session object - Session session = Session.getInstance(props, auth); - return session; - + return Session.getInstance(props, auth); }); } } diff -Nru tomcat10-10.1.40/java/org/apache/naming/factory/OpenEjbFactory.java tomcat10-10.1.52/java/org/apache/naming/factory/OpenEjbFactory.java --- tomcat10-10.1.40/java/org/apache/naming/factory/OpenEjbFactory.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/naming/factory/OpenEjbFactory.java 2026-01-23 19:33:36.000000000 +0000 @@ -23,50 +23,37 @@ import javax.naming.InitialContext; import javax.naming.Name; import javax.naming.RefAddr; -import javax.naming.Reference; import javax.naming.spi.ObjectFactory; import org.apache.naming.EjbRef; /** * Object factory for EJBs. - * - * @author Jacek Laskowski - * @author Remy Maucherat */ public class OpenEjbFactory implements ObjectFactory { - - // -------------------------------------------------------------- Constants - - - protected static final String DEFAULT_OPENEJB_FACTORY = - "org.openejb.client.LocalInitialContextFactory"; - - - // -------------------------------------------------- ObjectFactory Methods - + protected static final String DEFAULT_OPENEJB_FACTORY = "org.openejb.client.LocalInitialContextFactory"; /** * Create a new EJB instance using OpenEJB. * - * @param obj The reference object describing the DataSource - * @param name the bound name - * @param nameCtx unused + * @param obj The reference object describing the DataSource + * @param name the bound name + * @param nameCtx unused * @param environment unused + * * @return the object instance + * * @throws Exception if an error occur creating the instance */ @Override - public Object getObjectInstance(Object obj, Name name, Context nameCtx, - Hashtable environment) - throws Exception { + public Object getObjectInstance(Object obj, Name name, Context nameCtx, Hashtable environment) + throws Exception { Object beanObj = null; if (obj instanceof EjbRef) { - - Reference ref = (Reference) obj; + EjbRef ref = (EjbRef) obj; String factory = DEFAULT_OPENEJB_FACTORY; RefAddr factoryRefAddr = ref.get("openejb.factory"); @@ -83,12 +70,8 @@ String ejbLink = linkRefAddr.getContent().toString(); beanObj = (new InitialContext(env)).lookup(ejbLink); } - } return beanObj; - } - - } diff -Nru tomcat10-10.1.40/java/org/apache/naming/factory/ResourceEnvFactory.java tomcat10-10.1.52/java/org/apache/naming/factory/ResourceEnvFactory.java --- tomcat10-10.1.40/java/org/apache/naming/factory/ResourceEnvFactory.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/naming/factory/ResourceEnvFactory.java 2026-01-23 19:33:36.000000000 +0000 @@ -23,8 +23,6 @@ /** * Object factory for Resources env. - * - * @author Remy Maucherat */ public class ResourceEnvFactory extends FactoryBase { diff -Nru tomcat10-10.1.40/java/org/apache/naming/factory/ResourceFactory.java tomcat10-10.1.52/java/org/apache/naming/factory/ResourceFactory.java --- tomcat10-10.1.40/java/org/apache/naming/factory/ResourceFactory.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/naming/factory/ResourceFactory.java 2026-01-23 19:33:36.000000000 +0000 @@ -25,8 +25,6 @@ /** * Object factory for Resources. - * - * @author Remy Maucherat */ public class ResourceFactory extends FactoryBase { @@ -44,11 +42,10 @@ if (ref.getClassName().equals("javax.sql.DataSource")) { String javaxSqlDataSourceFactoryClassName = - System.getProperty("javax.sql.DataSource.Factory", - Constants.DBCP_DATASOURCE_FACTORY); + System.getProperty("javax.sql.DataSource.Factory", Constants.DBCP_DATASOURCE_FACTORY); try { - factory = (ObjectFactory) Class.forName( - javaxSqlDataSourceFactoryClassName).getConstructor().newInstance(); + factory = (ObjectFactory) Class.forName(javaxSqlDataSourceFactoryClassName).getConstructor() + .newInstance(); } catch (Exception e) { NamingException ex = new NamingException(sm.getString("resourceFactory.factoryCreationError")); ex.initCause(e); @@ -56,12 +53,11 @@ } } else if (ref.getClassName().equals("jakarta.mail.Session")) { String javaxMailSessionFactoryClassName = - System.getProperty("jakarta.mail.Session.Factory", - "org.apache.naming.factory.MailSessionFactory"); + System.getProperty("jakarta.mail.Session.Factory", "org.apache.naming.factory.MailSessionFactory"); try { - factory = (ObjectFactory) Class.forName( - javaxMailSessionFactoryClassName).getConstructor().newInstance(); - } catch(Throwable t) { + factory = + (ObjectFactory) Class.forName(javaxMailSessionFactoryClassName).getConstructor().newInstance(); + } catch (Throwable t) { if (t instanceof NamingException) { throw (NamingException) t; } diff -Nru tomcat10-10.1.40/java/org/apache/naming/factory/ResourceLinkFactory.java tomcat10-10.1.52/java/org/apache/naming/factory/ResourceLinkFactory.java --- tomcat10-10.1.40/java/org/apache/naming/factory/ResourceLinkFactory.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/naming/factory/ResourceLinkFactory.java 2026-01-23 19:33:36.000000000 +0000 @@ -25,16 +25,15 @@ import javax.naming.Name; import javax.naming.NamingException; import javax.naming.RefAddr; -import javax.naming.Reference; import javax.naming.spi.ObjectFactory; import org.apache.naming.ResourceLinkRef; import org.apache.naming.StringManager; /** - *

        Object factory for resource links.

        - * - * @author Remy Maucherat + *

        + * Object factory for resource links. + *

        */ public class ResourceLinkFactory implements ObjectFactory { @@ -47,8 +46,7 @@ */ private static Context globalContext = null; - private static final Map> globalResourceRegistrations = - new ConcurrentHashMap<>(); + private static final Map> globalResourceRegistrations = new ConcurrentHashMap<>(); // --------------------------------------------------------- Public Methods @@ -60,15 +58,13 @@ public static void setGlobalContext(Context newGlobalContext) { SecurityManager sm = System.getSecurityManager(); if (sm != null) { - sm.checkPermission(new RuntimePermission( - ResourceLinkFactory.class.getName() + ".setGlobalContext")); + sm.checkPermission(new RuntimePermission(ResourceLinkFactory.class.getName() + ".setGlobalContext")); } globalContext = newGlobalContext; } - public static void registerGlobalResourceAccess(Context globalContext, String localName, - String globalName) { + public static void registerGlobalResourceAccess(Context globalContext, String localName, String globalName) { validateGlobalContext(globalContext); ClassLoader cl = Thread.currentThread().getContextClassLoader(); // Web application initialization is single threaded so this is @@ -95,8 +91,7 @@ private static void validateGlobalContext(Context globalContext) { - if (ResourceLinkFactory.globalContext != null && - ResourceLinkFactory.globalContext != globalContext) { + if (ResourceLinkFactory.globalContext != null && ResourceLinkFactory.globalContext != globalContext) { throw new SecurityException(sm.getString("resourceLinkFactory.invalidGlobalContext")); } } @@ -120,22 +115,24 @@ /** * Create a new resource instance. * - * @param name the bound name - * @param nameCtx unused + * @param name the bound name + * @param nameCtx unused * @param environment unused + * * @return the object instance + * * @throws NamingException if an error occur creating the instance */ @Override - public Object getObjectInstance(Object obj, Name name, Context nameCtx, - Hashtable environment) throws NamingException { + public Object getObjectInstance(Object obj, Name name, Context nameCtx, Hashtable environment) + throws NamingException { if (!(obj instanceof ResourceLinkRef)) { return null; } // Can we process this request? - Reference ref = (Reference) obj; + ResourceLinkRef ref = (ResourceLinkRef) obj; // Read the global ref addr String globalName; @@ -151,19 +148,18 @@ // Check the expected type String expectedClassName = ref.getClassName(); if (expectedClassName == null) { - throw new IllegalArgumentException( - sm.getString("resourceLinkFactory.nullType", name, globalName)); + throw new IllegalArgumentException(sm.getString("resourceLinkFactory.nullType", name, globalName)); } try { - Class expectedClazz = Class.forName( - expectedClassName, true, Thread.currentThread().getContextClassLoader()); + Class expectedClazz = + Class.forName(expectedClassName, true, Thread.currentThread().getContextClassLoader()); if (!expectedClazz.isAssignableFrom(result.getClass())) { - throw new IllegalArgumentException(sm.getString("resourceLinkFactory.wrongType", - name, globalName, expectedClassName, result.getClass().getName())); + throw new IllegalArgumentException(sm.getString("resourceLinkFactory.wrongType", name, globalName, + expectedClassName, result.getClass().getName())); } } catch (ClassNotFoundException e) { - throw new IllegalArgumentException(sm.getString("resourceLinkFactory.unknownType", - name, globalName, expectedClassName), e); + throw new IllegalArgumentException( + sm.getString("resourceLinkFactory.unknownType", name, globalName, expectedClassName), e); } return result; } diff -Nru tomcat10-10.1.40/java/org/apache/naming/factory/SendMailFactory.java tomcat10-10.1.52/java/org/apache/naming/factory/SendMailFactory.java --- tomcat10-10.1.40/java/org/apache/naming/factory/SendMailFactory.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/naming/factory/SendMailFactory.java 2026-01-23 19:33:36.000000000 +0000 @@ -33,14 +33,16 @@ import jakarta.mail.internet.MimeMessage; import jakarta.mail.internet.MimePartDataSource; +import org.apache.tomcat.util.ExceptionUtils; + /** - * Factory class that creates a JNDI named javamail MimePartDataSource - * object which can be used for sending email using SMTP. + * Factory class that creates a JNDI named javamail MimePartDataSource object which can be used for sending email using + * SMTP. *

        - * Can be configured in the Context scope - * of your server.xml configuration file. + * Can be configured in the Context scope of your server.xml configuration file. *

        * Example: + * *

          * <Resource name="mail/send"
          *           auth="CONTAINER"
        @@ -54,58 +56,52 @@
          *           mail.smtp.dsn.ret="FULL"
          *           />
          * 
        - * - * @author Glenn Nielsen Rich Catlett */ - -public class SendMailFactory implements ObjectFactory -{ +public class SendMailFactory implements ObjectFactory { // The class name for the javamail MimeMessageDataSource - protected static final String DataSourceClassName = - "jakarta.mail.internet.MimePartDataSource"; + protected static final String DataSourceClassName = "jakarta.mail.internet.MimePartDataSource"; @Override - public Object getObjectInstance(Object refObj, Name name, Context ctx, - Hashtable env) throws Exception { - final Reference ref = (Reference)refObj; + public Object getObjectInstance(Object refObj, Name name, Context ctx, Hashtable env) throws Exception { + final Reference ref = (Reference) refObj; // Creation of the DataSource is wrapped inside a doPrivileged // so that javamail can read its default properties without // throwing Security Exceptions if (ref.getClassName().equals(DataSourceClassName)) { - return AccessController.doPrivileged( - (PrivilegedAction) () -> { - // set up the smtp session that will send the message - Properties props = new Properties(); - // enumeration of all refaddr - Enumeration list = ref.getAll(); - // current refaddr to be set - RefAddr refaddr; - // set transport to smtp - props.put("mail.transport.protocol", "smtp"); - - while (list.hasMoreElements()) { - refaddr = list.nextElement(); - - // set property - props.put(refaddr.getType(), refaddr.getContent()); - } - MimeMessage message = new MimeMessage( - Session.getInstance(props)); - try { - RefAddr fromAddr = ref.get("mail.from"); - String from = null; - if (fromAddr != null) { - from = (String) fromAddr.getContent(); - } - if (from != null) { - message.setFrom(new InternetAddress(from)); - } - message.setSubject(""); - } catch (Exception e) {/*Ignore*/} - MimePartDataSource mds = new MimePartDataSource(message); - return mds; - }); + return AccessController.doPrivileged((PrivilegedAction) () -> { + // set up the smtp session that will send the message + Properties props = new Properties(); + // enumeration of all refaddr + Enumeration list = ref.getAll(); + // current refaddr to be set + RefAddr refaddr; + // set transport to smtp + props.put("mail.transport.protocol", "smtp"); + + while (list.hasMoreElements()) { + refaddr = list.nextElement(); + + // set property + props.put(refaddr.getType(), refaddr.getContent()); + } + MimeMessage message = new MimeMessage(Session.getInstance(props)); + try { + RefAddr fromAddr = ref.get("mail.from"); + String from = null; + if (fromAddr != null) { + from = (String) fromAddr.getContent(); + } + if (from != null) { + message.setFrom(new InternetAddress(from)); + } + message.setSubject(""); + } catch (Throwable t) { + ExceptionUtils.handleThrowable(t); + // Otherwise ignore + } + return new MimePartDataSource(message); + }); } else { // We can't create an instance of the DataSource return null; } diff -Nru tomcat10-10.1.40/java/org/apache/naming/factory/TransactionFactory.java tomcat10-10.1.52/java/org/apache/naming/factory/TransactionFactory.java --- tomcat10-10.1.40/java/org/apache/naming/factory/TransactionFactory.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/naming/factory/TransactionFactory.java 2026-01-23 19:33:36.000000000 +0000 @@ -23,8 +23,6 @@ /** * Object factory for User transactions. - * - * @author Remy Maucherat */ public class TransactionFactory extends FactoryBase { diff -Nru tomcat10-10.1.40/java/org/apache/naming/factory/webservices/ServiceProxy.java tomcat10-10.1.52/java/org/apache/naming/factory/webservices/ServiceProxy.java --- tomcat10-10.1.40/java/org/apache/naming/factory/webservices/ServiceProxy.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/naming/factory/webservices/ServiceProxy.java 2026-01-23 19:33:36.000000000 +0000 @@ -31,16 +31,13 @@ /** * Object proxy for Web Services. - * - * @author Fabien Carrion */ public class ServiceProxy implements InvocationHandler { private static final StringManager sm = StringManager.getManager(ServiceProxy.class); /** - * Service object. - * used for delegation + * Service object. used for delegation */ private final Service service; @@ -61,14 +58,16 @@ /** * Constructs a new ServiceProxy wrapping given Service instance. + * * @param service the wrapped Service instance + * * @throws ServiceException should be never thrown */ public ServiceProxy(Service service) throws ServiceException { this.service = service; try { - portQNameClass = Service.class.getDeclaredMethod("getPort", new Class[]{QName.class, Class.class}); - portClass = Service.class.getDeclaredMethod("getPort", new Class[]{Class.class}); + portQNameClass = Service.class.getDeclaredMethod("getPort", new Class[] { QName.class, Class.class }); + portClass = Service.class.getDeclaredMethod("getPort", new Class[] { Class.class }); } catch (Exception e) { throw new ServiceException(e); } @@ -78,8 +77,7 @@ * @see InvocationHandler#invoke(Object, Method, Object[]) */ @Override - public Object invoke(Object proxy, Method method, Object[] args) - throws Throwable { + public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { if (portQNameClass.equals(method)) { return getProxyPortQNameClass(args); @@ -98,7 +96,9 @@ /** * @param args Method call arguments + * * @return Returns the correct Port + * * @throws ServiceException if port's QName is an unknown Port (not defined in WSDL). */ private Object getProxyPortQNameClass(Object[] args) throws ServiceException { @@ -106,7 +106,8 @@ String nameString = name.getLocalPart(); Class serviceendpointClass = (Class) args[1]; - for (@SuppressWarnings("unchecked") Iterator ports = service.getPorts(); ports.hasNext();) { + for (@SuppressWarnings("unchecked") + Iterator ports = service.getPorts(); ports.hasNext();) { QName portName = ports.next(); String portnameString = portName.getLocalPart(); if (portnameString.equals(nameString)) { @@ -127,7 +128,9 @@ /** * @param args Method call arguments + * * @return Returns the correct Port + * * @throws ServiceException if port's QName is an unknown Port */ private Remote getProxyPortClass(Object[] args) throws ServiceException { diff -Nru tomcat10-10.1.40/java/org/apache/naming/factory/webservices/ServiceRefFactory.java tomcat10-10.1.52/java/org/apache/naming/factory/webservices/ServiceRefFactory.java --- tomcat10-10.1.40/java/org/apache/naming/factory/webservices/ServiceRefFactory.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/naming/factory/webservices/ServiceRefFactory.java 2026-01-23 19:33:36.000000000 +0000 @@ -53,8 +53,6 @@ /** * Object factory for Web Services. - * - * @author Fabien Carrion */ public class ServiceRefFactory implements ObjectFactory { @@ -117,7 +115,7 @@ } try { if (wsdlRefAddr == null) { - service = factory.createService( serviceQname ); + service = factory.createService(serviceQname); } else { service = factory.createService(new URI(wsdlRefAddr).toURL(), serviceQname); } @@ -130,7 +128,7 @@ // Loading service Interface try { serviceInterfaceClass = tcl.loadClass(serviceInterface); - } catch(ClassNotFoundException e) { + } catch (ClassNotFoundException e) { NamingException ex = new NamingException("Could not load service Interface"); ex.initCause(e); throw ex; @@ -145,8 +143,8 @@ } service = factory.loadService(serviceInterfaceClass); } else { - service = factory.loadService( - new URI(wsdlRefAddr).toURL(), serviceInterfaceClass, new Properties()); + service = factory.loadService(new URI(wsdlRefAddr).toURL(), serviceInterfaceClass, + new Properties()); } } catch (Exception e) { NamingException ex = new NamingException("Could not create service"); @@ -174,7 +172,7 @@ for (String portName : ports.keySet()) { Port port = wsdlservice.getPort(portName); String endpoint = getSOAPLocation(port); - m.invoke(service, new Object[]{port.getName(), endpoint}); + m.invoke(service, new Object[] { port.getName(), endpoint }); portComponentRef.put(endpoint, new QName(port.getName())); } } catch (Exception e) { @@ -242,7 +240,7 @@ Class handlerClass = null; try { handlerClass = tcl.loadClass((String) tmp.getContent()); - } catch(ClassNotFoundException e) { + } catch (ClassNotFoundException e) { break; } @@ -289,12 +287,11 @@ if (!portNames.isEmpty()) { for (String portName : portNames) { - initHandlerChain(new QName(portName), handlerRegistry, - handlerInfo, soaproles); + initHandlerChain(new QName(portName), handlerRegistry, handlerInfo, soaproles); } } else { Enumeration e = portComponentRef.elements(); - while(e.hasMoreElements()) { + while (e.hasMoreElements()) { initHandlerChain(e.nextElement(), handlerRegistry, handlerInfo, soaproles); } } @@ -311,6 +308,7 @@ /** * @param port analyzed port + * * @return Returns the endpoint URL of the given Port */ private String getSOAPLocation(Port port) { @@ -327,8 +325,8 @@ } - private void initHandlerChain(QName portName, HandlerRegistry handlerRegistry, - HandlerInfo handlerInfo, List soaprolesToAdd) { + private void initHandlerChain(QName portName, HandlerRegistry handlerRegistry, HandlerInfo handlerInfo, + List soaprolesToAdd) { HandlerChain handlerChain = (HandlerChain) handlerRegistry.getHandlerChain(portName); @SuppressWarnings("unchecked") // Can't change the API Iterator iter = handlerChain.iterator(); @@ -337,13 +335,13 @@ handler.init(handlerInfo); } String[] soaprolesRegistered = handlerChain.getRoles(); - String [] soaproles = new String[soaprolesRegistered.length + soaprolesToAdd.size()]; + String[] soaproles = new String[soaprolesRegistered.length + soaprolesToAdd.size()]; int i; - for (i = 0;i < soaprolesRegistered.length; i++) { + for (i = 0; i < soaprolesRegistered.length; i++) { soaproles[i] = soaprolesRegistered[i]; } for (int j = 0; j < soaprolesToAdd.size(); j++) { - soaproles[i+j] = soaprolesToAdd.get(j); + soaproles[i + j] = soaprolesToAdd.get(j); } handlerChain.setRoles(soaproles); handlerRegistry.setHandlerChain(portName, handlerChain); diff -Nru tomcat10-10.1.40/java/org/apache/naming/java/javaURLContextFactory.java tomcat10-10.1.52/java/org/apache/naming/java/javaURLContextFactory.java --- tomcat10-10.1.40/java/org/apache/naming/java/javaURLContextFactory.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/naming/java/javaURLContextFactory.java 2026-01-23 19:33:36.000000000 +0000 @@ -31,22 +31,15 @@ /** * Context factory for the "java:" namespace. *

        - * Important note : This factory MUST be associated with the "java" URL - * prefix, which can be done by either : + * Important note : This factory MUST be associated with the "java" URL prefix, which can be done by either : *

          - *
        • Adding a - * java.naming.factory.url.pkgs=org.apache.naming property - * to the JNDI properties file
        • - *
        • Setting an environment variable named Context.URL_PKG_PREFIXES with - * its value including the org.apache.naming package name. - * More detail about this can be found in the JNDI documentation : + *
        • Adding a java.naming.factory.url.pkgs=org.apache.naming property to the JNDI properties file
        • + *
        • Setting an environment variable named Context.URL_PKG_PREFIXES with its value including the org.apache.naming + * package name. More detail about this can be found in the JNDI documentation : * {@link javax.naming.spi.NamingManager#getURLContext(String, java.util.Hashtable)}.
        • *
        - * - * @author Remy Maucherat */ -public class javaURLContextFactory - implements ObjectFactory, InitialContextFactory { +public class javaURLContextFactory implements ObjectFactory, InitialContextFactory { // ----------------------------------------------------------- Constructors @@ -75,22 +68,22 @@ /** * Create a new Context's instance. - * @param obj unused - * @param name unused - * @param nameCtx unused + * + * @param obj unused + * @param name unused + * @param nameCtx unused * @param environment the environment used - * @return a selector context if the thread or classloader are bound, and - * null otherwise + * + * @return a selector context if the thread or classloader are bound, and null otherwise + * * @throws NamingException not thrown by this implementationm */ @SuppressWarnings("unchecked") @Override - public Object getObjectInstance(Object obj, Name name, Context nameCtx, - Hashtable environment) - throws NamingException { - if ((ContextBindings.isThreadBound()) || - (ContextBindings.isClassLoaderBound())) { - return new SelectorContext((Hashtable)environment); + public Object getObjectInstance(Object obj, Name name, Context nameCtx, Hashtable environment) + throws NamingException { + if ((ContextBindings.isThreadBound()) || (ContextBindings.isClassLoaderBound())) { + return new SelectorContext((Hashtable) environment); } return null; } @@ -98,28 +91,26 @@ /** * Get a new (writable) initial context. + * * @param environment the environment used - * @return a selector context if the thread or classloader are bound, and - * a shared writable context otherwise + * + * @return a selector context if the thread or classloader are bound, and a shared writable context otherwise + * * @throws NamingException not thrown by this implementationm */ @SuppressWarnings("unchecked") @Override - public Context getInitialContext(Hashtable environment) - throws NamingException { - if (ContextBindings.isThreadBound() || - (ContextBindings.isClassLoaderBound())) { + public Context getInitialContext(Hashtable environment) throws NamingException { + if (ContextBindings.isThreadBound() || (ContextBindings.isClassLoaderBound())) { // Redirect the request to the bound initial context - return new SelectorContext( - (Hashtable)environment, true); + return new SelectorContext((Hashtable) environment, true); } // If the thread is not bound, return a shared writable context if (initialContext == null) { - synchronized(javaURLContextFactory.class) { + synchronized (javaURLContextFactory.class) { if (initialContext == null) { - initialContext = new NamingContext( - (Hashtable)environment, MAIN); + initialContext = new NamingContext((Hashtable) environment, MAIN); } } } diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/ContextBind.java tomcat10-10.1.52/java/org/apache/tomcat/ContextBind.java --- tomcat10-10.1.40/java/org/apache/tomcat/ContextBind.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/ContextBind.java 2026-01-23 19:33:36.000000000 +0000 @@ -19,42 +19,30 @@ public interface ContextBind { /** - * Change the current thread context class loader to the web application - * class loader. If no web application class loader is defined, or if the - * current thread is already using the web application class loader then no - * change will be made. If the class loader is changed and a - * {@link org.apache.catalina.ThreadBindingListener} is configured then - * {@link org.apache.catalina.ThreadBindingListener#bind()} will be called - * after the change has been made. + * Change the current thread context class loader to the web application class loader. If no web application class + * loader is defined, or if the current thread is already using the web application class loader then no change will + * be made. If the class loader is changed and a {@link org.apache.catalina.ThreadBindingListener} is configured + * then {@link org.apache.catalina.ThreadBindingListener#bind()} will be called after the change has been made. * - * @param usePrivilegedAction - * Should a {@link java.security.PrivilegedAction} be used when - * obtaining the current thread context class loader and setting - * the new one? - * @param originalClassLoader - * The current class loader if known to save this method having to - * look it up + * @param usePrivilegedAction Should a {@link java.security.PrivilegedAction} be used when obtaining the current + * thread context class loader and setting the new one? + * @param originalClassLoader The current class loader if known to save this method having to look it up * - * @return If the class loader has been changed by the method it will return - * the thread context class loader in use when the method was - * called. If no change was made then this method returns null. + * @return If the class loader has been changed by the method it will return the thread context class loader in use + * when the method was called. If no change was made then this method returns null. */ ClassLoader bind(boolean usePrivilegedAction, ClassLoader originalClassLoader); /** - * Restore the current thread context class loader to the original class - * loader in used before {@link #bind(boolean, ClassLoader)} was called. If - * no original class loader is passed to this method then no change will be - * made. If the class loader is changed and a - * {@link org.apache.catalina.ThreadBindingListener} is configured then - * {@link org.apache.catalina.ThreadBindingListener#unbind()} will be called - * before the change is made. + * Restore the current thread context class loader to the original class loader in used before + * {@link #bind(boolean, ClassLoader)} was called. If no original class loader is passed to this method then no + * change will be made. If the class loader is changed and a {@link org.apache.catalina.ThreadBindingListener} is + * configured then {@link org.apache.catalina.ThreadBindingListener#unbind()} will be called before the change is + * made. * - * @param usePrivilegedAction - * Should a {@link java.security.PrivilegedAction} be used when - * setting the current thread context class loader? - * @param originalClassLoader - * The class loader to restore as the thread context class loader + * @param usePrivilegedAction Should a {@link java.security.PrivilegedAction} be used when setting the current + * thread context class loader? + * @param originalClassLoader The class loader to restore as the thread context class loader */ void unbind(boolean usePrivilegedAction, ClassLoader originalClassLoader); } diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/InstanceManager.java tomcat10-10.1.52/java/org/apache/tomcat/InstanceManager.java --- tomcat10-10.1.40/java/org/apache/tomcat/InstanceManager.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/InstanceManager.java 2026-01-23 19:33:36.000000000 +0000 @@ -22,28 +22,24 @@ public interface InstanceManager { - Object newInstance(Class clazz) throws IllegalAccessException, InvocationTargetException, - NamingException, InstantiationException, IllegalArgumentException, - NoSuchMethodException, SecurityException; - - Object newInstance(String className) throws IllegalAccessException, InvocationTargetException, - NamingException, InstantiationException, ClassNotFoundException, - IllegalArgumentException, NoSuchMethodException, SecurityException; - - Object newInstance(String fqcn, ClassLoader classLoader) throws IllegalAccessException, - InvocationTargetException, NamingException, InstantiationException, - ClassNotFoundException, IllegalArgumentException, NoSuchMethodException, - SecurityException; + Object newInstance(Class clazz) throws IllegalAccessException, InvocationTargetException, NamingException, + InstantiationException, IllegalArgumentException, NoSuchMethodException, SecurityException; - void newInstance(Object o) - throws IllegalAccessException, InvocationTargetException, NamingException; + Object newInstance(String className) + throws IllegalAccessException, InvocationTargetException, NamingException, InstantiationException, + ClassNotFoundException, IllegalArgumentException, NoSuchMethodException, SecurityException; + + Object newInstance(String fqcn, ClassLoader classLoader) + throws IllegalAccessException, InvocationTargetException, NamingException, InstantiationException, + ClassNotFoundException, IllegalArgumentException, NoSuchMethodException, SecurityException; + + void newInstance(Object o) throws IllegalAccessException, InvocationTargetException, NamingException; void destroyInstance(Object o) throws IllegalAccessException, InvocationTargetException; /** - * Called by the component using the InstanceManager periodically to perform - * any regular maintenance that might be required. By default, this method - * is a NO-OP. + * Called by the component using the InstanceManager periodically to perform any regular maintenance that might be + * required. By default, this method is a NO-OP. */ default void backgroundProcess() { // NO-OP by default diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/InstanceManagerBindings.java tomcat10-10.1.52/java/org/apache/tomcat/InstanceManagerBindings.java --- tomcat10-10.1.40/java/org/apache/tomcat/InstanceManagerBindings.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/InstanceManagerBindings.java 2026-01-23 19:33:36.000000000 +0000 @@ -21,14 +21,16 @@ public final class InstanceManagerBindings { - private static final Map bindings = new ConcurrentHashMap<>(); + private static final Map bindings = new ConcurrentHashMap<>(); public static void bind(ClassLoader classLoader, InstanceManager instanceManager) { bindings.put(classLoader, instanceManager); } + public static void unbind(ClassLoader classLoader) { bindings.remove(classLoader); } + public static InstanceManager get(ClassLoader classLoader) { return bindings.get(classLoader); } diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/InstrumentableClassLoader.java tomcat10-10.1.52/java/org/apache/tomcat/InstrumentableClassLoader.java --- tomcat10-10.1.40/java/org/apache/tomcat/InstrumentableClassLoader.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/InstrumentableClassLoader.java 2026-01-23 19:33:36.000000000 +0000 @@ -19,58 +19,46 @@ import java.lang.instrument.ClassFileTransformer; /** - * Specifies a class loader capable of being decorated with - * {@link ClassFileTransformer}s. These transformers can instrument - * (or weave) the byte code of classes loaded through this class loader - * to alter their behavior. Currently only - * {@link org.apache.catalina.loader.WebappClassLoaderBase} implements this - * interface. This allows web application frameworks or JPA providers - * bundled with a web application to instrument web application classes - * as necessary. + * Specifies a class loader capable of being decorated with {@link ClassFileTransformer}s. These transformers can + * instrument (or weave) the byte code of classes loaded through this class loader to alter their behavior. Currently + * only {@link org.apache.catalina.loader.WebappClassLoaderBase} implements this interface. This allows web application + * frameworks or JPA providers bundled with a web application to instrument web application classes as necessary. *

        - * You should always program against the methods of this interface - * (whether using reflection or otherwise). The methods in - * {@code WebappClassLoaderBase} are protected by the default security - * manager if one is in use. + * You should always program against the methods of this interface (whether using reflection or otherwise). The methods + * in {@code WebappClassLoaderBase} are protected by the default security manager if one is in use. * * @since 8.0, 7.0.64 */ public interface InstrumentableClassLoader { /** - * Adds the specified class file transformer to this class loader. The - * transformer will then be able to instrument the bytecode of any - * classes loaded by this class loader after the invocation of this - * method. + * Adds the specified class file transformer to this class loader. The transformer will then be able to instrument + * the bytecode of any classes loaded by this class loader after the invocation of this method. * * @param transformer The transformer to add to the class loader + * * @throws IllegalArgumentException if the {@literal transformer} is null. */ void addTransformer(ClassFileTransformer transformer); /** - * Removes the specified class file transformer from this class loader. - * It will no longer be able to instrument the byte code of any classes - * loaded by the class loader after the invocation of this method. - * However, any classes already instrumented by this transformer before - * this method call will remain in their instrumented state. + * Removes the specified class file transformer from this class loader. It will no longer be able to instrument the + * byte code of any classes loaded by the class loader after the invocation of this method. However, any classes + * already instrumented by this transformer before this method call will remain in their instrumented state. * * @param transformer The transformer to remove */ void removeTransformer(ClassFileTransformer transformer); /** - * Returns a copy of this class loader without any class file - * transformers. This is a tool often used by Java Persistence API - * providers to inspect entity classes in the absence of any - * instrumentation, something that can't be guaranteed within the - * context of a {@link ClassFileTransformer}'s - * {@link ClassFileTransformer#transform(ClassLoader, String, Class, - * java.security.ProtectionDomain, byte[]) transform} method. + * Returns a copy of this class loader without any class file transformers. This is a tool often used by Java + * Persistence API providers to inspect entity classes in the absence of any instrumentation, something that can't + * be guaranteed within the context of a {@link ClassFileTransformer}'s + * {@link ClassFileTransformer#transform(ClassLoader, String, Class, java.security.ProtectionDomain, byte[]) + * transform} method. *

        - * The returned class loader's resource cache will have been cleared - * so that classes already instrumented will not be retained or - * returned. + * The returned class loader's resource cache will have been cleared so that classes already instrumented will not + * be retained or returned. * * @return the transformer-free copy of this class loader. */ diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/Jar.java tomcat10-10.1.52/java/org/apache/tomcat/Jar.java --- tomcat10-10.1.40/java/org/apache/tomcat/Jar.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/Jar.java 2026-01-23 19:33:36.000000000 +0000 @@ -22,15 +22,12 @@ import java.util.jar.Manifest; /** - * Provides an abstraction for use by the various classes that need to scan - * JARs. The classes provided by the JRE for accessing JARs - * ({@link java.util.jar.JarFile} and {@link java.util.jar.JarInputStream}) have - * significantly different performance characteristics depending on the form of - * the URL used to access the JAR. For file based JAR {@link java.net.URL}s, - * {@link java.util.jar.JarFile} is faster but for non-file based - * {@link java.net.URL}s, {@link java.util.jar.JarFile} creates a copy of the - * JAR in the temporary directory so {@link java.util.jar.JarInputStream} is - * faster. + * Provides an abstraction for use by the various classes that need to scan JARs. The classes provided by the JRE for + * accessing JARs ({@link java.util.jar.JarFile} and {@link java.util.jar.JarInputStream}) have significantly different + * performance characteristics depending on the form of the URL used to access the JAR. For file based JAR + * {@link java.net.URL}s, {@link java.util.jar.JarFile} is faster but for non-file based {@link java.net.URL}s, + * {@link java.util.jar.JarFile} creates a copy of the JAR in the temporary directory so + * {@link java.util.jar.JarInputStream} is faster. */ public interface Jar extends AutoCloseable { @@ -40,12 +37,11 @@ URL getJarFileURL(); /** - * Obtain an {@link InputStream} for a given entry in a JAR. The caller is - * responsible for closing the stream. + * Obtain an {@link InputStream} for a given entry in a JAR. The caller is responsible for closing the stream. * - * @param name Entry to obtain an {@link InputStream} for - * @return An {@link InputStream} for the specified entry or null if - * the entry does not exist + * @param name Entry to obtain an {@link InputStream} for + * + * @return An {@link InputStream} for the specified entry or null if the entry does not exist * * @throws IOException if an I/O error occurs while processing the JAR file */ @@ -54,11 +50,10 @@ /** * Obtain the last modified time for the given resource in the JAR. * - * @param name Entry to obtain the modification time for + * @param name Entry to obtain the modification time for * - * @return The time (in the same format as - * {@link System#currentTimeMillis()}) that the resource was last - * modified. Returns -1 if the entry does not exist + * @return The time (in the same format as {@link System#currentTimeMillis()}) that the resource was last modified. + * Returns -1 if the entry does not exist * * @throws IOException if an I/O error occurs while processing the JAR file */ @@ -67,10 +62,9 @@ /** * Determine if the given resource in present in the JAR. * - * @param name Entry to look for + * @param name Entry to look for * - * @return {@code true} if the entry is present in the JAR, otherwise - * {@code false} + * @return {@code true} if the entry is present in the JAR, otherwise {@code false} * * @throws IOException if an I/O error occurs while processing the JAR file */ @@ -90,26 +84,24 @@ /** * Obtains the name of the current entry. * - * @return The entry name + * @return The entry name */ String getEntryName(); /** * Obtains the input stream for the current entry. * - * @return The input stream - * @throws IOException If the stream cannot be obtained + * @return The input stream + * + * @throws IOException If the stream cannot be obtained */ InputStream getEntryInputStream() throws IOException; /** - * Obtain, in String form, the URL for an entry in this JAR. Note that for - * JARs nested in WAR files, the Tomcat specific war:file:... form will not - * be used, rather the jar:jar:file:... form (that the JRE does not - * understand will be used). Note that this means that any code using these - * URLs will need to understand the jar:jar:file:... form and use the - * {@link org.apache.tomcat.util.scan.JarFactory} to ensure resources are - * accessed correctly. + * Obtain, in String form, the URL for an entry in this JAR. Note that for JARs nested in WAR files, the Tomcat + * specific war:file:... form will not be used, rather the jar:jar:file:... form (that the JRE does not understand + * will be used). Note that this means that any code using these URLs will need to understand the jar:jar:file:... + * form and use the {@link org.apache.tomcat.util.scan.JarFactory} to ensure resources are accessed correctly. * * @param entry The entry to generate the URL for * @@ -127,10 +119,9 @@ Manifest getManifest() throws IOException; /** - * Resets the internal pointer used to track JAR entries to the beginning of - * the JAR. + * Resets the internal pointer used to track JAR entries to the beginning of the JAR. * - * @throws IOException If the pointer cannot be reset + * @throws IOException If the pointer cannot be reset */ void reset() throws IOException; } diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/JarScanFilter.java tomcat10-10.1.52/java/org/apache/tomcat/JarScanFilter.java --- tomcat10-10.1.40/java/org/apache/tomcat/JarScanFilter.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/JarScanFilter.java 2026-01-23 19:33:36.000000000 +0000 @@ -19,18 +19,18 @@ public interface JarScanFilter { /** - * @param jarScanType The type of JAR scan currently being performed - * @param jarName The name of the JAR file (without any path - * information) to be checked to see if it should - * be included in the results or not - * @return true if the JAR should be returned in the results, - * false if it should be excluded + * @param jarScanType The type of JAR scan currently being performed + * @param jarName The name of the JAR file (without any path information) to be checked to see if it should be + * included in the results or not + * + * @return true if the JAR should be returned in the results, false if it should be + * excluded */ boolean check(JarScanType jarScanType, String jarName); /** - * @return true if all of the scans should be skipped which - * can improve startup performance. The default is false. + * @return true if all of the scans should be skipped which can improve startup performance. The + * default is false. */ default boolean isSkipAll() { return false; diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/JarScanner.java tomcat10-10.1.52/java/org/apache/tomcat/JarScanner.java --- tomcat10-10.1.40/java/org/apache/tomcat/JarScanner.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/JarScanner.java 2026-01-23 19:33:36.000000000 +0000 @@ -19,25 +19,21 @@ import jakarta.servlet.ServletContext; /** - * Scans a web application and classloader hierarchy for JAR files. Uses - * include TLD scanning and web-fragment.xml scanning. Uses a call-back - * mechanism so the caller can process each JAR found. + * Scans a web application and classloader hierarchy for JAR files. Uses include TLD scanning and web-fragment.xml + * scanning. Uses a call-back mechanism so the caller can process each JAR found. */ public interface JarScanner { /** - * Scan the provided ServletContext and classloader for JAR files. Each JAR - * file found will be passed to the callback handler to be processed. + * Scan the provided ServletContext and classloader for JAR files. Each JAR file found will be passed to the + * callback handler to be processed. * - * @param scanType The type of JAR scan to perform. This is passed to - * the filter which uses it to determine how to - * filter the results - * @param context The ServletContext - used to locate and access - * WEB-INF/lib - * @param callback The handler to process any JARs found + * @param scanType The type of JAR scan to perform. This is passed to the filter which uses it to determine how to + * filter the results + * @param context The ServletContext - used to locate and access WEB-INF/lib + * @param callback The handler to process any JARs found */ - void scan(JarScanType scanType, ServletContext context, - JarScannerCallback callback); + void scan(JarScanType scanType, ServletContext context, JarScannerCallback callback); JarScanFilter getJarScanFilter(); diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/JarScannerCallback.java tomcat10-10.1.52/java/org/apache/tomcat/JarScannerCallback.java --- tomcat10-10.1.40/java/org/apache/tomcat/JarScannerCallback.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/JarScannerCallback.java 2026-01-23 19:33:36.000000000 +0000 @@ -20,35 +20,31 @@ import java.io.IOException; /** - * This interface is implemented by clients of the {@link JarScanner} to enable - * them to receive notification of a discovered JAR. + * This interface is implemented by clients of the {@link JarScanner} to enable them to receive notification of a + * discovered JAR. */ public interface JarScannerCallback { /** - * A JAR was found and may be accessed for further processing via the - * provided URL connection. The caller is responsible for closing the JAR. + * A JAR was found and may be accessed for further processing via the provided URL connection. The caller is + * responsible for closing the JAR. * * @param jar The JAR to process * @param webappPath The path, if any, to the JAR within the web application - * @param isWebapp Indicates if the JAR was found within a web - * application. If false the JAR should + * @param isWebapp Indicates if the JAR was found within a web application. If false the JAR should * be treated as being provided by the container * * @throws IOException if an I/O error occurs while scanning the JAR */ - void scan(Jar jar, String webappPath, boolean isWebapp) - throws IOException; + void scan(Jar jar, String webappPath, boolean isWebapp) throws IOException; /** - * A directory was found that is to be treated as an unpacked JAR. The - * directory may be accessed for further processing via the provided file. + * A directory was found that is to be treated as an unpacked JAR. The directory may be accessed for further + * processing via the provided file. * * @param file The directory containing the unpacked JAR. - * @param webappPath The path, if any, to the file within the web - * application - * @param isWebapp Indicates if the JAR was found within a web - * application. If false the JAR should + * @param webappPath The path, if any, to the file within the web application + * @param isWebapp Indicates if the JAR was found within a web application. If false the JAR should * be treated as being provided by the container * * @throws IOException if an I/O error occurs while scanning the JAR @@ -56,10 +52,9 @@ void scan(File file, String webappPath, boolean isWebapp) throws IOException; /** - * A directory structure was found within the web application at - * /WEB-INF/classes that should be handled as an unpacked JAR. Note that all - * resource access must be via the ServletContext to ensure that any - * additional resources are visible. + * A directory structure was found within the web application at /WEB-INF/classes that should be handled as an + * unpacked JAR. Note that all resource access must be via the ServletContext to ensure that any additional + * resources are visible. * * @throws IOException if an I/O error occurs while scanning WEB-INF/classes */ diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/SimpleInstanceManager.java tomcat10-10.1.52/java/org/apache/tomcat/SimpleInstanceManager.java --- tomcat10-10.1.40/java/org/apache/tomcat/SimpleInstanceManager.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/SimpleInstanceManager.java 2026-01-23 19:33:36.000000000 +0000 @@ -29,30 +29,28 @@ } @Override - public Object newInstance(Class clazz) throws IllegalAccessException, - InvocationTargetException, NamingException, InstantiationException, NoSuchMethodException { + public Object newInstance(Class clazz) throws IllegalAccessException, InvocationTargetException, NamingException, + InstantiationException, NoSuchMethodException { return prepareInstance(clazz.getConstructor().newInstance()); } @Override - public Object newInstance(String className) throws IllegalAccessException, - InvocationTargetException, NamingException, InstantiationException, - ClassNotFoundException, NoSuchMethodException { + public Object newInstance(String className) throws IllegalAccessException, InvocationTargetException, + NamingException, InstantiationException, ClassNotFoundException, NoSuchMethodException { Class clazz = Thread.currentThread().getContextClassLoader().loadClass(className); return prepareInstance(clazz.getConstructor().newInstance()); } @Override - public Object newInstance(String fqcn, ClassLoader classLoader) throws IllegalAccessException, - InvocationTargetException, NamingException, InstantiationException, - ClassNotFoundException, NoSuchMethodException { + public Object newInstance(String fqcn, ClassLoader classLoader) + throws IllegalAccessException, InvocationTargetException, NamingException, InstantiationException, + ClassNotFoundException, NoSuchMethodException { Class clazz = classLoader.loadClass(fqcn); return prepareInstance(clazz.getConstructor().newInstance()); } @Override - public void newInstance(Object o) throws IllegalAccessException, InvocationTargetException, - NamingException { + public void newInstance(Object o) throws IllegalAccessException, InvocationTargetException, NamingException { // NO-OP } diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/buildutil/CheckEol.java tomcat10-10.1.52/java/org/apache/tomcat/buildutil/CheckEol.java --- tomcat10-10.1.40/java/org/apache/tomcat/buildutil/CheckEol.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/buildutil/CheckEol.java 2026-01-23 19:33:36.000000000 +0000 @@ -31,13 +31,10 @@ import org.apache.tools.ant.types.FileSet; /** - * Ant task that checks that all the files in the given fileset have end-of-line - * delimiters that are appropriate. - * + * Ant task that checks that all the files in the given fileset have end-of-line delimiters that are appropriate. *

        - * The goal is to check whether we have problems with Subversion's svn:eol-style - * property or Git's autocrlf setting when files are committed on one OS and then - * checked on another one. + * The goal is to check whether we have problems with Subversion's svn:eol-style property or Git's autocrlf setting when + * files are committed on one OS and then checked on another one. */ public class CheckEol extends Task { @@ -52,8 +49,8 @@ * * @param fs The fileset to be checked. */ - public void addFileset( FileSet fs ) { - filesets.add( fs ); + public void addFileset(FileSet fs) { + filesets.add(fs); } /** @@ -61,12 +58,12 @@ * * @param mode The line ending mode (either LF or CRLF) */ - public void setMode( String mode ) { - this.mode = Mode.valueOf( mode.toUpperCase(Locale.ENGLISH) ); + public void setMode(String mode) { + this.mode = Mode.valueOf(mode.toUpperCase(Locale.ENGLISH)); } private Mode getMode() { - if ( mode != null ) { + if (mode != null) { return mode; } else { if ("\n".equals(System.lineSeparator())) { @@ -82,14 +79,13 @@ /** * Perform the check * - * @throws BuildException if an error occurs during execution of - * this task. + * @throws BuildException if an error occurs during execution of this task. */ @Override public void execute() throws BuildException { Mode mode = getMode(); - if ( mode == null ) { + if (mode == null) { log("Line ends check skipped, because OS line ends setting is neither LF nor CRLF.", Project.MSG_VERBOSE); return; } @@ -107,25 +103,21 @@ log("Checking line ends in " + files.length + " file(s)"); for (String filename : files) { File file = new File(basedir, filename); - log("Checking file '" + file + "' for correct line ends", - Project.MSG_DEBUG); + log("Checking file '" + file + "' for correct line ends", Project.MSG_DEBUG); try { check(file, errors, mode); - } catch (IOException e) { - throw new BuildException("Could not check file '" - + file.getAbsolutePath() + "'", e); + } catch (IOException ioe) { + throw new BuildException("Could not check file '" + file.getAbsolutePath() + "'", ioe); } count++; } } } if (count > 0) { - log("Done line ends check in " + count + " file(s), " - + errors.size() + " error(s) found."); + log("Done line ends check in " + count + " file(s), " + errors.size() + " error(s) found."); } if (!errors.isEmpty()) { - String message = "The following files have wrong line ends: " - + errors; + String message = "The following files have wrong line ends: " + errors; // We need to explicitly write the message to the log, because // long BuildException messages may be trimmed. E.g. I observed // this problem with Eclipse IDE 3.7. @@ -135,7 +127,8 @@ } private enum Mode { - LF, CRLF + LF, + CRLF } private static class CheckFailure { @@ -156,8 +149,7 @@ } private void check(File file, List errors, Mode mode) throws IOException { - try (FileInputStream fis = new FileInputStream(file); - BufferedInputStream is = new BufferedInputStream(fis)) { + try (FileInputStream fis = new FileInputStream(file); BufferedInputStream is = new BufferedInputStream(fis)) { int line = 1; int prev = -1; int ch; diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/buildutil/MimeTypeMappings.java tomcat10-10.1.52/java/org/apache/tomcat/buildutil/MimeTypeMappings.java --- tomcat10-10.1.40/java/org/apache/tomcat/buildutil/MimeTypeMappings.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/buildutil/MimeTypeMappings.java 2026-01-23 19:33:36.000000000 +0000 @@ -49,7 +49,7 @@ digester.parse(globalWebXml); Map webXmlMimeMappings = webXmlDefaultFragment.getMimeMappings(); - SortedMap sortedWebXmlMimeMappings = new TreeMap<>(webXmlMimeMappings); + SortedMap sortedWebXmlMimeMappings = new TreeMap<>(webXmlMimeMappings); File f = new File("java/org/apache/catalina/startup/MimeTypeMappings.properties"); try (FileOutputStream fos = new FileOutputStream(f); @@ -59,7 +59,7 @@ w.write(System.lineSeparator()); - for (Map.Entry mapping : sortedWebXmlMimeMappings.entrySet()) { + for (Map.Entry mapping : sortedWebXmlMimeMappings.entrySet()) { w.write(mapping.getKey()); w.write("="); w.write(mapping.getValue()); diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/buildutil/RepeatableArchive.java tomcat10-10.1.52/java/org/apache/tomcat/buildutil/RepeatableArchive.java --- tomcat10-10.1.40/java/org/apache/tomcat/buildutil/RepeatableArchive.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/buildutil/RepeatableArchive.java 2026-01-23 19:33:36.000000000 +0000 @@ -41,11 +41,9 @@ /** * Ant task to assist with repeatable builds. *

        - * While originally written to address an issue with Javadoc output, this task - * takes a generic approach that could be used with any archive. The task takes - * a set of zip (or jar, war etc) files as its input and sets the last modified - * time of every file in the archive to be the same as the last modified time - * of the archive. + * While originally written to address an issue with Javadoc output, this task takes a generic approach that could be + * used with any archive. The task takes a set of zip (or jar, war etc) files as its input and sets the last modified + * time of every file in the archive to be the same as the last modified time of the archive. */ public class RepeatableArchive extends Task { diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/buildutil/Txt2Html.java tomcat10-10.1.52/java/org/apache/tomcat/buildutil/Txt2Html.java --- tomcat10-10.1.40/java/org/apache/tomcat/buildutil/Txt2Html.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/buildutil/Txt2Html.java 2026-01-23 19:33:36.000000000 +0000 @@ -34,17 +34,12 @@ import org.apache.tools.ant.types.FileSet; /** - * Ant task to convert a given set of files from Text to HTML. - * Inserts an HTML header including pre tags and replaces special characters - * with their HTML escaped equivalents. - * - *

        This task is currently used by the ant script to build our examples

        - * - * @author Mark Roth + * Ant task to convert a given set of files from Text to HTML. Inserts an HTML header including pre tags and replaces + * special characters with their HTML escaped equivalents. + *

        + * This task is currently used by the ant script to build our examples */ -public class Txt2Html - extends Task -{ +public class Txt2Html extends Task { /** The directory to contain the resulting files */ private File todir; @@ -53,14 +48,13 @@ private final List filesets = new ArrayList<>(); /** - * The encoding of the source files (.java and .jsp). Once they use - * UTF-8, this will need to be updated. + * The encoding of the source files (.java and .jsp). Once they use UTF-8, this will need to be updated. */ private static final String SOURCE_ENCODING = "ISO-8859-1"; /** - * Line terminator to be used for separating lines of the generated - * HTML page, to be independent of the "line.separator" system property. + * Line terminator to be used for separating lines of the generated HTML page, to be independent of the + * "line.separator" system property. */ private static final String LINE_SEPARATOR = "\r\n"; @@ -69,7 +63,7 @@ * * @param todir The directory */ - public void setTodir( File todir ) { + public void setTodir(File todir) { this.todir = todir; } @@ -78,20 +72,17 @@ * * @param fs The fileset to be converted. */ - public void addFileset( FileSet fs ) { - filesets.add( fs ); + public void addFileset(FileSet fs) { + filesets.add(fs); } /** * Perform the conversion * - * @throws BuildException if an error occurs during execution of - * this task. + * @throws BuildException if an error occurs during execution of this task. */ @Override - public void execute() - throws BuildException - { + public void execute() throws BuildException { int count = 0; // Step through each file and convert. @@ -102,23 +93,21 @@ for (String file : files) { File from = new File(basedir, file); File to = new File(todir, file + ".html"); - if (!to.exists() || - (from.lastModified() > to.lastModified())) { - log("Converting file '" + from.getAbsolutePath() + - "' to '" + to.getAbsolutePath(), Project.MSG_VERBOSE); + if (!to.exists() || (from.lastModified() > to.lastModified())) { + log("Converting file '" + from.getAbsolutePath() + "' to '" + to.getAbsolutePath(), + Project.MSG_VERBOSE); try { convert(from, to); - } catch (IOException e) { - throw new BuildException("Could not convert '" + - from.getAbsolutePath() + "' to '" + - to.getAbsolutePath() + "'", e); + } catch (IOException ioe) { + throw new BuildException( + "Could not convert '" + from.getAbsolutePath() + "' to '" + to.getAbsolutePath() + "'", + ioe); } count++; } } - if( count > 0 ) { - log( "Converted " + count + " file" + (count > 1 ? "s" : "") + - " to " + todir.getAbsolutePath() ); + if (count > 0) { + log("Converted " + count + " file" + (count > 1 ? "s" : "") + " to " + todir.getAbsolutePath()); } } } @@ -127,45 +116,43 @@ * Perform the actual copy and conversion * * @param from The input file - * @param to The output file + * @param to The output file + * * @throws IOException Thrown if an error occurs during the conversion */ - private void convert( File from, File to ) - throws IOException - { + private void convert(File from, File to) throws IOException { // Open files: - try (BufferedReader in = new BufferedReader(new InputStreamReader( - new FileInputStream(from), SOURCE_ENCODING))) { - try (PrintWriter out = new PrintWriter(new OutputStreamWriter( - new FileOutputStream(to), "UTF-8"))) { + try (BufferedReader in = + new BufferedReader(new InputStreamReader(new FileInputStream(from), SOURCE_ENCODING))) { + try (PrintWriter out = new PrintWriter(new OutputStreamWriter(new FileOutputStream(to), "UTF-8"))) { // Output header: - out.print("" - + "Source Code

        " );
        +                out.print("" +
        +                        "Source Code
        ");
         
                         // Convert, line-by-line:
                         String line;
        -                while( (line = in.readLine()) != null ) {
        +                while ((line = in.readLine()) != null) {
                             StringBuilder result = new StringBuilder();
                             int len = line.length();
        -                    for( int i = 0; i < len; i++ ) {
        -                        char c = line.charAt( i );
        -                        switch( c ) {
        +                    for (int i = 0; i < len; i++) {
        +                        char c = line.charAt(i);
        +                        switch (c) {
                                     case '&':
        -                                result.append( "&" );
        +                                result.append("&");
                                         break;
                                     case '<':
        -                                result.append( "<" );
        +                                result.append("<");
                                         break;
                                     default:
        -                                result.append( c );
        +                                result.append(c);
                                 }
                             }
        -                    out.print( result.toString() + LINE_SEPARATOR );
        +                    out.print(result.toString() + LINE_SEPARATOR);
                         }
         
                         // Output footer:
        -                out.print( "
        " ); + out.print("
        "); } } @@ -173,4 +160,3 @@ } - diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/buildutil/translate/BackportEnglish.java tomcat10-10.1.52/java/org/apache/tomcat/buildutil/translate/BackportEnglish.java --- tomcat10-10.1.40/java/org/apache/tomcat/buildutil/translate/BackportEnglish.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/buildutil/translate/BackportEnglish.java 2026-01-23 19:33:36.000000000 +0000 @@ -21,11 +21,9 @@ import java.util.Set; /** - * Generates a set of English property files to back-port updates to a previous - * version. Where a key exists in the source and target versions the value is - * copied from the source to the target, overwriting the value in the target. - * The expectation is that the changes will be manually reviewed before - * committing them. + * Generates a set of English property files to back-port updates to a previous version. Where a key exists in the + * source and target versions the value is copied from the source to the target, overwriting the value in the target. + * The expectation is that the changes will be manually reviewed before committing them. */ public class BackportEnglish extends BackportBase { diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/buildutil/translate/BackportTranslations.java tomcat10-10.1.52/java/org/apache/tomcat/buildutil/translate/BackportTranslations.java --- tomcat10-10.1.40/java/org/apache/tomcat/buildutil/translate/BackportTranslations.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/buildutil/translate/BackportTranslations.java 2026-01-23 19:33:36.000000000 +0000 @@ -20,10 +20,8 @@ import java.util.Properties; /** - * Generates a set of translated property files to back-port updates to a - * previous version. If the source and target use the same value for the English - * key then any translated value for that key is copied from the source to the - * target. + * Generates a set of translated property files to back-port updates to a previous version. If the source and target use + * the same value for the English key then any translated value for that key is copied from the source to the target. */ public class BackportTranslations extends BackportBase { @@ -53,8 +51,7 @@ } for (Object key : targetEnglish.keySet()) { - if (sourceTranslated.containsKey(key) && - targetEnglish.get(key).equals(sourceEnglish.get(key))) { + if (sourceTranslated.containsKey(key) && targetEnglish.get(key).equals(sourceEnglish.get(key))) { targetTranslated.put(key, sourceTranslated.get(key)); } diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/buildutil/translate/Import.java tomcat10-10.1.52/java/org/apache/tomcat/buildutil/translate/Import.java --- tomcat10-10.1.40/java/org/apache/tomcat/buildutil/translate/Import.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/buildutil/translate/Import.java 2026-01-23 19:33:36.000000000 +0000 @@ -68,7 +68,8 @@ if (w != null) { w.close(); } - File outFile = new File(currentPkg.replace('.', File.separatorChar), Constants.L10N_PREFIX + language + Constants.L10N_SUFFIX); + File outFile = new File(currentPkg.replace('.', File.separatorChar), + Constants.L10N_PREFIX + language + Constants.L10N_SUFFIX); FileOutputStream fos = new FileOutputStream(outFile); w = new OutputStreamWriter(fos, StandardCharsets.UTF_8); org.apache.tomcat.buildutil.Utils.insertLicense(w); diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/buildutil/translate/Utils.java tomcat10-10.1.52/java/org/apache/tomcat/buildutil/translate/Utils.java --- tomcat10-10.1.40/java/org/apache/tomcat/buildutil/translate/Utils.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/buildutil/translate/Utils.java 2026-01-23 19:33:36.000000000 +0000 @@ -64,13 +64,21 @@ try (FileInputStream fis = new FileInputStream(f); Reader r = new InputStreamReader(fis, StandardCharsets.UTF_8)) { props.load(r); - } catch (IOException e) { - e.printStackTrace(); + } catch (IOException ioe) { + ioe.printStackTrace(); } return props; } + /* + * This is the formatting applied when exporting values from Tomcat to POE. + * + * The values have been read from Tomcat's property files (so the input is the actual value with none of the + * escaping required to represent that value in a property file) and are being written back out in a single file to + * be imported into POEditor. The padding for blank lines needs to be added followed by the common formatting + * required to convert a property value to the representation of that value in a file. + */ static String formatValueExport(String in) { String result; @@ -84,6 +92,14 @@ } + /* + * This is the formatting applied when importing values to Tomcat from POE. + * + * The values have been read from POE's property files (so the input is the actual value with none of the + * escaping required to represent that value in a property file) and are being written back out to individual files + * in Tomcat. The padding for blank lines needs to be removed followed by the common formatting required to convert + * a property value to the representation of that value in a file. + */ static String formatValueImport(String in) { String result; @@ -98,9 +114,8 @@ /* - * Values containing "[{n}]" and "'" need to have the "'" escaped as "''". - * POEditor attempts to do this automatically but does it for any value - * containing "{" or "}" leading to some unnecessary escaping. This method + * Values containing "[{n}]" and "'" need to have the "'" escaped as "''". POEditor attempts to do this + * automatically but does it for any value containing "{" or "}" leading to some unnecessary escaping. This method * undoes the unnecessary escaping. */ static String fixUnnecessaryEscaping(String key, String value) { @@ -112,8 +127,13 @@ /* - * Common formatting to convert a String for storage as a value in a - * property file. + * Common formatting to convert a String value for storage as a value in a property file. Values that contain + * line-breaks need the line-break in the value to be replaced with the correct representation of a line-break in a + * property file. Leading space needs to be escaped with a '\' and horizontal tabs need to be converted to "\t". + * + * Note that a single '\' needs to be escaped both in a Java string and in a property file so if a property value + * needs to contain a single `\` (e.g. to escape white space at the start of a line) that will appear as "\\\\" in + * the Java code. */ static String formatValueCommon(String in) { String result = in.replace("\n", "\\n\\\n"); diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/dbcp/dbcp2/AbandonedTrace.java tomcat10-10.1.52/java/org/apache/tomcat/dbcp/dbcp2/AbandonedTrace.java --- tomcat10-10.1.40/java/org/apache/tomcat/dbcp/dbcp2/AbandonedTrace.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/dbcp/dbcp2/AbandonedTrace.java 2026-01-23 19:33:36.000000000 +0000 @@ -6,7 +6,7 @@ * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -131,12 +131,12 @@ * @return List of objects. */ protected List getTrace() { - final int size = traceList.size(); - if (size == 0) { - return Collections.emptyList(); - } - final ArrayList result = new ArrayList<>(size); synchronized (this.traceList) { + final int size = traceList.size(); + if (size == 0) { + return Collections.emptyList(); + } + final ArrayList result = new ArrayList<>(size); final Iterator> iter = traceList.iterator(); while (iter.hasNext()) { final AbandonedTrace trace = iter.next().get(); @@ -147,8 +147,8 @@ result.add(trace); } } + return result; } - return result; } /** diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/dbcp/dbcp2/BasicDataSource.java tomcat10-10.1.52/java/org/apache/tomcat/dbcp/dbcp2/BasicDataSource.java --- tomcat10-10.1.40/java/org/apache/tomcat/dbcp/dbcp2/BasicDataSource.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/dbcp/dbcp2/BasicDataSource.java 2026-01-23 19:33:36.000000000 +0000 @@ -6,7 +6,7 @@ * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -72,8 +72,8 @@ private static final Log log = LogFactory.getLog(BasicDataSource.class); static { - // Attempt to prevent deadlocks - see DBCP - 272 - DriverManager.getDrivers(); + // Attempt to prevent deadlocks - see DBCP-272 + DriverManager.getDrivers(); // NOPMD try { // Load classes now to prevent AccessControlExceptions later // A number of classes are loaded when getConnection() is called @@ -153,7 +153,7 @@ * The property that controls if the pooled connections cache some state rather than query the database for current * state to improve performance. */ - private boolean cacheState = true; + private volatile boolean cacheState = true; /** * The instance of the JDBC Driver to use. @@ -219,7 +219,7 @@ */ private boolean poolPreparedStatements; - private boolean clearStatementPoolOnReturn; + private volatile boolean clearStatementPoolOnReturn; /** *

        @@ -330,19 +330,19 @@ /** * Controls access to the underlying connection. */ - private boolean accessToUnderlyingConnectionAllowed; + private volatile boolean accessToUnderlyingConnectionAllowed; private Duration maxConnDuration = Duration.ofMillis(-1); - private boolean logExpiredConnections = true; + private volatile boolean logExpiredConnections = true; private String jmxName; - private boolean registerConnectionMBean = true; + private volatile boolean registerConnectionMBean = true; - private boolean autoCommitOnReturn = true; + private volatile boolean autoCommitOnReturn = true; - private boolean rollbackOnReturn = true; + private volatile boolean rollbackOnReturn = true; private volatile Set disconnectionSqlCodes; @@ -353,7 +353,7 @@ */ private volatile Set disconnectionIgnoreSqlCodes; - private boolean fastFailValidation; + private volatile boolean fastFailValidation; /** * The object pool that internally manages our connections. @@ -389,6 +389,13 @@ private ObjectNameWrapper registeredJmxObjectName; /** + * Constructs a new instance. + */ + public BasicDataSource() { + // empty + } + + /** * Adds a custom connection property to the set that will be passed to our JDBC driver. This MUST * be called before the first connection is retrieved (along with all the other configuration property setters). * Calls to this method after the connection pool has been initialized have no effect. @@ -458,7 +465,7 @@ * with the specified {@link ClassLoader}.

      • *
      • If {code driverClassName} is specified and the previous attempt fails, the class is loaded using the * context class loader of the current thread.
      • - *
      • If a driver still isn't loaded one is loaded via the {@link DriverManager} using the specified {code connectionString}. + *
      • If a driver still isn't loaded one is loaded via the {@link DriverManager} using the specified {code connectionString}.
      • * *

        * This method exists so subclasses can replace the implementation class. @@ -2021,8 +2028,8 @@ *

        * * @param disconnectionSqlCodes SQL State codes considered to signal fatal conditions - * @since 2.1 * @throws IllegalArgumentException if any SQL state codes overlap with those in {@link #disconnectionIgnoreSqlCodes}. + * @since 2.1 */ public void setDisconnectionSqlCodes(final Collection disconnectionSqlCodes) { Utils.checkSqlCodes(disconnectionSqlCodes, this.disconnectionIgnoreSqlCodes); @@ -2110,8 +2117,10 @@ } /** + * Sets whether connections created by this factory will fast fail validation. + * + * @param fastFailValidation true means connections created by this factory will fast fail validation. * @see #getFastFailValidation() - * @param fastFailValidation true means connections created by this factory will fast fail validation * @since 2.1 */ public void setFastFailValidation(final boolean fastFailValidation) { @@ -2155,6 +2164,8 @@ } /** + * Sets whether to log abandoned resources. + * * @param logAbandoned new logAbandoned property value */ public void setLogAbandoned(final boolean logAbandoned) { @@ -2392,8 +2403,9 @@ } /** - * @param removeAbandonedOnBorrow true means abandoned connections may be removed when connections are borrowed from - * the pool. + * Sets abandoned connections may be removed when connections are borrowed from the pool. + * + * @param removeAbandonedOnBorrow true means abandoned connections may be removed when connections are borrowed from the pool. * @see #getRemoveAbandonedOnBorrow() */ public void setRemoveAbandonedOnBorrow(final boolean removeAbandonedOnBorrow) { @@ -2401,6 +2413,8 @@ } /** + * Sets whether abandoned connections may be removed on pool maintenance. + * * @param removeAbandonedOnMaintenance true means abandoned connections may be removed on pool maintenance. * @see #getRemoveAbandonedOnMaintenance() */ diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/dbcp/dbcp2/BasicDataSourceFactory.java tomcat10-10.1.52/java/org/apache/tomcat/dbcp/dbcp2/BasicDataSourceFactory.java --- tomcat10-10.1.40/java/org/apache/tomcat/dbcp/dbcp2/BasicDataSourceFactory.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/dbcp/dbcp2/BasicDataSourceFactory.java 2026-01-23 19:33:36.000000000 +0000 @@ -6,7 +6,7 @@ * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -49,12 +49,12 @@ import org.apache.tomcat.dbcp.pool2.impl.GenericObjectPoolConfig; /** - * JNDI object factory that creates an instance of {@code BasicDataSource} that has been configured based on the - * {@code RefAddr} values of the specified {@code Reference}, which must match the names and data types of the - * {@code BasicDataSource} bean properties with the following exceptions: + * JNDI object factory that creates an instance of {@link BasicDataSource} that has been configured based on the + * {@link RefAddr} values of the specified {@code Reference}, which must match the names and data types of the + * {@link BasicDataSource} bean properties with the following exceptions: *
          *
        • {@code connectionInitSqls} must be passed to this factory as a single String using semicolon to delimit the - * statements whereas {@code BasicDataSource} requires a collection of Strings.
        • + * statements whereas {@link BasicDataSource} requires a collection of Strings. *
        * * @since 2.0 @@ -131,7 +131,6 @@ */ private static final String PROP_DISCONNECTION_IGNORE_SQL_CODES = "disconnectionIgnoreSqlCodes"; - /* * Block with obsolete properties from DBCP 1.x. Warn users that these are ignored and they should use the 2.x * properties. @@ -175,11 +174,11 @@ "Property " + NUPROP_MAX_ACTIVE + " is not used in DBCP2, use " + PROP_MAX_TOTAL + " instead. " + PROP_MAX_TOTAL + " default value is " + GenericObjectPoolConfig.DEFAULT_MAX_TOTAL + "."); NUPROP_WARNTEXT.put(NUPROP_REMOVE_ABANDONED, - "Property " + NUPROP_REMOVE_ABANDONED + " is not used in DBCP2," + " use one or both of " + "Property " + NUPROP_REMOVE_ABANDONED + " is not used in DBCP2, use one or both of " + PROP_REMOVE_ABANDONED_ON_BORROW + " or " + PROP_REMOVE_ABANDONED_ON_MAINTENANCE + " instead. " + "Both have default value set to false."); NUPROP_WARNTEXT.put(NUPROP_MAXWAIT, - "Property " + NUPROP_MAXWAIT + " is not used in DBCP2" + " , use " + PROP_MAX_WAIT_MILLIS + " instead. " + "Property " + NUPROP_MAXWAIT + " is not used in DBCP2 , use " + PROP_MAX_WAIT_MILLIS + " instead. " + PROP_MAX_WAIT_MILLIS + " default value is " + BaseObjectPoolConfig.DEFAULT_MAX_WAIT + "."); } @@ -240,31 +239,31 @@ value = value.toUpperCase(Locale.ROOT); int level = PoolableConnectionFactory.UNKNOWN_TRANSACTION_ISOLATION; switch (value) { - case "NONE": - level = Connection.TRANSACTION_NONE; - break; - case "READ_COMMITTED": - level = Connection.TRANSACTION_READ_COMMITTED; - break; - case "READ_UNCOMMITTED": - level = Connection.TRANSACTION_READ_UNCOMMITTED; - break; - case "REPEATABLE_READ": - level = Connection.TRANSACTION_REPEATABLE_READ; - break; - case "SERIALIZABLE": - level = Connection.TRANSACTION_SERIALIZABLE; - break; - default: - try { - level = Integer.parseInt(value); - } catch (final NumberFormatException e) { - System.err.println("Could not parse defaultTransactionIsolation: " + value); - System.err.println("WARNING: defaultTransactionIsolation not set"); - System.err.println("using default value of database driver"); - level = PoolableConnectionFactory.UNKNOWN_TRANSACTION_ISOLATION; - } - break; + case "NONE": + level = Connection.TRANSACTION_NONE; + break; + case "READ_COMMITTED": + level = Connection.TRANSACTION_READ_COMMITTED; + break; + case "READ_UNCOMMITTED": + level = Connection.TRANSACTION_READ_UNCOMMITTED; + break; + case "REPEATABLE_READ": + level = Connection.TRANSACTION_REPEATABLE_READ; + break; + case "SERIALIZABLE": + level = Connection.TRANSACTION_SERIALIZABLE; + break; + default: + try { + level = Integer.parseInt(value); + } catch (final NumberFormatException e) { + System.err.println("Could not parse defaultTransactionIsolation: " + value); + System.err.println("WARNING: defaultTransactionIsolation not set"); + System.err.println("using default value of database driver"); + level = PoolableConnectionFactory.UNKNOWN_TRANSACTION_ISOLATION; + } + break; } dataSource.setDefaultTransactionIsolation(level); }); @@ -306,9 +305,10 @@ final String value = properties.getProperty(PROP_CONNECTION_PROPERTIES); if (value != null) { - for (final Object key : getProperties(value).keySet()) { - final String propertyName = Objects.toString(key, null); - dataSource.addConnectionProperty(propertyName, getProperties(value).getProperty(propertyName)); + final Properties connectionProperties = getProperties(value); + for (final Object key : connectionProperties.keySet()) { + final String propertyName = Objects.toString(key); + dataSource.addConnectionProperty(propertyName, connectionProperties.getProperty(propertyName)); } } @@ -376,7 +376,14 @@ } /** - * Creates and return a new {@code BasicDataSource} instance. If no instance can be created, return + * Constructs a new instance. + */ + public BasicDataSourceFactory() { + // empty + } + + /** + * Creates and return a new {@link BasicDataSource} instance. If no instance can be created, return * {@code null} instead. * * @param obj diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/dbcp/dbcp2/BasicDataSourceMXBean.java tomcat10-10.1.52/java/org/apache/tomcat/dbcp/dbcp2/BasicDataSourceMXBean.java --- tomcat10-10.1.40/java/org/apache/tomcat/dbcp/dbcp2/BasicDataSourceMXBean.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/dbcp/dbcp2/BasicDataSourceMXBean.java 2026-01-23 19:33:36.000000000 +0000 @@ -6,7 +6,7 @@ * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/dbcp/dbcp2/ConnectionFactory.java tomcat10-10.1.52/java/org/apache/tomcat/dbcp/dbcp2/ConnectionFactory.java --- tomcat10-10.1.40/java/org/apache/tomcat/dbcp/dbcp2/ConnectionFactory.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/dbcp/dbcp2/ConnectionFactory.java 2026-01-23 19:33:36.000000000 +0000 @@ -6,7 +6,7 @@ * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -20,15 +20,15 @@ import java.sql.SQLException; /** - * Abstract factory interface for creating {@link java.sql.Connection}s. + * Abstract factory interface for creating {@link Connection}s. * * @since 2.0 */ public interface ConnectionFactory { /** - * Create a new {@link java.sql.Connection} in an implementation specific fashion. + * Create a new {@link Connection} in an implementation specific fashion. * - * @return a new {@link java.sql.Connection} + * @return a new {@link Connection} * @throws SQLException * if a database error occurs creating the connection */ diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/dbcp/dbcp2/ConnectionFactoryFactory.java tomcat10-10.1.52/java/org/apache/tomcat/dbcp/dbcp2/ConnectionFactoryFactory.java --- tomcat10-10.1.40/java/org/apache/tomcat/dbcp/dbcp2/ConnectionFactoryFactory.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/dbcp/dbcp2/ConnectionFactoryFactory.java 2026-01-23 19:33:36.000000000 +0000 @@ -6,7 +6,7 @@ * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/dbcp/dbcp2/Constants.java tomcat10-10.1.52/java/org/apache/tomcat/dbcp/dbcp2/Constants.java --- tomcat10-10.1.40/java/org/apache/tomcat/dbcp/dbcp2/Constants.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/dbcp/dbcp2/Constants.java 2026-01-23 19:33:36.000000000 +0000 @@ -6,7 +6,7 @@ * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -61,4 +61,14 @@ * @since 2.9.0 */ public static final String KEY_USER = "user"; + + /** + * Deprecated, only contains static methods. + * + * @deprecated Will be private in the next major version. + */ + @Deprecated + public Constants() { + // empty + } } diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/dbcp/dbcp2/DataSourceConnectionFactory.java tomcat10-10.1.52/java/org/apache/tomcat/dbcp/dbcp2/DataSourceConnectionFactory.java --- tomcat10-10.1.40/java/org/apache/tomcat/dbcp/dbcp2/DataSourceConnectionFactory.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/dbcp/dbcp2/DataSourceConnectionFactory.java 2026-01-23 19:33:36.000000000 +0000 @@ -6,7 +6,7 @@ * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -86,6 +86,8 @@ } /** + * Gets the data source.. + * * @return The data source. * @since 2.6.0 */ @@ -94,7 +96,9 @@ } /** - * @return The user name. + * Gets the user name, may be null. + * + * @return The user name, may be null. * @since 2.6.0 */ public String getUserName() { @@ -102,7 +106,9 @@ } /** - * @return The user password. + * Gets the user password, may be null. + * + * @return The user password, may be null. * @since 2.6.0 */ public char[] getUserPassword() { diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/dbcp/dbcp2/DataSourceMXBean.java tomcat10-10.1.52/java/org/apache/tomcat/dbcp/dbcp2/DataSourceMXBean.java --- tomcat10-10.1.40/java/org/apache/tomcat/dbcp/dbcp2/DataSourceMXBean.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/dbcp/dbcp2/DataSourceMXBean.java 2026-01-23 19:33:36.000000000 +0000 @@ -6,7 +6,7 @@ * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/dbcp/dbcp2/DelegatingCallableStatement.java tomcat10-10.1.52/java/org/apache/tomcat/dbcp/dbcp2/DelegatingCallableStatement.java --- tomcat10-10.1.40/java/org/apache/tomcat/dbcp/dbcp2/DelegatingCallableStatement.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/dbcp/dbcp2/DelegatingCallableStatement.java 2026-01-23 19:33:36.000000000 +0000 @@ -6,7 +6,7 @@ * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/dbcp/dbcp2/DelegatingConnection.java tomcat10-10.1.52/java/org/apache/tomcat/dbcp/dbcp2/DelegatingConnection.java --- tomcat10-10.1.40/java/org/apache/tomcat/dbcp/dbcp2/DelegatingConnection.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/dbcp/dbcp2/DelegatingConnection.java 2026-01-23 19:33:36.000000000 +0000 @@ -6,7 +6,7 @@ * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -69,8 +69,7 @@ private volatile C connection; private volatile boolean closed; - - private boolean cacheState = true; + private volatile boolean cacheState = true; private Boolean cachedAutoCommit; private Boolean cachedReadOnly; private String cachedCatalog; @@ -167,6 +166,11 @@ } } + /** + * Closes the underlying connection for {@link #close()}. + * + * @throws SQLException SQLException if a database access error occurs. + */ protected final void closeInternal() throws SQLException { try { passivate(); @@ -284,7 +288,7 @@ @Override public Statement createStatement(final int resultSetType, final int resultSetConcurrency, - final int resultSetHoldability) throws SQLException { + final int resultSetHoldability) throws SQLException { checkOpen(); try { return init(new DelegatingStatement(this, @@ -426,14 +430,14 @@ } /** - * If my underlying {@link Connection} is not a {@code DelegatingConnection}, returns it, otherwise recursively + * If my underlying {@link Connection} is not a {@link DelegatingConnection}, returns it, otherwise recursively * invokes this method on my delegate. *

        - * Hence this method will return the first delegate that is not a {@code DelegatingConnection}, or {@code null} when - * no non-{@code DelegatingConnection} delegate can be found by traversing this chain. + * Hence this method will return the first delegate that is not a {@link DelegatingConnection}, or {@code null} when + * no non-{@link DelegatingConnection} delegate can be found by traversing this chain. *

        *

        - * This method is useful when you may have nested {@code DelegatingConnection}s, and you want to make sure to obtain + * This method is useful when you may have nested {@link DelegatingConnection}s, and you want to make sure to obtain * a "genuine" {@link Connection}. *

        * @@ -541,11 +545,11 @@ } /** - * Handles the given {@code SQLException}. + * Handles the given {@link SQLException}. * * @param The throwable type. * @param e The SQLException - * @return the given {@code SQLException} + * @return the given {@link SQLException} * @since 2.7.0 */ protected T handleExceptionNoThrow(final T e) { @@ -643,10 +647,7 @@ @Override public boolean isWrapperFor(final Class iface) throws SQLException { - if (iface.isAssignableFrom(getClass())) { - return true; - } - if (iface.isAssignableFrom(connection.getClass())) { + if (iface.isAssignableFrom(getClass()) || iface.isAssignableFrom(connection.getClass())) { return true; } return connection.isWrapperFor(iface); @@ -710,7 +711,7 @@ @Override public CallableStatement prepareCall(final String sql, final int resultSetType, final int resultSetConcurrency, - final int resultSetHoldability) throws SQLException { + final int resultSetHoldability) throws SQLException { checkOpen(); try { return init(new DelegatingCallableStatement(this, @@ -758,7 +759,7 @@ @Override public PreparedStatement prepareStatement(final String sql, final int resultSetType, final int resultSetConcurrency, - final int resultSetHoldability) throws SQLException { + final int resultSetHoldability) throws SQLException { checkOpen(); try { return init(new DelegatingPreparedStatement(this, diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/dbcp/dbcp2/DelegatingDatabaseMetaData.java tomcat10-10.1.52/java/org/apache/tomcat/dbcp/dbcp2/DelegatingDatabaseMetaData.java --- tomcat10-10.1.40/java/org/apache/tomcat/dbcp/dbcp2/DelegatingDatabaseMetaData.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/dbcp/dbcp2/DelegatingDatabaseMetaData.java 2026-01-23 19:33:36.000000000 +0000 @@ -6,7 +6,7 @@ * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -264,13 +264,13 @@ } /** - * If my underlying {@link ResultSet} is not a {@code DelegatingResultSet}, returns it, otherwise recursively invokes this method on my delegate. + * If my underlying {@link ResultSet} is not a {@link DelegatingResultSet}, returns it, otherwise recursively invokes this method on my delegate. *

        - * Hence this method will return the first delegate that is not a {@code DelegatingResultSet}, or {@code null} when no non-{@code DelegatingResultSet} + * Hence this method will return the first delegate that is not a {@link DelegatingResultSet}, or {@code null} when no non-{@link DelegatingResultSet} * delegate can be found by traversing this chain. *

        *

        - * This method is useful when you may have nested {@code DelegatingResultSet}s, and you want to make sure to obtain a "genuine" {@link ResultSet}. + * This method is useful when you may have nested {@link DelegatingResultSet}s, and you want to make sure to obtain a "genuine" {@link ResultSet}. *

        * * @return the innermost database meta data. @@ -580,10 +580,7 @@ @Override public boolean isWrapperFor(final Class iface) throws SQLException { - if (iface.isAssignableFrom(getClass())) { - return true; - } - if (iface.isAssignableFrom(databaseMetaData.getClass())) { + if (iface.isAssignableFrom(getClass()) || iface.isAssignableFrom(databaseMetaData.getClass())) { return true; } return databaseMetaData.isWrapperFor(iface); diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/dbcp/dbcp2/DelegatingPreparedStatement.java tomcat10-10.1.52/java/org/apache/tomcat/dbcp/dbcp2/DelegatingPreparedStatement.java --- tomcat10-10.1.40/java/org/apache/tomcat/dbcp/dbcp2/DelegatingPreparedStatement.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/dbcp/dbcp2/DelegatingPreparedStatement.java 2026-01-23 19:33:36.000000000 +0000 @@ -6,7 +6,7 @@ * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -167,10 +167,14 @@ } } + /** + * Prepares internal states before calling {@link #passivate()}. + * + * @throws SQLException Thrown closing a traced resource or calling {@link #passivate()}. + */ protected void prepareToReturn() throws SQLException { setClosedInternal(true); removeThisTrace(getConnectionInternal()); - // The JDBC spec requires that a statement close any open // ResultSet's when it is closed. // FIXME The PreparedStatement we're wrapping should handle this for us. @@ -184,7 +188,6 @@ throw new SQLExceptionList(thrownList); } } - super.passivate(); } diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/dbcp/dbcp2/DelegatingResultSet.java tomcat10-10.1.52/java/org/apache/tomcat/dbcp/dbcp2/DelegatingResultSet.java --- tomcat10-10.1.40/java/org/apache/tomcat/dbcp/dbcp2/DelegatingResultSet.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/dbcp/dbcp2/DelegatingResultSet.java 2026-01-23 19:33:36.000000000 +0000 @@ -6,7 +6,7 @@ * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -595,14 +595,14 @@ } /** - * If my underlying {@link ResultSet} is not a {@code DelegatingResultSet}, returns it, otherwise recursively + * If my underlying {@link ResultSet} is not a {@link DelegatingResultSet}, returns it, otherwise recursively * invokes this method on my delegate. *

        - * Hence this method will return the first delegate that is not a {@code DelegatingResultSet}, or {@code null} when - * no non-{@code DelegatingResultSet} delegate can be found by traversing this chain. + * Hence this method will return the first delegate that is not a {@link DelegatingResultSet}, or {@code null} when + * no non-{@link DelegatingResultSet} delegate can be found by traversing this chain. *

        *

        - * This method is useful when you may have nested {@code DelegatingResultSet}s, and you want to make sure to obtain + * This method is useful when you may have nested {@link DelegatingResultSet}s, and you want to make sure to obtain * a "genuine" {@link ResultSet}. *

        * @@ -1052,6 +1052,12 @@ } } + /** + * Handles a SQL exception by delegating to a DelegatingStatement or DelegatingConnection. + * + * @param e The exception to handle. + * @throws SQLException Throws the given exception if not handled. + */ protected void handleException(final SQLException e) throws SQLException { if (statement instanceof DelegatingStatement) { ((DelegatingStatement) statement).handleException(e); @@ -1123,10 +1129,7 @@ @Override public boolean isWrapperFor(final Class iface) throws SQLException { - if (iface.isAssignableFrom(getClass())) { - return true; - } - if (iface.isAssignableFrom(resultSet.getClass())) { + if (iface.isAssignableFrom(getClass()) || iface.isAssignableFrom(resultSet.getClass())) { return true; } return resultSet.isWrapperFor(iface); diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/dbcp/dbcp2/DelegatingStatement.java tomcat10-10.1.52/java/org/apache/tomcat/dbcp/dbcp2/DelegatingStatement.java --- tomcat10-10.1.40/java/org/apache/tomcat/dbcp/dbcp2/DelegatingStatement.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/dbcp/dbcp2/DelegatingStatement.java 2026-01-23 19:33:36.000000000 +0000 @@ -6,7 +6,7 @@ * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -44,7 +44,7 @@ /** The connection that created me. **/ private DelegatingConnection connection; - private boolean closed; + private volatile boolean closed; /** * Create a wrapper for the Statement which traces this Statement to the Connection which created it and the code @@ -62,6 +62,8 @@ } /** + * Activates this instance by delegating to the underlying statement. + * * @throws SQLException * thrown by the delegating statement. * @since 2.4.0 made public, was protected in 2.3.0. @@ -92,6 +94,11 @@ } } + /** + * Checks whether this instance is closed and throws an exception if it is. + * + * @throws SQLException Thrown if this instance is closed. + */ protected void checkOpen() throws SQLException { if (isClosed()) { throw new SQLException(this.getClass().getName() + " with address: \"" + toString() + "\" is closed."); @@ -390,6 +397,11 @@ return getConnectionInternal(); // return the delegating connection that created this } + /** + * Gets the internal connection. + * + * @return the internal connection. + */ protected DelegatingConnection getConnectionInternal() { return connection; } @@ -438,14 +450,14 @@ } /** - * If my underlying {@link Statement} is not a {@code DelegatingStatement}, returns it, otherwise recursively + * If my underlying {@link Statement} is not a {@link DelegatingStatement}, returns it, otherwise recursively * invokes this method on my delegate. *

        - * Hence this method will return the first delegate that is not a {@code DelegatingStatement} or {@code null} when - * no non-{@code DelegatingStatement} delegate can be found by traversing this chain. + * Hence this method will return the first delegate that is not a {@link DelegatingStatement} or {@code null} when + * no non-{@link DelegatingStatement} delegate can be found by traversing this chain. *

        *

        - * This method is useful when you may have nested {@code DelegatingStatement}s, and you want to make sure to obtain + * This method is useful when you may have nested {@link DelegatingStatement}s, and you want to make sure to obtain * a "genuine" {@link Statement}. *

        * @@ -612,6 +624,12 @@ } } + /** + * Delegates the exception to the internal connection if set, otherwise rethrows it. + * + * @param e The exception to handle. + * @throws SQLException The given exception if not handled. + */ protected void handleException(final SQLException e) throws SQLException { if (connection == null) { throw e; @@ -627,6 +645,11 @@ return closed; } + /** + * Tests whether this instance is closed. + * + * @return whether this instance is closed. + */ protected boolean isClosedInternal() { return closed; } @@ -655,16 +678,15 @@ @Override public boolean isWrapperFor(final Class iface) throws SQLException { - if (iface.isAssignableFrom(getClass())) { - return true; - } - if (iface.isAssignableFrom(statement.getClass())) { + if (iface.isAssignableFrom(getClass()) || iface.isAssignableFrom(statement.getClass())) { return true; } return statement.isWrapperFor(iface); } /** + * Passivates this instance by delegating to the underlying statement. + * * @throws SQLException * thrown by the delegating statement. * @since 2.4.0 made public, was protected in 2.3.0. @@ -675,6 +697,11 @@ } } + /** + * Sets the closed internal state. + * + * @param closed whether the instance is now closed. + */ protected void setClosedInternal(final boolean closed) { this.closed = closed; } diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/dbcp/dbcp2/DriverConnectionFactory.java tomcat10-10.1.52/java/org/apache/tomcat/dbcp/dbcp2/DriverConnectionFactory.java --- tomcat10-10.1.40/java/org/apache/tomcat/dbcp/dbcp2/DriverConnectionFactory.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/dbcp/dbcp2/DriverConnectionFactory.java 2026-01-23 19:33:36.000000000 +0000 @@ -6,7 +6,7 @@ * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -85,6 +85,6 @@ @Override public String toString() { return this.getClass().getName() + " [" + driver + ";" + connectionString + ";" - + Utils.cloneWithoutCredentials(properties) + "]"; + + Utils.cloneWithoutCredentials(properties) + "]"; } } diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/dbcp/dbcp2/DriverFactory.java tomcat10-10.1.52/java/org/apache/tomcat/dbcp/dbcp2/DriverFactory.java --- tomcat10-10.1.40/java/org/apache/tomcat/dbcp/dbcp2/DriverFactory.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/dbcp/dbcp2/DriverFactory.java 2026-01-23 19:33:36.000000000 +0000 @@ -6,7 +6,7 @@ * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -60,7 +60,7 @@ } else { // Usage of DriverManager is not possible, as it does not // respect the ContextClassLoader - // N.B. This cast may cause ClassCastException which is + // This cast may cause ClassCastException which is // handled below driverToUse = (Driver) driverFromCCL.getConstructor().newInstance(); if (!driverToUse.acceptsURL(url)) { diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/dbcp/dbcp2/DriverManagerConnectionFactory.java tomcat10-10.1.52/java/org/apache/tomcat/dbcp/dbcp2/DriverManagerConnectionFactory.java --- tomcat10-10.1.40/java/org/apache/tomcat/dbcp/dbcp2/DriverManagerConnectionFactory.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/dbcp/dbcp2/DriverManagerConnectionFactory.java 2026-01-23 19:33:36.000000000 +0000 @@ -6,7 +6,7 @@ * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -29,12 +29,12 @@ public class DriverManagerConnectionFactory implements ConnectionFactory { static { - // Related to DBCP-212 + // Related to DBCP-272 // Driver manager does not sync loading of drivers that use the service // provider interface. This will cause issues is multi-threaded // environments. This hack makes sure the drivers are loaded before // DBCP tries to use them. - DriverManager.getDrivers(); + DriverManager.getDrivers(); // NOPMD } private final String connectionUri; @@ -123,6 +123,8 @@ } /** + * Gets the connection URI. + * * @return The connection URI. * @since 2.6.0 */ @@ -131,7 +133,9 @@ } /** - * @return The Properties. + * Gets the Properties, may be null. + * + * @return The Properties, may be null. * @since 2.6.0 */ public Properties getProperties() { @@ -139,7 +143,9 @@ } /** - * @return The user name. + * Gets the user name, may be null. + * + * @return The user name, may be null. * @since 2.6.0 */ public String getUserName() { diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/dbcp/dbcp2/Jdbc41Bridge.java tomcat10-10.1.52/java/org/apache/tomcat/dbcp/dbcp2/Jdbc41Bridge.java --- tomcat10-10.1.40/java/org/apache/tomcat/dbcp/dbcp2/Jdbc41Bridge.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/dbcp/dbcp2/Jdbc41Bridge.java 2026-01-23 19:33:36.000000000 +0000 @@ -6,7 +6,7 @@ * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -485,4 +485,14 @@ } } + /** + * Deprecated, this class only contains static methods. + * + * @deprecated Constructor will be private in the next major release. + */ + @Deprecated + public Jdbc41Bridge() { + // empty + } + } diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/dbcp/dbcp2/LifetimeExceededException.java tomcat10-10.1.52/java/org/apache/tomcat/dbcp/dbcp2/LifetimeExceededException.java --- tomcat10-10.1.40/java/org/apache/tomcat/dbcp/dbcp2/LifetimeExceededException.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/dbcp/dbcp2/LifetimeExceededException.java 2026-01-23 19:33:36.000000000 +0000 @@ -6,7 +6,7 @@ * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/dbcp/dbcp2/ListException.java tomcat10-10.1.52/java/org/apache/tomcat/dbcp/dbcp2/ListException.java --- tomcat10-10.1.40/java/org/apache/tomcat/dbcp/dbcp2/ListException.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/dbcp/dbcp2/ListException.java 2026-01-23 19:33:36.000000000 +0000 @@ -6,7 +6,7 @@ * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -27,6 +27,9 @@ private static final long serialVersionUID = 1L; + /** + * A list of causes. + */ private final List exceptionList; /** diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/dbcp/dbcp2/LocalStrings.properties tomcat10-10.1.52/java/org/apache/tomcat/dbcp/dbcp2/LocalStrings.properties --- tomcat10-10.1.40/java/org/apache/tomcat/dbcp/dbcp2/LocalStrings.properties 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/dbcp/dbcp2/LocalStrings.properties 2026-01-23 19:33:36.000000000 +0000 @@ -5,7 +5,7 @@ # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # -# http://www.apache.org/licenses/LICENSE-2.0 +# https://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/dbcp/dbcp2/ObjectNameWrapper.java tomcat10-10.1.52/java/org/apache/tomcat/dbcp/dbcp2/ObjectNameWrapper.java --- tomcat10-10.1.40/java/org/apache/tomcat/dbcp/dbcp2/ObjectNameWrapper.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/dbcp/dbcp2/ObjectNameWrapper.java 2026-01-23 19:33:36.000000000 +0000 @@ -6,7 +6,7 @@ * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -42,7 +42,9 @@ return ManagementFactory.getPlatformMBeanServer(); } catch (final LinkageError | Exception e) { // ignore - JMX not available - log.debug("Failed to get platform MBeanServer", e); + if (log.isDebugEnabled()) { + log.debug("Failed to get platform MBeanServer", e); + } return null; } } diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/dbcp/dbcp2/PStmtKey.java tomcat10-10.1.52/java/org/apache/tomcat/dbcp/dbcp2/PStmtKey.java --- tomcat10-10.1.40/java/org/apache/tomcat/dbcp/dbcp2/PStmtKey.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/dbcp/dbcp2/PStmtKey.java 2026-01-23 19:33:36.000000000 +0000 @@ -6,7 +6,7 @@ * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -17,6 +17,7 @@ package org.apache.tomcat.dbcp.dbcp2; import java.sql.Connection; +import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; import java.util.Arrays; @@ -48,17 +49,17 @@ private static final StatementBuilder StatementColumnNames = (c, k) -> c.prepareStatement(k.sql, k.columnNames); private static final StatementBuilder StatementConcurrency = (c, k) -> c.prepareStatement(k.sql, k.resultSetType.intValue(), k.resultSetConcurrency.intValue()); private static final StatementBuilder StatementHoldability = (c, k) -> c.prepareStatement(k.sql, k.resultSetType.intValue(), k.resultSetConcurrency.intValue(), - k.resultSetHoldability.intValue()); + k.resultSetHoldability.intValue()); private static final StatementBuilder StatementSQL = (c, k) -> c.prepareStatement(k.sql); private static StatementBuilder match(final StatementType statementType, final StatementBuilder prep, final StatementBuilder call) { switch (Objects.requireNonNull(statementType, "statementType")) { - case PREPARED_STATEMENT: - return prep; - case CALLABLE_STATEMENT: - return call; - default: - throw new IllegalArgumentException(statementType.toString()); + case PREPARED_STATEMENT: + return prep; + case CALLABLE_STATEMENT: + return call; + default: + throw new IllegalArgumentException(statementType.toString()); } } @@ -68,20 +69,20 @@ private final String sql; /** - * Result set type; one of {@code ResultSet.TYPE_FORWARD_ONLY}, {@code ResultSet.TYPE_SCROLL_INSENSITIVE}, or - * {@code ResultSet.TYPE_SCROLL_SENSITIVE}. + * Result set type; one of {@link ResultSet#TYPE_FORWARD_ONLY}, {@link ResultSet#TYPE_SCROLL_INSENSITIVE}, or + * {@link ResultSet#TYPE_SCROLL_SENSITIVE}. */ private final Integer resultSetType; /** - * Result set concurrency. A concurrency type; one of {@code ResultSet.CONCUR_READ_ONLY} or - * {@code ResultSet.CONCUR_UPDATABLE}. + * Result set concurrency. A concurrency type; one of {@link ResultSet#CONCUR_READ_ONLY} or + * {@link ResultSet#CONCUR_UPDATABLE}. */ private final Integer resultSetConcurrency; /** - * Result set holdability. One of the following {@code ResultSet} constants: {@code ResultSet.HOLD_CURSORS_OVER_COMMIT} - * or {@code ResultSet.CLOSE_CURSORS_AT_COMMIT}. + * Result set holdability. One of the following {@link ResultSet} constants: {@link ResultSet#HOLD_CURSORS_OVER_COMMIT} + * or {@link ResultSet#CLOSE_CURSORS_AT_COMMIT}. */ private final Integer resultSetHoldability; @@ -96,8 +97,8 @@ private final String schema; /** - * A flag indicating whether auto-generated keys should be returned; one of {@code Statement.RETURN_GENERATED_KEYS} or - * {@code Statement.NO_GENERATED_KEYS}. + * A flag indicating whether auto-generated keys should be returned; one of {@link Statement#RETURN_GENERATED_KEYS} or + * {@link Statement#NO_GENERATED_KEYS}. */ private final Integer autoGeneratedKeys; @@ -136,10 +137,10 @@ * Constructs a key to uniquely identify a prepared statement. * * @param sql The SQL statement. - * @param resultSetType A result set type; one of {@code ResultSet.TYPE_FORWARD_ONLY}, - * {@code ResultSet.TYPE_SCROLL_INSENSITIVE}, or {@code ResultSet.TYPE_SCROLL_SENSITIVE}. - * @param resultSetConcurrency A concurrency type; one of {@code ResultSet.CONCUR_READ_ONLY} or - * {@code ResultSet.CONCUR_UPDATABLE}. + * @param resultSetType A result set type; one of {@link ResultSet#TYPE_FORWARD_ONLY}, + * {@link ResultSet#TYPE_SCROLL_INSENSITIVE}, or {@link ResultSet#TYPE_SCROLL_SENSITIVE}. + * @param resultSetConcurrency A concurrency type; one of {@link ResultSet#CONCUR_READ_ONLY} or + * {@link ResultSet#CONCUR_UPDATABLE}. * @deprecated Use {@link #PStmtKey(String, String, String, int, int)}. */ @Deprecated @@ -165,7 +166,7 @@ * @param sql The SQL statement. * @param catalog The catalog. * @param autoGeneratedKeys A flag indicating whether auto-generated keys should be returned; one of - * {@code Statement.RETURN_GENERATED_KEYS} or {@code Statement.NO_GENERATED_KEYS}. + * {@link Statement#RETURN_GENERATED_KEYS} or {@link Statement#NO_GENERATED_KEYS}. * @deprecated Use {@link #PStmtKey(String, String, String, int)}. */ @Deprecated @@ -178,10 +179,10 @@ * * @param sql The SQL statement. * @param catalog The catalog. - * @param resultSetType A result set type; one of {@code ResultSet.TYPE_FORWARD_ONLY}, - * {@code ResultSet.TYPE_SCROLL_INSENSITIVE}, or {@code ResultSet.TYPE_SCROLL_SENSITIVE}. - * @param resultSetConcurrency A concurrency type; one of {@code ResultSet.CONCUR_READ_ONLY} or - * {@code ResultSet.CONCUR_UPDATABLE}. + * @param resultSetType A result set type; one of {@link ResultSet#TYPE_FORWARD_ONLY}, + * {@link ResultSet#TYPE_SCROLL_INSENSITIVE}, or {@link ResultSet#TYPE_SCROLL_SENSITIVE}. + * @param resultSetConcurrency A concurrency type; one of {@link ResultSet#CONCUR_READ_ONLY} or + * {@link ResultSet#CONCUR_UPDATABLE}. * @deprecated Use {@link #PStmtKey(String, String, String, int, int)}. */ @Deprecated @@ -194,12 +195,12 @@ * * @param sql The SQL statement. * @param catalog The catalog. - * @param resultSetType a result set type; one of {@code ResultSet.TYPE_FORWARD_ONLY}, - * {@code ResultSet.TYPE_SCROLL_INSENSITIVE}, or {@code ResultSet.TYPE_SCROLL_SENSITIVE}. - * @param resultSetConcurrency A concurrency type; one of {@code ResultSet.CONCUR_READ_ONLY} or - * {@code ResultSet.CONCUR_UPDATABLE} - * @param resultSetHoldability One of the following {@code ResultSet} constants: - * {@code ResultSet.HOLD_CURSORS_OVER_COMMIT} or {@code ResultSet.CLOSE_CURSORS_AT_COMMIT}. + * @param resultSetType a result set type; one of {@link ResultSet#TYPE_FORWARD_ONLY}, + * {@link ResultSet#TYPE_SCROLL_INSENSITIVE}, or {@link ResultSet#TYPE_SCROLL_SENSITIVE}. + * @param resultSetConcurrency A concurrency type; one of {@link ResultSet#CONCUR_READ_ONLY} or + * {@link ResultSet#CONCUR_UPDATABLE} + * @param resultSetHoldability One of the following {@link ResultSet} constants: + * {@link ResultSet#HOLD_CURSORS_OVER_COMMIT} or {@link ResultSet#CLOSE_CURSORS_AT_COMMIT}. * @deprecated Use {@link #PStmtKey(String, String, String, int, int, int)}. */ @Deprecated @@ -212,12 +213,12 @@ * * @param sql The SQL statement. * @param catalog The catalog. - * @param resultSetType a result set type; one of {@code ResultSet.TYPE_FORWARD_ONLY}, - * {@code ResultSet.TYPE_SCROLL_INSENSITIVE}, or {@code ResultSet.TYPE_SCROLL_SENSITIVE} - * @param resultSetConcurrency A concurrency type; one of {@code ResultSet.CONCUR_READ_ONLY} or - * {@code ResultSet.CONCUR_UPDATABLE}. - * @param resultSetHoldability One of the following {@code ResultSet} constants: - * {@code ResultSet.HOLD_CURSORS_OVER_COMMIT} or {@code ResultSet.CLOSE_CURSORS_AT_COMMIT}. + * @param resultSetType a result set type; one of {@link ResultSet#TYPE_FORWARD_ONLY}, + * {@link ResultSet#TYPE_SCROLL_INSENSITIVE}, or {@link ResultSet#TYPE_SCROLL_SENSITIVE} + * @param resultSetConcurrency A concurrency type; one of {@link ResultSet#CONCUR_READ_ONLY} or + * {@link ResultSet#CONCUR_UPDATABLE}. + * @param resultSetHoldability One of the following {@link ResultSet} constants: + * {@link ResultSet#HOLD_CURSORS_OVER_COMMIT} or {@link ResultSet#CLOSE_CURSORS_AT_COMMIT}. * @param statementType The SQL statement type, prepared or callable. * @deprecated Use {@link #PStmtKey(String, String, String, int, int, int, PoolingConnection.StatementType)} */ @@ -225,7 +226,7 @@ public PStmtKey(final String sql, final String catalog, final int resultSetType, final int resultSetConcurrency, final int resultSetHoldability, final StatementType statementType) { this(sql, catalog, null, Integer.valueOf(resultSetType), Integer.valueOf(resultSetConcurrency), Integer.valueOf(resultSetHoldability), null, null, null, statementType, - k -> match(statementType, StatementHoldability, CallHoldability)); + k -> match(statementType, StatementHoldability, CallHoldability)); } /** @@ -233,17 +234,17 @@ * * @param sql The SQL statement. * @param catalog The catalog. - * @param resultSetType A result set type; one of {@code ResultSet.TYPE_FORWARD_ONLY}, - * {@code ResultSet.TYPE_SCROLL_INSENSITIVE}, or {@code ResultSet.TYPE_SCROLL_SENSITIVE}. - * @param resultSetConcurrency A concurrency type; one of {@code ResultSet.CONCUR_READ_ONLY} or - * {@code ResultSet.CONCUR_UPDATABLE}. + * @param resultSetType A result set type; one of {@link ResultSet#TYPE_FORWARD_ONLY}, + * {@link ResultSet#TYPE_SCROLL_INSENSITIVE}, or {@link ResultSet#TYPE_SCROLL_SENSITIVE}. + * @param resultSetConcurrency A concurrency type; one of {@link ResultSet#CONCUR_READ_ONLY} or + * {@link ResultSet#CONCUR_UPDATABLE}. * @param statementType The SQL statement type, prepared or callable. * @deprecated Use {@link #PStmtKey(String, String, String, int, int, PoolingConnection.StatementType)}. */ @Deprecated public PStmtKey(final String sql, final String catalog, final int resultSetType, final int resultSetConcurrency, final StatementType statementType) { this(sql, catalog, null, Integer.valueOf(resultSetType), Integer.valueOf(resultSetConcurrency), null, null, null, null, statementType, - k -> match(statementType, StatementConcurrency, CallConcurrency)); + k -> match(statementType, StatementConcurrency, CallConcurrency)); } /** @@ -280,13 +281,13 @@ * @param catalog The catalog. * @param statementType The SQL statement type, prepared or callable. * @param autoGeneratedKeys A flag indicating whether auto-generated keys should be returned; one of - * {@code Statement.RETURN_GENERATED_KEYS} or {@code Statement.NO_GENERATED_KEYS}. + * {@link Statement#RETURN_GENERATED_KEYS} or {@link Statement#NO_GENERATED_KEYS}. * @deprecated Use {@link #PStmtKey(String, String, String, PoolingConnection.StatementType, Integer)} */ @Deprecated public PStmtKey(final String sql, final String catalog, final StatementType statementType, final Integer autoGeneratedKeys) { this(sql, catalog, null, null, null, null, autoGeneratedKeys, null, null, statementType, - k -> match(statementType, StatementAutoGeneratedKeys, CallSQL)); + k -> match(statementType, StatementAutoGeneratedKeys, CallSQL)); } /** @@ -308,7 +309,7 @@ * @param catalog The catalog. * @param schema The schema * @param autoGeneratedKeys A flag indicating whether auto-generated keys should be returned; one of - * {@code Statement.RETURN_GENERATED_KEYS} or {@code Statement.NO_GENERATED_KEYS}. + * {@link Statement#RETURN_GENERATED_KEYS} or {@link Statement#NO_GENERATED_KEYS}. * @since 2.5.0 */ public PStmtKey(final String sql, final String catalog, final String schema, final int autoGeneratedKeys) { @@ -321,10 +322,10 @@ * @param sql The SQL statement. * @param catalog The catalog. * @param schema The schema - * @param resultSetType A result set type; one of {@code ResultSet.TYPE_FORWARD_ONLY}, - * {@code ResultSet.TYPE_SCROLL_INSENSITIVE}, or {@code ResultSet.TYPE_SCROLL_SENSITIVE}. - * @param resultSetConcurrency A concurrency type; one of {@code ResultSet.CONCUR_READ_ONLY} or - * {@code ResultSet.CONCUR_UPDATABLE}. + * @param resultSetType A result set type; one of {@link ResultSet#TYPE_FORWARD_ONLY}, + * {@link ResultSet#TYPE_SCROLL_INSENSITIVE}, or {@link ResultSet#TYPE_SCROLL_SENSITIVE}. + * @param resultSetConcurrency A concurrency type; one of {@link ResultSet#CONCUR_READ_ONLY} or + * {@link ResultSet#CONCUR_UPDATABLE}. */ public PStmtKey(final String sql, final String catalog, final String schema, final int resultSetType, final int resultSetConcurrency) { this(sql, catalog, schema, resultSetType, resultSetConcurrency, StatementType.PREPARED_STATEMENT); @@ -336,12 +337,12 @@ * @param sql The SQL statement. * @param catalog The catalog. * @param schema The schema - * @param resultSetType a result set type; one of {@code ResultSet.TYPE_FORWARD_ONLY}, - * {@code ResultSet.TYPE_SCROLL_INSENSITIVE}, or {@code ResultSet.TYPE_SCROLL_SENSITIVE}. - * @param resultSetConcurrency A concurrency type; one of {@code ResultSet.CONCUR_READ_ONLY} or - * {@code ResultSet.CONCUR_UPDATABLE} - * @param resultSetHoldability One of the following {@code ResultSet} constants: - * {@code ResultSet.HOLD_CURSORS_OVER_COMMIT} or {@code ResultSet.CLOSE_CURSORS_AT_COMMIT}. + * @param resultSetType a result set type; one of {@link ResultSet#TYPE_FORWARD_ONLY}, + * {@link ResultSet#TYPE_SCROLL_INSENSITIVE}, or {@link ResultSet#TYPE_SCROLL_SENSITIVE}. + * @param resultSetConcurrency A concurrency type; one of {@link ResultSet#CONCUR_READ_ONLY} or + * {@link ResultSet#CONCUR_UPDATABLE} + * @param resultSetHoldability One of the following {@link ResultSet} constants: + * {@link ResultSet#HOLD_CURSORS_OVER_COMMIT} or {@link ResultSet#CLOSE_CURSORS_AT_COMMIT}. * @since 2.5.0 */ public PStmtKey(final String sql, final String catalog, final String schema, final int resultSetType, final int resultSetConcurrency, @@ -355,19 +356,19 @@ * @param sql The SQL statement. * @param catalog The catalog. * @param schema The schema. - * @param resultSetType a result set type; one of {@code ResultSet.TYPE_FORWARD_ONLY}, - * {@code ResultSet.TYPE_SCROLL_INSENSITIVE}, or {@code ResultSet.TYPE_SCROLL_SENSITIVE} - * @param resultSetConcurrency A concurrency type; one of {@code ResultSet.CONCUR_READ_ONLY} or - * {@code ResultSet.CONCUR_UPDATABLE}. - * @param resultSetHoldability One of the following {@code ResultSet} constants: - * {@code ResultSet.HOLD_CURSORS_OVER_COMMIT} or {@code ResultSet.CLOSE_CURSORS_AT_COMMIT}. + * @param resultSetType a result set type; one of {@link ResultSet#TYPE_FORWARD_ONLY}, + * {@link ResultSet#TYPE_SCROLL_INSENSITIVE}, or {@link ResultSet#TYPE_SCROLL_SENSITIVE} + * @param resultSetConcurrency A concurrency type; one of {@link ResultSet#CONCUR_READ_ONLY} or + * {@link ResultSet#CONCUR_UPDATABLE}. + * @param resultSetHoldability One of the following {@link ResultSet} constants: + * {@link ResultSet#HOLD_CURSORS_OVER_COMMIT} or {@link ResultSet#CLOSE_CURSORS_AT_COMMIT}. * @param statementType The SQL statement type, prepared or callable. * @since 2.5.0 */ public PStmtKey(final String sql, final String catalog, final String schema, final int resultSetType, final int resultSetConcurrency, final int resultSetHoldability, final StatementType statementType) { this(sql, catalog, schema, Integer.valueOf(resultSetType), Integer.valueOf(resultSetConcurrency), Integer.valueOf(resultSetHoldability), null, null, null, statementType, - k -> match(statementType, StatementHoldability, CallHoldability)); + k -> match(statementType, StatementHoldability, CallHoldability)); } /** @@ -376,17 +377,17 @@ * @param sql The SQL statement. * @param catalog The catalog. * @param schema The schema. - * @param resultSetType A result set type; one of {@code ResultSet.TYPE_FORWARD_ONLY}, - * {@code ResultSet.TYPE_SCROLL_INSENSITIVE}, or {@code ResultSet.TYPE_SCROLL_SENSITIVE}. - * @param resultSetConcurrency A concurrency type; one of {@code ResultSet.CONCUR_READ_ONLY} or - * {@code ResultSet.CONCUR_UPDATABLE}. + * @param resultSetType A result set type; one of {@link ResultSet#TYPE_FORWARD_ONLY}, + * {@link ResultSet#TYPE_SCROLL_INSENSITIVE}, or {@link ResultSet#TYPE_SCROLL_SENSITIVE}. + * @param resultSetConcurrency A concurrency type; one of {@link ResultSet#CONCUR_READ_ONLY} or + * {@link ResultSet#CONCUR_UPDATABLE}. * @param statementType The SQL statement type, prepared or callable. * @since 2.5.0 */ public PStmtKey(final String sql, final String catalog, final String schema, final int resultSetType, final int resultSetConcurrency, final StatementType statementType) { this(sql, catalog, schema, Integer.valueOf(resultSetType), Integer.valueOf(resultSetConcurrency), null, null, null, null, statementType, - k -> match(statementType, StatementConcurrency, CallConcurrency)); + k -> match(statementType, StatementConcurrency, CallConcurrency)); } /** @@ -403,8 +404,8 @@ } private PStmtKey(final String sql, final String catalog, final String schema, final Integer resultSetType, final Integer resultSetConcurrency, - final Integer resultSetHoldability, final Integer autoGeneratedKeys, final int[] columnIndexes, final String[] columnNames, - final StatementType statementType, final Function statementBuilder) { + final Integer resultSetHoldability, final Integer autoGeneratedKeys, final int[] columnIndexes, final String[] columnNames, + final StatementType statementType, final Function statementBuilder) { this.sql = Objects.requireNonNull(sql, "sql").trim(); this.catalog = catalog; this.schema = schema; @@ -420,8 +421,8 @@ // Root constructor. private PStmtKey(final String sql, final String catalog, final String schema, final Integer resultSetType, final Integer resultSetConcurrency, - final Integer resultSetHoldability, final Integer autoGeneratedKeys, final int[] columnIndexes, final String[] columnNames, - final StatementType statementType, final StatementBuilder statementBuilder) { + final Integer resultSetHoldability, final Integer autoGeneratedKeys, final int[] columnIndexes, final String[] columnNames, + final StatementType statementType, final StatementBuilder statementBuilder) { this.sql = sql; this.catalog = catalog; this.schema = schema; @@ -456,12 +457,12 @@ * @param schema The schema. * @param statementType The SQL statement type, prepared or callable. * @param autoGeneratedKeys A flag indicating whether auto-generated keys should be returned; one of - * {@code Statement.RETURN_GENERATED_KEYS} or {@code Statement.NO_GENERATED_KEYS}. + * {@link Statement#RETURN_GENERATED_KEYS} or {@link Statement#NO_GENERATED_KEYS}. * @since 2.5.0 */ public PStmtKey(final String sql, final String catalog, final String schema, final StatementType statementType, final Integer autoGeneratedKeys) { this(sql, catalog, schema, null, null, null, autoGeneratedKeys, null, null, statementType, - k -> match(statementType, StatementAutoGeneratedKeys, CallSQL)); + k -> match(statementType, StatementAutoGeneratedKeys, CallSQL)); } /** @@ -516,35 +517,16 @@ if (this == obj) { return true; } - if (obj == null) { - return false; - } - if (getClass() != obj.getClass()) { + if (obj == null || getClass() != obj.getClass()) { return false; } final PStmtKey other = (PStmtKey) obj; - if (!Objects.equals(autoGeneratedKeys, other.autoGeneratedKeys)) { - return false; - } - if (!Objects.equals(catalog, other.catalog)) { - return false; - } - if (!Arrays.equals(columnIndexes, other.columnIndexes)) { - return false; - } - if (!Arrays.equals(columnNames, other.columnNames)) { - return false; - } - if (!Objects.equals(resultSetConcurrency, other.resultSetConcurrency)) { - return false; - } - if (!Objects.equals(resultSetHoldability, other.resultSetHoldability)) { - return false; - } - if (!Objects.equals(resultSetType, other.resultSetType)) { + if (!Objects.equals(autoGeneratedKeys, other.autoGeneratedKeys) || !Objects.equals(catalog, other.catalog) + || !Arrays.equals(columnIndexes, other.columnIndexes) || !Arrays.equals(columnNames, other.columnNames)) { return false; } - if (!Objects.equals(schema, other.schema)) { + if (!Objects.equals(resultSetConcurrency, other.resultSetConcurrency) || !Objects.equals(resultSetHoldability, other.resultSetHoldability) + || !Objects.equals(resultSetType, other.resultSetType) || !Objects.equals(schema, other.schema)) { return false; } if (!Objects.equals(sql, other.sql)) { @@ -554,8 +536,8 @@ } /** - * Gets a flag indicating whether auto-generated keys should be returned; one of {@code Statement.RETURN_GENERATED_KEYS} - * or {@code Statement.NO_GENERATED_KEYS}. + * Gets a flag indicating whether auto-generated keys should be returned; one of {@link Statement#RETURN_GENERATED_KEYS} + * or {@link Statement#NO_GENERATED_KEYS}. * * @return a flag indicating whether auto-generated keys should be returned. */ @@ -591,8 +573,8 @@ } /** - * Gets the result set concurrency type; one of {@code ResultSet.CONCUR_READ_ONLY} or - * {@code ResultSet.CONCUR_UPDATABLE}. + * Gets the result set concurrency type; one of {@link ResultSet#CONCUR_READ_ONLY} or + * {@link ResultSet#CONCUR_UPDATABLE}. * * @return The result set concurrency type. */ @@ -601,8 +583,8 @@ } /** - * Gets the result set holdability, one of the following {@code ResultSet} constants: - * {@code ResultSet.HOLD_CURSORS_OVER_COMMIT} or {@code ResultSet.CLOSE_CURSORS_AT_COMMIT}. + * Gets the result set holdability, one of the following {@link ResultSet} constants: + * {@link ResultSet#HOLD_CURSORS_OVER_COMMIT} or {@link ResultSet#CLOSE_CURSORS_AT_COMMIT}. * * @return The result set holdability. */ @@ -611,8 +593,8 @@ } /** - * Gets the result set type, one of {@code ResultSet.TYPE_FORWARD_ONLY}, {@code ResultSet.TYPE_SCROLL_INSENSITIVE}, or - * {@code ResultSet.TYPE_SCROLL_SENSITIVE}. + * Gets the result set type, one of {@link ResultSet#TYPE_FORWARD_ONLY}, {@link ResultSet#TYPE_SCROLL_INSENSITIVE}, or + * {@link ResultSet#TYPE_SCROLL_SENSITIVE}. * * @return the result set type. */ @@ -650,7 +632,7 @@ @Override public int hashCode() { return Objects.hash(autoGeneratedKeys, catalog, Integer.valueOf(Arrays.hashCode(columnIndexes)), Integer.valueOf(Arrays.hashCode(columnNames)), - resultSetConcurrency, resultSetHoldability, resultSetType, schema, sql, statementType); + resultSetConcurrency, resultSetHoldability, resultSetType, schema, sql, statementType); } @Override diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/dbcp/dbcp2/PoolableCallableStatement.java tomcat10-10.1.52/java/org/apache/tomcat/dbcp/dbcp2/PoolableCallableStatement.java --- tomcat10-10.1.40/java/org/apache/tomcat/dbcp/dbcp2/PoolableCallableStatement.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/dbcp/dbcp2/PoolableCallableStatement.java 2026-01-23 19:33:36.000000000 +0000 @@ -6,7 +6,7 @@ * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/dbcp/dbcp2/PoolableConnection.java tomcat10-10.1.52/java/org/apache/tomcat/dbcp/dbcp2/PoolableConnection.java --- tomcat10-10.1.40/java/org/apache/tomcat/dbcp/dbcp2/PoolableConnection.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/dbcp/dbcp2/PoolableConnection.java 2026-01-23 19:33:36.000000000 +0000 @@ -6,7 +6,7 @@ * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -24,6 +24,7 @@ import java.time.Duration; import java.util.Collection; import java.util.concurrent.Executor; +import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; @@ -59,8 +60,9 @@ private final ObjectNameWrapper jmxObjectName; - // Use a prepared statement for validation, retaining the last used SQL to - // check if the validation query has changed. + /** + * Use a prepared statement for validation, retaining the last used SQL to check if the validation query has changed. + */ private PreparedStatement validationPreparedStatement; private String lastValidationSql; @@ -68,7 +70,7 @@ * Indicate that unrecoverable SQLException was thrown when using this connection. Such a connection should be * considered broken and not pass validation in the future. */ - private boolean fatalSqlExceptionThrown; + private final AtomicBoolean fatalSqlExceptionThrown = new AtomicBoolean(); /** * SQL State codes considered to signal fatal conditions. Overrides the defaults in @@ -83,13 +85,14 @@ */ private final Collection disconnectionIgnoreSqlCodes; - /** Whether or not to fast fail validation after fatal connection errors */ private final boolean fastFailValidation; private final Lock lock = new ReentrantLock(); /** + * Constructs a new instance. + * * @param conn * my underlying connection * @param pool @@ -103,6 +106,8 @@ } /** + * Constructs a new instance. + * * @param conn * my underlying connection * @param pool @@ -237,6 +242,8 @@ } /** + * Gets the disconnection SQL codes. + * * @return The disconnection SQL codes. * @since 2.6.0 */ @@ -254,7 +261,7 @@ @Override protected void handleException(final SQLException e) throws SQLException { - fatalSqlExceptionThrown |= isFatalException(e); + fatalSqlExceptionThrown.compareAndSet(false, isFatalException(e)); super.handleException(e); } @@ -264,6 +271,7 @@ * This method should not be used by a client to determine whether or not a connection should be return to the * connection pool (by calling {@link #close()}). Clients should always attempt to return a connection to the pool * once it is no longer required. + *

        */ @Override public boolean isClosed() throws SQLException { @@ -303,13 +311,15 @@ return false; } fatalException = disconnectionSqlCodes == null - ? sqlState.startsWith(Utils.DISCONNECTION_SQL_CODE_PREFIX) || Utils.isDisconnectionSqlCode(sqlState) - : disconnectionSqlCodes.contains(sqlState); + ? sqlState.startsWith(Utils.DISCONNECTION_SQL_CODE_PREFIX) || Utils.isDisconnectionSqlCode(sqlState) + : disconnectionSqlCodes.contains(sqlState); } return fatalException; } /** + * Tests whether to fail-fast. + * * @return Whether to fail-fast. * @since 2.6.0 */ @@ -384,11 +394,11 @@ * Validates the connection, using the following algorithm: *
          *
        1. If {@code fastFailValidation} (constructor argument) is {@code true} and this connection has previously - * thrown a fatal disconnection exception, a {@code SQLException} is thrown.
        2. + * thrown a fatal disconnection exception, a {@link SQLException} is thrown. *
        3. If {@code sql} is null, the driver's #{@link Connection#isValid(int) isValid(timeout)} is called. If it - * returns {@code false}, {@code SQLException} is thrown; otherwise, this method returns successfully.
        4. - *
        5. If {@code sql} is not null, it is executed as a query and if the resulting {@code ResultSet} contains at - * least one row, this method returns successfully. If not, {@code SQLException} is thrown.
        6. + * returns {@code false}, {@link SQLException} is thrown; otherwise, this method returns successfully. + *
        7. If {@code sql} is not null, it is executed as a query and if the resulting {@link ResultSet} contains at + * least one row, this method returns successfully. If not, {@link SQLException} is thrown.
        8. *
        * * @param sql @@ -400,7 +410,7 @@ * @since 2.10.0 */ public void validate(final String sql, Duration timeoutDuration) throws SQLException { - if (fastFailValidation && fatalSqlExceptionThrown) { + if (fastFailValidation && fatalSqlExceptionThrown.get()) { throw new SQLException(Utils.getMessage("poolableConnection.validate.fastFail")); } @@ -438,11 +448,11 @@ * Validates the connection, using the following algorithm: *
          *
        1. If {@code fastFailValidation} (constructor argument) is {@code true} and this connection has previously - * thrown a fatal disconnection exception, a {@code SQLException} is thrown.
        2. + * thrown a fatal disconnection exception, a {@link SQLException} is thrown. *
        3. If {@code sql} is null, the driver's #{@link Connection#isValid(int) isValid(timeout)} is called. If it - * returns {@code false}, {@code SQLException} is thrown; otherwise, this method returns successfully.
        4. - *
        5. If {@code sql} is not null, it is executed as a query and if the resulting {@code ResultSet} contains at - * least one row, this method returns successfully. If not, {@code SQLException} is thrown.
        6. + * returns {@code false}, {@link SQLException} is thrown; otherwise, this method returns successfully. + *
        7. If {@code sql} is not null, it is executed as a query and if the resulting {@link ResultSet} contains at + * least one row, this method returns successfully. If not, {@link SQLException} is thrown.
        8. *
        * * @param sql diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/dbcp/dbcp2/PoolableConnectionFactory.java tomcat10-10.1.52/java/org/apache/tomcat/dbcp/dbcp2/PoolableConnectionFactory.java --- tomcat10-10.1.40/java/org/apache/tomcat/dbcp/dbcp2/PoolableConnectionFactory.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/dbcp/dbcp2/PoolableConnectionFactory.java 2026-01-23 19:33:36.000000000 +0000 @@ -6,7 +6,7 @@ * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -66,7 +66,7 @@ private Collection disconnectionIgnoreSqlCodes; - private boolean fastFailValidation = true; + private volatile boolean fastFailValidation = true; private volatile ObjectPool pool; @@ -74,23 +74,23 @@ private Boolean defaultAutoCommit; - private boolean autoCommitOnReturn = true; + private volatile boolean autoCommitOnReturn = true; - private boolean rollbackOnReturn = true; + private volatile boolean rollbackOnReturn = true; - private int defaultTransactionIsolation = UNKNOWN_TRANSACTION_ISOLATION; + private volatile int defaultTransactionIsolation = UNKNOWN_TRANSACTION_ISOLATION; private String defaultCatalog; private String defaultSchema; - private boolean cacheState; + private volatile boolean cacheState; - private boolean poolStatements; + private volatile boolean poolStatements; - private boolean clearStatementPoolOnReturn; + private volatile boolean clearStatementPoolOnReturn; - private int maxOpenPreparedStatements = GenericKeyedObjectPoolConfig.DEFAULT_MAX_TOTAL_PER_KEY; + private volatile int maxOpenPreparedStatements = GenericKeyedObjectPoolConfig.DEFAULT_MAX_TOTAL_PER_KEY; private Duration maxConnDuration = Duration.ofMillis(-1); @@ -99,7 +99,7 @@ private Duration defaultQueryTimeoutDuration; /** - * Creates a new {@code PoolableConnectionFactory}. + * Creates a new {@link PoolableConnectionFactory}. * * @param connFactory * the {@link ConnectionFactory} from which to obtain base {@link Connection}s @@ -113,29 +113,26 @@ @Override public void activateObject(final PooledObject p) throws SQLException { - validateLifetime(p); - - final PoolableConnection pConnection = p.getObject(); - pConnection.activate(); - - if (defaultAutoCommit != null && pConnection.getAutoCommit() != defaultAutoCommit.booleanValue()) { - pConnection.setAutoCommit(defaultAutoCommit.booleanValue()); + final PoolableConnection poolableConnection = p.getObject(); + poolableConnection.activate(); + if (defaultAutoCommit != null && poolableConnection.getAutoCommit() != defaultAutoCommit.booleanValue()) { + poolableConnection.setAutoCommit(defaultAutoCommit.booleanValue()); } if (defaultTransactionIsolation != UNKNOWN_TRANSACTION_ISOLATION - && pConnection.getTransactionIsolation() != defaultTransactionIsolation) { - pConnection.setTransactionIsolation(defaultTransactionIsolation); + && poolableConnection.getTransactionIsolation() != defaultTransactionIsolation) { + poolableConnection.setTransactionIsolation(defaultTransactionIsolation); } - if (defaultReadOnly != null && pConnection.isReadOnly() != defaultReadOnly.booleanValue()) { - pConnection.setReadOnly(defaultReadOnly.booleanValue()); + if (defaultReadOnly != null && poolableConnection.isReadOnly() != defaultReadOnly.booleanValue()) { + poolableConnection.setReadOnly(defaultReadOnly.booleanValue()); } - if (defaultCatalog != null && !defaultCatalog.equals(pConnection.getCatalog())) { - pConnection.setCatalog(defaultCatalog); + if (defaultCatalog != null && !defaultCatalog.equals(poolableConnection.getCatalog())) { + poolableConnection.setCatalog(defaultCatalog); } - if (defaultSchema != null && !defaultSchema.equals(Jdbc41Bridge.getSchema(pConnection))) { - Jdbc41Bridge.setSchema(pConnection, defaultSchema); + if (defaultSchema != null && !defaultSchema.equals(Jdbc41Bridge.getSchema(poolableConnection))) { + Jdbc41Bridge.setSchema(poolableConnection, defaultSchema); } - pConnection.setDefaultQueryTimeout(defaultQueryTimeoutDuration); + poolableConnection.setDefaultQueryTimeout(defaultQueryTimeoutDuration); } @Override @@ -699,8 +696,8 @@ * @param disconnectionSqlCodes * The disconnection SQL codes. * @see #getDisconnectionSqlCodes() - * @since 2.1 * @throws IllegalArgumentException if any SQL state codes overlap with those in {@link #disconnectionIgnoreSqlCodes}. + * @since 2.1 */ public void setDisconnectionSqlCodes(final Collection disconnectionSqlCodes) { Utils.checkSqlCodes(disconnectionSqlCodes, this.disconnectionIgnoreSqlCodes); @@ -718,9 +715,10 @@ } /** + * Sets whether connections created by this factory will fast fail validation. + * + * @param fastFailValidation true means connections created by this factory will fast fail validation * @see #isFastFailValidation() - * @param fastFailValidation - * true means connections created by this factory will fast fail validation * @since 2.1 */ public void setFastFailValidation(final boolean fastFailValidation) { diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/dbcp/dbcp2/PoolableConnectionMXBean.java tomcat10-10.1.52/java/org/apache/tomcat/dbcp/dbcp2/PoolableConnectionMXBean.java --- tomcat10-10.1.40/java/org/apache/tomcat/dbcp/dbcp2/PoolableConnectionMXBean.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/dbcp/dbcp2/PoolableConnectionMXBean.java 2026-01-23 19:33:36.000000000 +0000 @@ -6,7 +6,7 @@ * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/dbcp/dbcp2/PoolablePreparedStatement.java tomcat10-10.1.52/java/org/apache/tomcat/dbcp/dbcp2/PoolablePreparedStatement.java --- tomcat10-10.1.40/java/org/apache/tomcat/dbcp/dbcp2/PoolablePreparedStatement.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/dbcp/dbcp2/PoolablePreparedStatement.java 2026-01-23 19:33:36.000000000 +0000 @@ -6,7 +6,7 @@ * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/dbcp/dbcp2/PoolingConnection.java tomcat10-10.1.52/java/org/apache/tomcat/dbcp/dbcp2/PoolingConnection.java --- tomcat10-10.1.40/java/org/apache/tomcat/dbcp/dbcp2/PoolingConnection.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/dbcp/dbcp2/PoolingConnection.java 2026-01-23 19:33:36.000000000 +0000 @@ -6,7 +6,7 @@ * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -74,9 +74,9 @@ } /** Pool of {@link PreparedStatement}s. and {@link CallableStatement}s */ - private KeyedObjectPool pStmtPool; + private KeyedObjectPool stmtPool; - private boolean clearStatementPoolOnReturn; + private volatile boolean clearStatementPoolOnReturn; /** * Constructs a new instance. @@ -109,9 +109,9 @@ @Override public synchronized void close() throws SQLException { try { - if (null != pStmtPool) { - final KeyedObjectPool oldPool = pStmtPool; - pStmtPool = null; + if (null != stmtPool) { + final KeyedObjectPool oldPool = stmtPool; + stmtPool = null; try { oldPool.close(); } catch (final RuntimeException e) { @@ -140,9 +140,9 @@ * @since 2.8.0 */ public void connectionReturnedToPool() throws SQLException { - if (pStmtPool != null && clearStatementPoolOnReturn) { + if (stmtPool != null && clearStatementPoolOnReturn) { try { - pStmtPool.clear(); + stmtPool.clear(); } catch (final Exception e) { throw new SQLException("Error clearing statement pool", e); } @@ -168,7 +168,7 @@ * the SQL string used to define the statement * @param autoGeneratedKeys * A flag indicating whether auto-generated keys should be returned; one of - * {@code Statement.RETURN_GENERATED_KEYS} or {@code Statement.NO_GENERATED_KEYS}. + * {@link Statement#RETURN_GENERATED_KEYS} or {@link Statement#NO_GENERATED_KEYS}. * * @return the PStmtKey created for the given arguments. */ @@ -341,7 +341,7 @@ * @since 2.8.0 */ public KeyedObjectPool getStatementPool() { - return pStmtPool; + return stmtPool; } /** @@ -361,11 +361,11 @@ if (key.getStmtType() == StatementType.PREPARED_STATEMENT) { final PreparedStatement statement = (PreparedStatement) key.createStatement(getDelegate()); @SuppressWarnings({"rawtypes", "unchecked" }) // Unable to find way to avoid this - final PoolablePreparedStatement pps = new PoolablePreparedStatement(statement, key, pStmtPool, this); + final PoolablePreparedStatement pps = new PoolablePreparedStatement(statement, key, stmtPool, this); return new DefaultPooledObject<>(pps); } final CallableStatement statement = (CallableStatement) key.createStatement(getDelegate()); - final PoolableCallableStatement pcs = new PoolableCallableStatement(statement, key, pStmtPool, this); + final PoolableCallableStatement pcs = new PoolableCallableStatement(statement, key, stmtPool, this); return new DefaultPooledObject<>(pcs); } @@ -474,11 +474,11 @@ * Wraps an underlying exception. */ private PreparedStatement prepareStatement(final PStmtKey key) throws SQLException { - if (null == pStmtPool) { + if (null == stmtPool) { throw new SQLException("Statement pool is null - closed or invalid PoolingConnection."); } try { - return pStmtPool.borrowObject(key); + return stmtPool.borrowObject(key); } catch (final NoSuchElementException e) { throw new SQLException("MaxOpenPreparedStatements limit reached", e); } catch (final RuntimeException e) { @@ -509,7 +509,7 @@ * the SQL string used to define the PreparedStatement * @param autoGeneratedKeys * A flag indicating whether auto-generated keys should be returned; one of - * {@code Statement.RETURN_GENERATED_KEYS} or {@code Statement.NO_GENERATED_KEYS}. + * {@link Statement#RETURN_GENERATED_KEYS} or {@link Statement#NO_GENERATED_KEYS}. * @return a {@link PoolablePreparedStatement} * @throws SQLException * Wraps an underlying exception. @@ -610,19 +610,19 @@ * the prepared statement pool. */ public void setStatementPool(final KeyedObjectPool pool) { - pStmtPool = pool; + stmtPool = pool; } @Override public synchronized String toString() { - if (pStmtPool instanceof GenericKeyedObjectPool) { + if (stmtPool instanceof GenericKeyedObjectPool) { // DBCP-596 PoolingConnection.toString() causes StackOverflowError - final GenericKeyedObjectPool gkop = (GenericKeyedObjectPool) pStmtPool; + final GenericKeyedObjectPool gkop = (GenericKeyedObjectPool) stmtPool; if (gkop.getFactory() == this) { - return "PoolingConnection: " + pStmtPool.getClass() + "@" + System.identityHashCode(pStmtPool); + return "PoolingConnection: " + stmtPool.getClass() + "@" + System.identityHashCode(stmtPool); } } - return "PoolingConnection: " + Objects.toString(pStmtPool); + return "PoolingConnection: " + Objects.toString(stmtPool); } /** diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/dbcp/dbcp2/PoolingDataSource.java tomcat10-10.1.52/java/org/apache/tomcat/dbcp/dbcp2/PoolingDataSource.java --- tomcat10-10.1.40/java/org/apache/tomcat/dbcp/dbcp2/PoolingDataSource.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/dbcp/dbcp2/PoolingDataSource.java 2026-01-23 19:33:36.000000000 +0000 @@ -6,7 +6,7 @@ * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -129,7 +129,7 @@ } /** - * Returns a {@link java.sql.Connection} from my pool, according to the contract specified by + * Returns a {@link Connection} from my pool, according to the contract specified by * {@link ObjectPool#borrowObject}. */ @Override @@ -164,7 +164,6 @@ throw new UnsupportedOperationException(); } - /** * Throws {@link UnsupportedOperationException}. * diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/dbcp/dbcp2/PoolingDriver.java tomcat10-10.1.52/java/org/apache/tomcat/dbcp/dbcp2/PoolingDriver.java --- tomcat10-10.1.40/java/org/apache/tomcat/dbcp/dbcp2/PoolingDriver.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/dbcp/dbcp2/PoolingDriver.java 2026-01-23 19:33:36.000000000 +0000 @@ -6,7 +6,7 @@ * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/dbcp/dbcp2/SQLExceptionList.java tomcat10-10.1.52/java/org/apache/tomcat/dbcp/dbcp2/SQLExceptionList.java --- tomcat10-10.1.40/java/org/apache/tomcat/dbcp/dbcp2/SQLExceptionList.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/dbcp/dbcp2/SQLExceptionList.java 2026-01-23 19:33:36.000000000 +0000 @@ -6,7 +6,7 @@ * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -31,6 +31,10 @@ public class SQLExceptionList extends SQLException { private static final long serialVersionUID = 1L; + + /** + * The list of causes. + */ private final List causeList; /** diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/dbcp/dbcp2/SwallowedExceptionLogger.java tomcat10-10.1.52/java/org/apache/tomcat/dbcp/dbcp2/SwallowedExceptionLogger.java --- tomcat10-10.1.40/java/org/apache/tomcat/dbcp/dbcp2/SwallowedExceptionLogger.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/dbcp/dbcp2/SwallowedExceptionLogger.java 2026-01-23 19:33:36.000000000 +0000 @@ -6,7 +6,7 @@ * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/dbcp/dbcp2/Utils.java tomcat10-10.1.52/java/org/apache/tomcat/dbcp/dbcp2/Utils.java --- tomcat10-10.1.40/java/org/apache/tomcat/dbcp/dbcp2/Utils.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/dbcp/dbcp2/Utils.java 2026-01-23 19:33:36.000000000 +0000 @@ -6,7 +6,7 @@ * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -39,7 +39,7 @@ public final class Utils { private static final ResourceBundle messages = ResourceBundle - .getBundle(Utils.class.getPackage().getName() + ".LocalStrings"); + .getBundle(Utils.class.getPackage().getName() + ".LocalStrings"); /** * Whether the security manager is enabled. @@ -50,7 +50,7 @@ public static final boolean IS_SECURITY_ENABLED = isSecurityEnabled(); /** - * Any SQL_STATE starting with this value is considered a fatal disconnect. + * Any SQL State starting with this value is considered a fatal disconnect. */ public static final String DISCONNECTION_SQL_CODE_PREFIX = "08"; diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/dbcp/dbcp2/cpdsadapter/ConnectionImpl.java tomcat10-10.1.52/java/org/apache/tomcat/dbcp/dbcp2/cpdsadapter/ConnectionImpl.java --- tomcat10-10.1.40/java/org/apache/tomcat/dbcp/dbcp2/cpdsadapter/ConnectionImpl.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/dbcp/dbcp2/cpdsadapter/ConnectionImpl.java 2026-01-23 19:33:36.000000000 +0000 @@ -6,7 +6,7 @@ * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -19,6 +19,7 @@ import java.sql.CallableStatement; import java.sql.Connection; import java.sql.PreparedStatement; +import java.sql.ResultSet; import java.sql.SQLException; import org.apache.tomcat.dbcp.dbcp2.DelegatingCallableStatement; @@ -26,9 +27,9 @@ import org.apache.tomcat.dbcp.dbcp2.DelegatingPreparedStatement; /** - * This class is the {@code Connection} that will be returned from - * {@code PooledConnectionImpl.getConnection()}. Most methods are wrappers around the JDBC 1.x - * {@code Connection}. A few exceptions include preparedStatement and close. In accordance with the JDBC + * This class is the {@link Connection} that will be returned from + * {@link PooledConnectionImpl#getConnection()}. Most methods are wrappers around the JDBC 1.x + * {@link Connection}. A few exceptions include preparedStatement and close. In accordance with the JDBC * specification this Connection cannot be used after closed() is called. Any further usage will result in an * SQLException. *

        @@ -131,13 +132,13 @@ } /** - * If pooling of {@code CallableStatement}s is turned on in the {@link DriverAdapterCPDS}, a pooled object may - * be returned, otherwise delegate to the wrapped JDBC 1.x {@link java.sql.Connection}. + * If pooling of {@link CallableStatement}s is turned on in the {@link DriverAdapterCPDS}, a pooled object may + * be returned, otherwise delegate to the wrapped JDBC 1.x {@link Connection}. * * @param sql * an SQL statement that may contain one or more '?' parameter placeholders. Typically, this statement is * specified using JDBC call escape syntax. - * @return a default {@code CallableStatement} object containing the pre-compiled SQL statement. + * @return a default {@link CallableStatement} object containing the pre-compiled SQL statement. * @throws SQLException * Thrown if a database access error occurs or this method is called on a closed connection. * @since 2.4.0 @@ -154,23 +155,23 @@ } /** - * If pooling of {@code CallableStatement}s is turned on in the {@link DriverAdapterCPDS}, a pooled object may - * be returned, otherwise delegate to the wrapped JDBC 1.x {@link java.sql.Connection}. + * If pooling of {@link CallableStatement}s is turned on in the {@link DriverAdapterCPDS}, a pooled object may + * be returned, otherwise delegate to the wrapped JDBC 1.x {@link Connection}. * * @param sql - * a {@code String} object that is the SQL statement to be sent to the database; may contain on or + * a {@link String} object that is the SQL statement to be sent to the database; may contain on or * more '?' parameters. * @param resultSetType - * a result set type; one of {@code ResultSet.TYPE_FORWARD_ONLY}, - * {@code ResultSet.TYPE_SCROLL_INSENSITIVE}, or {@code ResultSet.TYPE_SCROLL_SENSITIVE}. + * a result set type; one of {@link ResultSet#TYPE_FORWARD_ONLY}, + * {@link ResultSet#TYPE_SCROLL_INSENSITIVE}, or {@link ResultSet#TYPE_SCROLL_SENSITIVE}. * @param resultSetConcurrency - * a concurrency type; one of {@code ResultSet.CONCUR_READ_ONLY} or - * {@code ResultSet.CONCUR_UPDATABLE}. - * @return a {@code CallableStatement} object containing the pre-compiled SQL statement that will produce - * {@code ResultSet} objects with the given type and concurrency. + * a concurrency type; one of {@link ResultSet#CONCUR_READ_ONLY} or + * {@link ResultSet#CONCUR_UPDATABLE}. + * @return a {@link CallableStatement} object containing the pre-compiled SQL statement that will produce + * {@link ResultSet} objects with the given type and concurrency. * @throws SQLException * Thrown if a database access error occurs, this method is called on a closed connection or the given - * parameters are not {@code ResultSet} constants indicating type and concurrency. + * parameters are not {@link ResultSet} constants indicating type and concurrency. * @since 2.4.0 */ @Override @@ -187,26 +188,26 @@ } /** - * If pooling of {@code CallableStatement}s is turned on in the {@link DriverAdapterCPDS}, a pooled object may - * be returned, otherwise delegate to the wrapped JDBC 1.x {@link java.sql.Connection}. + * If pooling of {@link CallableStatement}s is turned on in the {@link DriverAdapterCPDS}, a pooled object may + * be returned, otherwise delegate to the wrapped JDBC 1.x {@link Connection}. * * @param sql - * a {@code String} object that is the SQL statement to be sent to the database; may contain on or + * a {@link String} object that is the SQL statement to be sent to the database; may contain on or * more '?' parameters. * @param resultSetType - * one of the following {@code ResultSet} constants: {@code ResultSet.TYPE_FORWARD_ONLY}, - * {@code ResultSet.TYPE_SCROLL_INSENSITIVE}, or {@code ResultSet.TYPE_SCROLL_SENSITIVE}. + * one of the following {@link ResultSet} constants: {@link ResultSet#TYPE_FORWARD_ONLY}, + * {@link ResultSet#TYPE_SCROLL_INSENSITIVE}, or {@link ResultSet#TYPE_SCROLL_SENSITIVE}. * @param resultSetConcurrency - * one of the following {@code ResultSet} constants: {@code ResultSet.CONCUR_READ_ONLY} or - * {@code ResultSet.CONCUR_UPDATABLE}. + * one of the following {@link ResultSet} constants: {@link ResultSet#CONCUR_READ_ONLY} or + * {@link ResultSet#CONCUR_UPDATABLE}. * @param resultSetHoldability - * one of the following {@code ResultSet} constants: {@code ResultSet.HOLD_CURSORS_OVER_COMMIT} - * or {@code ResultSet.CLOSE_CURSORS_AT_COMMIT}. - * @return a new {@code CallableStatement} object, containing the pre-compiled SQL statement, that will - * generate {@code ResultSet} objects with the given type, concurrency, and holdability. + * one of the following {@link ResultSet} constants: {@link ResultSet#HOLD_CURSORS_OVER_COMMIT} + * or {@link ResultSet#CLOSE_CURSORS_AT_COMMIT}. + * @return a new {@link CallableStatement} object, containing the pre-compiled SQL statement, that will + * generate {@link ResultSet} objects with the given type, concurrency, and holdability. * @throws SQLException * Thrown if a database access error occurs, this method is called on a closed connection or the given - * parameters are not {@code ResultSet} constants indicating type, concurrency, and holdability. + * parameters are not {@link ResultSet} constants indicating type, concurrency, and holdability. * @since 2.4.0 */ @Override @@ -223,8 +224,8 @@ } /** - * If pooling of {@code PreparedStatement}s is turned on in the {@link DriverAdapterCPDS}, a pooled object may - * be returned, otherwise delegate to the wrapped JDBC 1.x {@link java.sql.Connection}. + * If pooling of {@link PreparedStatement}s is turned on in the {@link DriverAdapterCPDS}, a pooled object may + * be returned, otherwise delegate to the wrapped JDBC 1.x {@link Connection}. * * @param sql * SQL statement to be prepared @@ -259,8 +260,8 @@ // /** - * If pooling of {@code PreparedStatement}s is turned on in the {@link DriverAdapterCPDS}, a pooled object may - * be returned, otherwise delegate to the wrapped JDBC 1.x {@link java.sql.Connection}. + * If pooling of {@link PreparedStatement}s is turned on in the {@link DriverAdapterCPDS}, a pooled object may + * be returned, otherwise delegate to the wrapped JDBC 1.x {@link Connection}. * * @throws SQLException * if this connection is closed or an error occurs in the wrapped connection. diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/dbcp/dbcp2/cpdsadapter/DriverAdapterCPDS.java tomcat10-10.1.52/java/org/apache/tomcat/dbcp/dbcp2/cpdsadapter/DriverAdapterCPDS.java --- tomcat10-10.1.40/java/org/apache/tomcat/dbcp/dbcp2/cpdsadapter/DriverAdapterCPDS.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/dbcp/dbcp2/cpdsadapter/DriverAdapterCPDS.java 2026-01-23 19:33:36.000000000 +0000 @@ -6,7 +6,7 @@ * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -18,7 +18,9 @@ import java.io.PrintWriter; import java.io.Serializable; +import java.sql.Connection; import java.sql.DriverManager; +import java.sql.PreparedStatement; import java.sql.SQLException; import java.sql.SQLFeatureNotSupportedException; import java.time.Duration; @@ -35,6 +37,7 @@ import javax.naming.StringRefAddr; import javax.naming.spi.ObjectFactory; import javax.sql.ConnectionPoolDataSource; +import javax.sql.DataSource; import javax.sql.PooledConnection; import org.apache.tomcat.dbcp.dbcp2.Constants; @@ -49,22 +52,22 @@ /** *

        * An adapter for JDBC drivers that do not include an implementation of {@link javax.sql.ConnectionPoolDataSource}, but - * still include a {@link java.sql.DriverManager} implementation. {@code ConnectionPoolDataSource}s are not used - * within general applications. They are used by {@code DataSource} implementations that pool - * {@code Connection}s, such as {@link org.apache.tomcat.dbcp.dbcp2.datasources.SharedPoolDataSource}. A J2EE container - * will normally provide some method of initializing the {@code ConnectionPoolDataSource} whose attributes are + * still include a {@link java.sql.DriverManager} implementation. {@link ConnectionPoolDataSource}s are not used + * within general applications. They are used by {@link DataSource} implementations that pool + * {@link Connection}s, such as {@link org.apache.tomcat.dbcp.dbcp2.datasources.SharedPoolDataSource}. A J2EE container + * will normally provide some method of initializing the {@link ConnectionPoolDataSource} whose attributes are * presented as bean getters/setters and then deploying it via JNDI. It is then available as a source of physical - * connections to the database, when the pooling {@code DataSource} needs to create a new physical connection. + * connections to the database, when the pooling {link DataSource} needs to create a new physical connection. *

        *

        * Although normally used within a JNDI environment, the DriverAdapterCPDS can be instantiated and initialized as any - * bean and then attached directly to a pooling {@code DataSource}. {@code Jdbc2PoolDataSource} can use the - * {@code ConnectionPoolDataSource} with or without the use of JNDI. + * bean and then attached directly to a pooling {link DataSource}. {@code Jdbc2PoolDataSource} can use the + * {link ConnectionPoolDataSource} with or without the use of JNDI. *

        *

        - * The DriverAdapterCPDS also provides {@code PreparedStatement} pooling which is not generally available in jdbc2 - * {@code ConnectionPoolDataSource} implementation, but is addressed within the JDBC 3 specification. The - * {@code PreparedStatement} pool in DriverAdapterCPDS has been in the DBCP package for some time, but it has not + * The DriverAdapterCPDS also provides {@link PreparedStatement} pooling which is not generally available in jdbc2 + * {@link ConnectionPoolDataSource} implementation, but is addressed within the JDBC 3 specification. The + * {@link PreparedStatement} pool in DriverAdapterCPDS has been in the DBCP package for some time, but it has not * undergone extensive testing in the configuration used here. It should be considered experimental and can be toggled * with the poolPreparedStatements attribute. *

        @@ -110,7 +113,7 @@ static { // Attempt to prevent deadlocks - see DBCP-272 - DriverManager.getDrivers(); + DriverManager.getDrivers(); // NOPMD } /** Description */ @@ -129,19 +132,28 @@ private String driver; /** Login TimeOut in seconds */ - private int loginTimeout; + private volatile int loginTimeout; /** Log stream. NOT USED */ private transient PrintWriter logWriter; - // PreparedStatement pool properties - private boolean poolPreparedStatements; - private int maxIdle = 10; + /** PreparedStatement pool property defaults to false. */ + private volatile boolean poolPreparedStatements; + + /** PreparedStatement pool property defaults to 10. */ + private volatile int maxIdle = 10; + + /** PreparedStatement pool property defaults to {@link BaseObjectPoolConfig#DEFAULT_DURATION_BETWEEN_EVICTION_RUNS}. */ private Duration durationBetweenEvictionRuns = BaseObjectPoolConfig.DEFAULT_DURATION_BETWEEN_EVICTION_RUNS; - private int numTestsPerEvictionRun = -1; + + /** PreparedStatement pool property defaults to -1. */ + private volatile int numTestsPerEvictionRun = -1; + + /** PreparedStatement pool property defaults to {@link BaseObjectPoolConfig#DEFAULT_MIN_EVICTABLE_IDLE_DURATION}. */ private Duration minEvictableIdleDuration = BaseObjectPoolConfig.DEFAULT_MIN_EVICTABLE_IDLE_DURATION; - private int maxPreparedStatements = -1; + /** Maximum number of prepared statements, defaults to -1, meaning no limit. */ + private volatile int maxPreparedStatements = -1; /** Whether or not getConnection has been called */ private volatile boolean getConnectionCalled; @@ -248,7 +260,7 @@ /** * Gets the maximum number of prepared statements. * - * @return maxPrepartedStatements value + * @return maxPrepartedStatements, defaults to -1, meaning no limit. */ public int getMaxPreparedStatements() { return maxPreparedStatements; @@ -537,7 +549,7 @@ } /** - * Whether to toggle the pooling of {@code PreparedStatement}s + * Tests whether to toggle the pooling of {@link PreparedStatement}s * * @return value of poolPreparedStatements. */ @@ -656,7 +668,7 @@ /** * Sets the maximum number of prepared statements. * - * @param maxPreparedStatements the new maximum number of prepared statements + * @param maxPreparedStatements the new maximum number of prepared statements, <= 0 means no limit. */ public void setMaxPreparedStatements(final int maxPreparedStatements) { this.maxPreparedStatements = maxPreparedStatements; @@ -736,7 +748,7 @@ } /** - * Whether to toggle the pooling of {@code PreparedStatement}s + * Sets whether to toggle the pooling of {@link PreparedStatement}s * * @param poolPreparedStatements true to pool statements. * @throws IllegalStateException if {@link #getPooledConnection()} has been called diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/dbcp/dbcp2/cpdsadapter/PStmtKeyCPDS.java tomcat10-10.1.52/java/org/apache/tomcat/dbcp/dbcp2/cpdsadapter/PStmtKeyCPDS.java --- tomcat10-10.1.40/java/org/apache/tomcat/dbcp/dbcp2/cpdsadapter/PStmtKeyCPDS.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/dbcp/dbcp2/cpdsadapter/PStmtKeyCPDS.java 2026-01-23 19:33:36.000000000 +0000 @@ -6,7 +6,7 @@ * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -17,6 +17,8 @@ package org.apache.tomcat.dbcp.dbcp2.cpdsadapter; import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.Statement; import org.apache.tomcat.dbcp.dbcp2.PStmtKey; @@ -46,7 +48,7 @@ * The SQL statement. * @param autoGeneratedKeys * A flag indicating whether auto-generated keys should be returned; one of - * {@code Statement.RETURN_GENERATED_KEYS} or {@code Statement.NO_GENERATED_KEYS}. + * {@link Statement#RETURN_GENERATED_KEYS} or {@link Statement#NO_GENERATED_KEYS}. */ public PStmtKeyCPDS(final String sql, final int autoGeneratedKeys) { super(sql, null, autoGeneratedKeys); @@ -58,11 +60,11 @@ * @param sql * The SQL statement. * @param resultSetType - * A result set type; one of {@code ResultSet.TYPE_FORWARD_ONLY}, - * {@code ResultSet.TYPE_SCROLL_INSENSITIVE}, or {@code ResultSet.TYPE_SCROLL_SENSITIVE}. + * A result set type; one of {@link ResultSet#TYPE_FORWARD_ONLY}, + * {@link ResultSet#TYPE_SCROLL_INSENSITIVE}, or {@link ResultSet#TYPE_SCROLL_SENSITIVE}. * @param resultSetConcurrency - * A concurrency type; one of {@code ResultSet.CONCUR_READ_ONLY} or - * {@code ResultSet.CONCUR_UPDATABLE}. + * A concurrency type; one of {@link ResultSet#CONCUR_READ_ONLY} or + * {@link ResultSet#CONCUR_UPDATABLE}. */ public PStmtKeyCPDS(final String sql, final int resultSetType, final int resultSetConcurrency) { super(sql, resultSetType, resultSetConcurrency); @@ -74,14 +76,14 @@ * @param sql * The SQL statement. * @param resultSetType - * a result set type; one of {@code ResultSet.TYPE_FORWARD_ONLY}, - * {@code ResultSet.TYPE_SCROLL_INSENSITIVE}, or {@code ResultSet.TYPE_SCROLL_SENSITIVE}. + * a result set type; one of {@link ResultSet#TYPE_FORWARD_ONLY}, + * {@link ResultSet#TYPE_SCROLL_INSENSITIVE}, or {@link ResultSet#TYPE_SCROLL_SENSITIVE}. * @param resultSetConcurrency - * A concurrency type; one of {@code ResultSet.CONCUR_READ_ONLY} or - * {@code ResultSet.CONCUR_UPDATABLE} + * A concurrency type; one of {@link ResultSet#CONCUR_READ_ONLY} or + * {@link ResultSet#CONCUR_UPDATABLE} * @param resultSetHoldability - * One of the following {@code ResultSet} constants: {@code ResultSet.HOLD_CURSORS_OVER_COMMIT} - * or {@code ResultSet.CLOSE_CURSORS_AT_COMMIT}. + * One of the following {@link ResultSet} constants: {@link ResultSet#HOLD_CURSORS_OVER_COMMIT} + * or {@link ResultSet#CLOSE_CURSORS_AT_COMMIT}. */ public PStmtKeyCPDS(final String sql, final int resultSetType, final int resultSetConcurrency, final int resultSetHoldability) { diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/dbcp/dbcp2/cpdsadapter/PooledConnectionImpl.java tomcat10-10.1.52/java/org/apache/tomcat/dbcp/dbcp2/cpdsadapter/PooledConnectionImpl.java --- tomcat10-10.1.40/java/org/apache/tomcat/dbcp/dbcp2/cpdsadapter/PooledConnectionImpl.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/dbcp/dbcp2/cpdsadapter/PooledConnectionImpl.java 2026-01-23 19:33:36.000000000 +0000 @@ -6,7 +6,7 @@ * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -19,6 +19,7 @@ import java.sql.CallableStatement; import java.sql.Connection; import java.sql.PreparedStatement; +import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; import java.util.ArrayList; @@ -81,10 +82,10 @@ /** * Flag set to true, once {@link #close()} is called. */ - private boolean closed; + private volatile boolean closed; /** My pool of {@link PreparedStatement}s. */ - private KeyedObjectPool pStmtPool; + private KeyedObjectPool stmtPool; /** * Controls access to the underlying connection. @@ -146,8 +147,8 @@ } /** - * Closes the physical connection and marks this {@code PooledConnection} so that it may not be used to - * generate any more logical {@code Connection}s. + * Closes the physical connection and marks this {@link PooledConnection} so that it may not be used to + * generate any more logical {@link Connection}s. * * @throws SQLException * Thrown when an error occurs or the connection is already closed. @@ -157,11 +158,11 @@ assertOpen(); closed = true; try { - if (pStmtPool != null) { + if (stmtPool != null) { try { - pStmtPool.close(); + stmtPool.close(); } finally { - pStmtPool = null; + stmtPool = null; } } } catch (final RuntimeException e) { @@ -195,7 +196,7 @@ * The SQL statement. * @param autoGeneratedKeys * A flag indicating whether auto-generated keys should be returned; one of - * {@code Statement.RETURN_GENERATED_KEYS} or {@code Statement.NO_GENERATED_KEYS}. + * {@link Statement#RETURN_GENERATED_KEYS} or {@link Statement#NO_GENERATED_KEYS}. * @return a key to uniquely identify a prepared statement. */ protected PStmtKey createKey(final String sql, final int autoGeneratedKeys) { @@ -208,11 +209,11 @@ * @param sql * The SQL statement. * @param resultSetType - * A result set type; one of {@code ResultSet.TYPE_FORWARD_ONLY}, - * {@code ResultSet.TYPE_SCROLL_INSENSITIVE}, or {@code ResultSet.TYPE_SCROLL_SENSITIVE}. + * A result set type; one of {@link ResultSet#TYPE_FORWARD_ONLY}, + * {@link ResultSet#TYPE_SCROLL_INSENSITIVE}, or {@link ResultSet#TYPE_SCROLL_SENSITIVE}. * @param resultSetConcurrency - * A concurrency type; one of {@code ResultSet.CONCUR_READ_ONLY} or - * {@code ResultSet.CONCUR_UPDATABLE}. + * A concurrency type; one of {@link ResultSet#CONCUR_READ_ONLY} or + * {@link ResultSet#CONCUR_UPDATABLE}. * @return a key to uniquely identify a prepared statement. */ protected PStmtKey createKey(final String sql, final int resultSetType, final int resultSetConcurrency) { @@ -225,14 +226,14 @@ * @param sql * The SQL statement. * @param resultSetType - * a result set type; one of {@code ResultSet.TYPE_FORWARD_ONLY}, - * {@code ResultSet.TYPE_SCROLL_INSENSITIVE}, or {@code ResultSet.TYPE_SCROLL_SENSITIVE}. + * a result set type; one of {@link ResultSet#TYPE_FORWARD_ONLY}, + * {@link ResultSet#TYPE_SCROLL_INSENSITIVE}, or {@link ResultSet#TYPE_SCROLL_SENSITIVE}. * @param resultSetConcurrency - * A concurrency type; one of {@code ResultSet.CONCUR_READ_ONLY} or - * {@code ResultSet.CONCUR_UPDATABLE} + * A concurrency type; one of {@link ResultSet#CONCUR_READ_ONLY} or + * {@link ResultSet#CONCUR_UPDATABLE} * @param resultSetHoldability - * One of the following {@code ResultSet} constants: {@code ResultSet.HOLD_CURSORS_OVER_COMMIT} - * or {@code ResultSet.CLOSE_CURSORS_AT_COMMIT}. + * One of the following {@link ResultSet} constants: {@link ResultSet#HOLD_CURSORS_OVER_COMMIT} + * or {@link ResultSet#CLOSE_CURSORS_AT_COMMIT}. * @return a key to uniquely identify a prepared statement. */ protected PStmtKey createKey(final String sql, final int resultSetType, final int resultSetConcurrency, final int resultSetHoldability) { @@ -245,21 +246,21 @@ * @param sql * The SQL statement. * @param resultSetType - * a result set type; one of {@code ResultSet.TYPE_FORWARD_ONLY}, - * {@code ResultSet.TYPE_SCROLL_INSENSITIVE}, or {@code ResultSet.TYPE_SCROLL_SENSITIVE} + * a result set type; one of {@link ResultSet#TYPE_FORWARD_ONLY}, + * {@link ResultSet#TYPE_SCROLL_INSENSITIVE}, or {@link ResultSet#TYPE_SCROLL_SENSITIVE} * @param resultSetConcurrency - * A concurrency type; one of {@code ResultSet.CONCUR_READ_ONLY} or - * {@code ResultSet.CONCUR_UPDATABLE}. + * A concurrency type; one of {@link ResultSet#CONCUR_READ_ONLY} or + * {@link ResultSet#CONCUR_UPDATABLE}. * @param resultSetHoldability - * One of the following {@code ResultSet} constants: {@code ResultSet.HOLD_CURSORS_OVER_COMMIT} - * or {@code ResultSet.CLOSE_CURSORS_AT_COMMIT}. + * One of the following {@link ResultSet} constants: {@link ResultSet#HOLD_CURSORS_OVER_COMMIT} + * or {@link ResultSet#CLOSE_CURSORS_AT_COMMIT}. * @param statementType * The SQL statement type, prepared or callable. * @return a key to uniquely identify a prepared statement. * @since 2.4.0 */ protected PStmtKey createKey(final String sql, final int resultSetType, final int resultSetConcurrency, final int resultSetHoldability, - final StatementType statementType) { + final StatementType statementType) { return new PStmtKey(sql, getCatalogOrNull(), getSchemaOrNull(), resultSetType, resultSetConcurrency, resultSetHoldability, statementType); } @@ -269,11 +270,11 @@ * @param sql * The SQL statement. * @param resultSetType - * A result set type; one of {@code ResultSet.TYPE_FORWARD_ONLY}, - * {@code ResultSet.TYPE_SCROLL_INSENSITIVE}, or {@code ResultSet.TYPE_SCROLL_SENSITIVE}. + * A result set type; one of {@link ResultSet#TYPE_FORWARD_ONLY}, + * {@link ResultSet#TYPE_SCROLL_INSENSITIVE}, or {@link ResultSet#TYPE_SCROLL_SENSITIVE}. * @param resultSetConcurrency - * A concurrency type; one of {@code ResultSet.CONCUR_READ_ONLY} or - * {@code ResultSet.CONCUR_UPDATABLE}. + * A concurrency type; one of {@link ResultSet#CONCUR_READ_ONLY} or + * {@link ResultSet#CONCUR_UPDATABLE}. * @param statementType * The SQL statement type, prepared or callable. * @return a key to uniquely identify a prepared statement. @@ -424,13 +425,13 @@ if (key.getStmtType() == StatementType.PREPARED_STATEMENT) { final PreparedStatement statement = (PreparedStatement) key.createStatement(connection); @SuppressWarnings({"rawtypes", "unchecked" }) // Unable to find way to avoid this - final PoolablePreparedStatement pps = new PoolablePreparedStatement(statement, key, pStmtPool, + final PoolablePreparedStatement pps = new PoolablePreparedStatement(statement, key, stmtPool, delegatingConnection); return new DefaultPooledObject<>(pps); } final CallableStatement statement = (CallableStatement) key.createStatement(connection); @SuppressWarnings("unchecked") - final PoolableCallableStatement pcs = new PoolableCallableStatement(statement, key, pStmtPool, + final PoolableCallableStatement pcs = new PoolableCallableStatement(statement, key, stmtPool, (DelegatingConnection) delegatingConnection); return new DefaultPooledObject<>(pcs); } @@ -466,17 +467,17 @@ * @param sql * an SQL statement that may contain one or more '?' parameter placeholders. Typically, this statement is * specified using JDBC call escape syntax. - * @return a default {@code CallableStatement} object containing the pre-compiled SQL statement. + * @return a default {@link CallableStatement} object containing the pre-compiled SQL statement. * @throws SQLException * Thrown if a database access error occurs or this method is called on a closed connection. * @since 2.4.0 */ CallableStatement prepareCall(final String sql) throws SQLException { - if (pStmtPool == null) { + if (stmtPool == null) { return getRawConnection().prepareCall(sql); } try { - return (CallableStatement) pStmtPool.borrowObject(createKey(sql, StatementType.CALLABLE_STATEMENT)); + return (CallableStatement) stmtPool.borrowObject(createKey(sql, StatementType.CALLABLE_STATEMENT)); } catch (final RuntimeException e) { throw e; } catch (final Exception e) { @@ -488,28 +489,28 @@ * Creates or obtains a {@link CallableStatement} from my pool. * * @param sql - * a {@code String} object that is the SQL statement to be sent to the database; may contain on or + * a {@link String} object that is the SQL statement to be sent to the database; may contain on or * more '?' parameters. * @param resultSetType - * a result set type; one of {@code ResultSet.TYPE_FORWARD_ONLY}, - * {@code ResultSet.TYPE_SCROLL_INSENSITIVE}, or {@code ResultSet.TYPE_SCROLL_SENSITIVE}. + * a result set type; one of {@link ResultSet#TYPE_FORWARD_ONLY}, + * {@link ResultSet#TYPE_SCROLL_INSENSITIVE}, or {@link ResultSet#TYPE_SCROLL_SENSITIVE}. * @param resultSetConcurrency - * a concurrency type; one of {@code ResultSet.CONCUR_READ_ONLY} or - * {@code ResultSet.CONCUR_UPDATABLE}. - * @return a {@code CallableStatement} object containing the pre-compiled SQL statement that will produce - * {@code ResultSet} objects with the given type and concurrency. + * a concurrency type; one of {@link ResultSet#CONCUR_READ_ONLY} or + * {@link ResultSet#CONCUR_UPDATABLE}. + * @return a {@link CallableStatement} object containing the pre-compiled SQL statement that will produce + * {@link ResultSet} objects with the given type and concurrency. * @throws SQLException * Thrown if a database access error occurs, this method is called on a closed connection or the given - * parameters are not {@code ResultSet} constants indicating type and concurrency. + * parameters are not {@link ResultSet} constants indicating type and concurrency. * @since 2.4.0 */ CallableStatement prepareCall(final String sql, final int resultSetType, final int resultSetConcurrency) throws SQLException { - if (pStmtPool == null) { + if (stmtPool == null) { return getRawConnection().prepareCall(sql, resultSetType, resultSetConcurrency); } try { - return (CallableStatement) pStmtPool.borrowObject( + return (CallableStatement) stmtPool.borrowObject( createKey(sql, resultSetType, resultSetConcurrency, StatementType.CALLABLE_STATEMENT)); } catch (final RuntimeException e) { throw e; @@ -522,31 +523,31 @@ * Creates or obtains a {@link CallableStatement} from my pool. * * @param sql - * a {@code String} object that is the SQL statement to be sent to the database; may contain on or + * a {@link String} object that is the SQL statement to be sent to the database; may contain on or * more '?' parameters. * @param resultSetType - * one of the following {@code ResultSet} constants: {@code ResultSet.TYPE_FORWARD_ONLY}, - * {@code ResultSet.TYPE_SCROLL_INSENSITIVE}, or {@code ResultSet.TYPE_SCROLL_SENSITIVE}. + * one of the following {@link ResultSet} constants: {@link ResultSet#TYPE_FORWARD_ONLY}, + * {@link ResultSet#TYPE_SCROLL_INSENSITIVE}, or {@link ResultSet#TYPE_SCROLL_SENSITIVE}. * @param resultSetConcurrency - * one of the following {@code ResultSet} constants: {@code ResultSet.CONCUR_READ_ONLY} or - * {@code ResultSet.CONCUR_UPDATABLE}. + * one of the following {@link ResultSet} constants: {@link ResultSet#CONCUR_READ_ONLY} or + * {@link ResultSet#CONCUR_UPDATABLE}. * @param resultSetHoldability - * one of the following {@code ResultSet} constants: {@code ResultSet.HOLD_CURSORS_OVER_COMMIT} - * or {@code ResultSet.CLOSE_CURSORS_AT_COMMIT}. - * @return a new {@code CallableStatement} object, containing the pre-compiled SQL statement, that will - * generate {@code ResultSet} objects with the given type, concurrency, and holdability. + * one of the following {@link ResultSet} constants: {@link ResultSet#HOLD_CURSORS_OVER_COMMIT} + * or {@link ResultSet#CLOSE_CURSORS_AT_COMMIT}. + * @return a new {@link CallableStatement} object, containing the pre-compiled SQL statement, that will + * generate {@link ResultSet} objects with the given type, concurrency, and holdability. * @throws SQLException * Thrown if a database access error occurs, this method is called on a closed connection or the given - * parameters are not {@code ResultSet} constants indicating type, concurrency, and holdability. + * parameters are not {@link ResultSet} constants indicating type, concurrency, and holdability. * @since 2.4.0 */ CallableStatement prepareCall(final String sql, final int resultSetType, final int resultSetConcurrency, final int resultSetHoldability) throws SQLException { - if (pStmtPool == null) { + if (stmtPool == null) { return getRawConnection().prepareCall(sql, resultSetType, resultSetConcurrency, resultSetHoldability); } try { - return (CallableStatement) pStmtPool.borrowObject(createKey(sql, resultSetType, resultSetConcurrency, + return (CallableStatement) stmtPool.borrowObject(createKey(sql, resultSetType, resultSetConcurrency, resultSetHoldability, StatementType.CALLABLE_STATEMENT)); } catch (final RuntimeException e) { throw e; @@ -564,11 +565,11 @@ * the borrow failed. */ PreparedStatement prepareStatement(final String sql) throws SQLException { - if (pStmtPool == null) { + if (stmtPool == null) { return getRawConnection().prepareStatement(sql); } try { - return pStmtPool.borrowObject(createKey(sql)); + return stmtPool.borrowObject(createKey(sql)); } catch (final RuntimeException e) { throw e; } catch (final Exception e) { @@ -583,18 +584,18 @@ * an SQL statement that may contain one or more '?' IN parameter placeholders. * @param autoGeneratedKeys * a flag indicating whether auto-generated keys should be returned; one of - * {@code Statement.RETURN_GENERATED_KEYS} or {@code Statement.NO_GENERATED_KEYS}. + * {@link Statement#RETURN_GENERATED_KEYS} or {@link Statement#NO_GENERATED_KEYS}. * @return a {@link PoolablePreparedStatement} * @throws SQLException Thrown if a database access error occurs, this method is called on a closed connection, or * the borrow failed. * @see Connection#prepareStatement(String, int) */ PreparedStatement prepareStatement(final String sql, final int autoGeneratedKeys) throws SQLException { - if (pStmtPool == null) { + if (stmtPool == null) { return getRawConnection().prepareStatement(sql, autoGeneratedKeys); } try { - return pStmtPool.borrowObject(createKey(sql, autoGeneratedKeys)); + return stmtPool.borrowObject(createKey(sql, autoGeneratedKeys)); } catch (final RuntimeException e) { throw e; } catch (final Exception e) { @@ -606,14 +607,14 @@ * Creates or obtains a {@link PreparedStatement} from my pool. * * @param sql - * a {@code String} object that is the SQL statement to be sent to the database; may contain one or + * a {@link String} object that is the SQL statement to be sent to the database; may contain one or * more '?' IN parameters. * @param resultSetType - * a result set type; one of {@code ResultSet.TYPE_FORWARD_ONLY}, - * {@code ResultSet.TYPE_SCROLL_INSENSITIVE}, or {@code ResultSet.TYPE_SCROLL_SENSITIVE}. + * a result set type; one of {@link ResultSet#TYPE_FORWARD_ONLY}, + * {@link ResultSet#TYPE_SCROLL_INSENSITIVE}, or {@link ResultSet#TYPE_SCROLL_SENSITIVE}. * @param resultSetConcurrency - * a concurrency type; one of {@code ResultSet.CONCUR_READ_ONLY} or - * {@code ResultSet.CONCUR_UPDATABLE}. + * a concurrency type; one of {@link ResultSet#CONCUR_READ_ONLY} or + * {@link ResultSet#CONCUR_UPDATABLE}. * * @return a {@link PoolablePreparedStatement}. * @throws SQLException Thrown if a database access error occurs, this method is called on a closed connection, or @@ -622,11 +623,11 @@ */ PreparedStatement prepareStatement(final String sql, final int resultSetType, final int resultSetConcurrency) throws SQLException { - if (pStmtPool == null) { + if (stmtPool == null) { return getRawConnection().prepareStatement(sql, resultSetType, resultSetConcurrency); } try { - return pStmtPool.borrowObject(createKey(sql, resultSetType, resultSetConcurrency)); + return stmtPool.borrowObject(createKey(sql, resultSetType, resultSetConcurrency)); } catch (final RuntimeException e) { throw e; } catch (final Exception e) { @@ -636,11 +637,11 @@ PreparedStatement prepareStatement(final String sql, final int resultSetType, final int resultSetConcurrency, final int resultSetHoldability) throws SQLException { - if (pStmtPool == null) { + if (stmtPool == null) { return getRawConnection().prepareStatement(sql, resultSetType, resultSetConcurrency, resultSetHoldability); } try { - return pStmtPool.borrowObject(createKey(sql, resultSetType, resultSetConcurrency, resultSetHoldability)); + return stmtPool.borrowObject(createKey(sql, resultSetType, resultSetConcurrency, resultSetHoldability)); } catch (final RuntimeException e) { throw e; } catch (final Exception e) { @@ -649,11 +650,11 @@ } PreparedStatement prepareStatement(final String sql, final int[] columnIndexes) throws SQLException { - if (pStmtPool == null) { + if (stmtPool == null) { return getRawConnection().prepareStatement(sql, columnIndexes); } try { - return pStmtPool.borrowObject(createKey(sql, columnIndexes)); + return stmtPool.borrowObject(createKey(sql, columnIndexes)); } catch (final RuntimeException e) { throw e; } catch (final Exception e) { @@ -662,11 +663,11 @@ } PreparedStatement prepareStatement(final String sql, final String[] columnNames) throws SQLException { - if (pStmtPool == null) { + if (stmtPool == null) { return getRawConnection().prepareStatement(sql, columnNames); } try { - return pStmtPool.borrowObject(createKey(sql, columnNames)); + return stmtPool.borrowObject(createKey(sql, columnNames)); } catch (final RuntimeException e) { throw e; } catch (final Exception e) { @@ -699,7 +700,7 @@ } public void setStatementPool(final KeyedObjectPool statementPool) { - pStmtPool = statementPool; + stmtPool = statementPool; } /** @@ -720,8 +721,8 @@ builder.append(statementEventListeners); builder.append(", closed="); builder.append(closed); - builder.append(", pStmtPool="); - builder.append(pStmtPool); + builder.append(", stmtPool="); + builder.append(stmtPool); builder.append(", accessToUnderlyingConnectionAllowed="); builder.append(accessToUnderlyingConnectionAllowed); builder.append("]"); diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/dbcp/dbcp2/cpdsadapter/package-info.java tomcat10-10.1.52/java/org/apache/tomcat/dbcp/dbcp2/cpdsadapter/package-info.java --- tomcat10-10.1.40/java/org/apache/tomcat/dbcp/dbcp2/cpdsadapter/package-info.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/dbcp/dbcp2/cpdsadapter/package-info.java 2026-01-23 19:33:36.000000000 +0000 @@ -6,7 +6,7 @@ * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/dbcp/dbcp2/datasources/AbstractConnectionFactory.java tomcat10-10.1.52/java/org/apache/tomcat/dbcp/dbcp2/datasources/AbstractConnectionFactory.java --- tomcat10-10.1.40/java/org/apache/tomcat/dbcp/dbcp2/datasources/AbstractConnectionFactory.java 1970-01-01 00:00:00.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/dbcp/dbcp2/datasources/AbstractConnectionFactory.java 2026-01-23 19:33:36.000000000 +0000 @@ -0,0 +1,147 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.tomcat.dbcp.dbcp2.datasources; + +import java.sql.Connection; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Statement; +import java.time.Duration; +import java.util.Collections; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; + +import javax.sql.ConnectionPoolDataSource; +import javax.sql.PooledConnection; + +import org.apache.tomcat.dbcp.dbcp2.Utils; +import org.apache.tomcat.dbcp.pool2.PooledObject; + +/** + * Abstracts services for connection factories in this package. + */ +class AbstractConnectionFactory { + + protected final ConnectionPoolDataSource cpds; + protected Duration maxConnDuration = Duration.ofMillis(-1); + protected final boolean rollbackAfterValidation; + + /** + * Map of PooledConnectionAndInfo instances + */ + protected final Map pcMap = new ConcurrentHashMap<>(); + + /** + * Map of PooledConnections for which close events are ignored. Connections are muted when they are being validated. + */ + protected final Set validatingSet = Collections.newSetFromMap(new ConcurrentHashMap<>()); + protected final String validationQuery; + protected final Duration validationQueryTimeoutDuration; + + AbstractConnectionFactory(final ConnectionPoolDataSource cpds, final String validationQuery, + final Duration validationQueryTimeoutDuration, final boolean rollbackAfterValidation) { + this.cpds = cpds; + this.validationQuery = validationQuery; + this.validationQueryTimeoutDuration = validationQueryTimeoutDuration; + this.rollbackAfterValidation = rollbackAfterValidation; + } + + /** + * Sets the maximum lifetime of a connection after which the connection will always fail activation, + * passivation and validation. + * + * @param duration + * A value of zero or less indicates an infinite lifetime. The default value is -1 milliseconds. + * @since 2.10.0 + */ + void setMaxConn(final Duration duration) { + this.maxConnDuration = duration; + } + + /** + * Converts a duration to seconds where a duration less than one second becomes 1 second. + * + * @param duration the duration to convert. + * @return a duration to seconds where a duration less than one second becomes 1 second. + * @throws ArithmeticException if the query validation timeout does not fit as seconds in an int. + */ + private int toSeconds(final Duration duration) { + if (duration.isNegative() || duration.isZero()) { + return 0; + } + final long seconds = validationQueryTimeoutDuration.getSeconds(); + return seconds != 0 ? Math.toIntExact(seconds) : 1; + } + + protected void validateLifetime(final PooledObject pooledObject) throws SQLException { + Utils.validateLifetime(pooledObject, maxConnDuration); + } + + public boolean validateObject(final PooledObject pooledObject) { + try { + validateLifetime(pooledObject); + } catch (final Exception e) { + return false; + } + boolean valid = false; + final PooledConnection pooledConn = pooledObject.getObject().getPooledConnection(); + Connection conn = null; + // logical Connection from the PooledConnection must be closed + // before another one can be requested and closing it will + // generate an event. Keep track so we know not to return + // the PooledConnection + validatingSet.add(pooledConn); + try { + final int timeoutSeconds = toSeconds(validationQueryTimeoutDuration); + if (validationQuery == null) { + try { + conn = pooledConn.getConnection(); + valid = conn.isValid(timeoutSeconds); + } catch (final SQLException e) { + valid = false; + } + } else { + Statement stmt = null; + ResultSet rset = null; + try { + conn = pooledConn.getConnection(); + stmt = conn.createStatement(); + if (timeoutSeconds > 0) { + stmt.setQueryTimeout(timeoutSeconds); + } + rset = stmt.executeQuery(validationQuery); + valid = rset.next(); + if (rollbackAfterValidation) { + conn.rollback(); + } + } catch (final Exception e) { + valid = false; + } finally { + Utils.closeQuietly((AutoCloseable) rset); + Utils.closeQuietly((AutoCloseable) stmt); + } + } + } finally { + Utils.closeQuietly((AutoCloseable) conn); + validatingSet.remove(pooledConn); + } + return valid; + } + +} diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/dbcp/dbcp2/datasources/CPDSConnectionFactory.java tomcat10-10.1.52/java/org/apache/tomcat/dbcp/dbcp2/datasources/CPDSConnectionFactory.java --- tomcat10-10.1.40/java/org/apache/tomcat/dbcp/dbcp2/datasources/CPDSConnectionFactory.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/dbcp/dbcp2/datasources/CPDSConnectionFactory.java 2026-01-23 19:33:36.000000000 +0000 @@ -6,7 +6,7 @@ * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -17,21 +17,14 @@ package org.apache.tomcat.dbcp.dbcp2.datasources; import java.sql.Connection; -import java.sql.ResultSet; import java.sql.SQLException; -import java.sql.Statement; import java.time.Duration; -import java.util.Collections; -import java.util.Map; -import java.util.Set; -import java.util.concurrent.ConcurrentHashMap; import javax.sql.ConnectionEvent; import javax.sql.ConnectionEventListener; import javax.sql.ConnectionPoolDataSource; import javax.sql.PooledConnection; -import org.apache.tomcat.dbcp.dbcp2.Utils; import org.apache.tomcat.dbcp.pool2.ObjectPool; import org.apache.tomcat.dbcp.pool2.PooledObject; import org.apache.tomcat.dbcp.pool2.PooledObjectFactory; @@ -42,31 +35,16 @@ * * @since 2.0 */ -final class CPDSConnectionFactory +final class CPDSConnectionFactory extends AbstractConnectionFactory implements PooledObjectFactory, ConnectionEventListener, PooledConnectionManager { private static final String NO_KEY_MESSAGE = "close() was called on a Connection, but I have no record of the underlying PooledConnection."; - private final ConnectionPoolDataSource cpds; - private final String validationQuery; - private final Duration validationQueryTimeoutDuration; - private final boolean rollbackAfterValidation; private ObjectPool pool; private UserPassKey userPassKey; - private Duration maxConnDuration = Duration.ofMillis(-1); /** - * Map of PooledConnections for which close events are ignored. Connections are muted when they are being validated. - */ - private final Set validatingSet = Collections.newSetFromMap(new ConcurrentHashMap<>()); - - /** - * Map of PooledConnectionAndInfo instances - */ - private final Map pcMap = new ConcurrentHashMap<>(); - - /** - * Creates a new {@code PoolableConnectionFactory}. + * Creates a new {@link PoolableConnectionFactory}. * * @param cpds * the ConnectionPoolDataSource from which to obtain PooledConnection's @@ -86,97 +64,14 @@ */ CPDSConnectionFactory(final ConnectionPoolDataSource cpds, final String validationQuery, final Duration validationQueryTimeoutDuration, final boolean rollbackAfterValidation, final String userName, - final char[] userPassword) { - this.cpds = cpds; - this.validationQuery = validationQuery; - this.validationQueryTimeoutDuration = validationQueryTimeoutDuration; + final char[] userPassword) { + super(cpds, validationQuery, validationQueryTimeoutDuration, rollbackAfterValidation); this.userPassKey = new UserPassKey(userName, userPassword); - this.rollbackAfterValidation = rollbackAfterValidation; - } - - /** - * Creates a new {@code PoolableConnectionFactory}. - * - * @param cpds - * the ConnectionPoolDataSource from which to obtain PooledConnection's - * @param validationQuery - * a query to use to {@link #validateObject validate} {@link Connection}s. Should return at least one - * row. May be {@code null} in which case {@link Connection#isValid(int)} will be used to validate - * connections. - * @param validationQueryTimeoutDuration - * Timeout in seconds before validation fails - * @param rollbackAfterValidation - * whether a rollback should be issued after {@link #validateObject validating} {@link Connection}s. - * @param userName - * The user name to use to create connections - * @param userPassword - * The password to use to create connections - * @since 2.10.0 - */ - CPDSConnectionFactory(final ConnectionPoolDataSource cpds, final String validationQuery, final Duration validationQueryTimeoutDuration, - final boolean rollbackAfterValidation, final String userName, final String userPassword) { - this(cpds, validationQuery, validationQueryTimeoutDuration, rollbackAfterValidation, userName, Utils.toCharArray(userPassword)); - } - - /** - * Creates a new {@code PoolableConnectionFactory}. - * - * @param cpds - * the ConnectionPoolDataSource from which to obtain PooledConnection's - * @param validationQuery - * a query to use to {@link #validateObject validate} {@link Connection}s. Should return at least one - * row. May be {@code null} in which case {@link Connection#isValid(int)} will be used to validate - * connections. - * @param validationQueryTimeoutSeconds - * Timeout in seconds before validation fails - * @param rollbackAfterValidation - * whether a rollback should be issued after {@link #validateObject validating} {@link Connection}s. - * @param userName - * The user name to use to create connections - * @param userPassword - * The password to use to create connections - * @since 2.4.0 - * @deprecated Use {@link #CPDSConnectionFactory(ConnectionPoolDataSource, String, Duration, boolean, String, char[])}. - */ - @Deprecated - CPDSConnectionFactory(final ConnectionPoolDataSource cpds, final String validationQuery, - final int validationQueryTimeoutSeconds, final boolean rollbackAfterValidation, final String userName, - final char[] userPassword) { - this.cpds = cpds; - this.validationQuery = validationQuery; - this.validationQueryTimeoutDuration = Duration.ofSeconds(validationQueryTimeoutSeconds); - this.userPassKey = new UserPassKey(userName, userPassword); - this.rollbackAfterValidation = rollbackAfterValidation; - } - - /** - * Creates a new {@code PoolableConnectionFactory}. - * - * @param cpds - * the ConnectionPoolDataSource from which to obtain PooledConnection's - * @param validationQuery - * a query to use to {@link #validateObject validate} {@link Connection}s. Should return at least one - * row. May be {@code null} in which case {@link Connection#isValid(int)} will be used to validate - * connections. - * @param validationQueryTimeoutSeconds - * Timeout in seconds before validation fails - * @param rollbackAfterValidation - * whether a rollback should be issued after {@link #validateObject validating} {@link Connection}s. - * @param userName - * The user name to use to create connections - * @param userPassword - * The password to use to create connections - * @deprecated Use {@link #CPDSConnectionFactory(ConnectionPoolDataSource, String, Duration, boolean, String, String)}. - */ - @Deprecated - CPDSConnectionFactory(final ConnectionPoolDataSource cpds, final String validationQuery, final int validationQueryTimeoutSeconds, - final boolean rollbackAfterValidation, final String userName, final String userPassword) { - this(cpds, validationQuery, validationQueryTimeoutSeconds, rollbackAfterValidation, userName, Utils.toCharArray(userPassword)); } @Override - public void activateObject(final PooledObject p) throws SQLException { - validateLifetime(p); + public void activateObject(final PooledObject pooledObject) throws SQLException { + validateLifetime(pooledObject); } /** @@ -216,7 +111,7 @@ try { pool.returnObject(pci); } catch (final Exception e) { - System.err.println("CLOSING DOWN CONNECTION AS IT COULD " + "NOT BE RETURNED TO THE POOL"); + System.err.println("CLOSING DOWN CONNECTION AS IT COULD NOT BE RETURNED TO THE POOL"); pc.removeConnectionEventListener(this); try { doDestroyObject(pci); @@ -296,8 +191,9 @@ throw new IllegalStateException(NO_KEY_MESSAGE); } try { - pool.invalidateObject(pci); // Destroy instance and update pool counters pool.close(); // Clear any other instances in this pool and kill others as they come back + // Calling close before invalidate ensures that invalidate will not trigger a create attempt + pool.invalidateObject(pci); // Destroy instance and update pool counters } catch (final Exception ex) { throw new SQLException("Error invalidating connection", ex); } @@ -328,50 +224,12 @@ } /** - * Sets the maximum Duration of a connection after which the connection will always fail activation, - * passivation and validation. - * - * @param maxConnDuration - * A value of zero or less indicates an infinite lifetime. The default value is -1 milliseconds. - * @since 2.10.0 - */ - public void setMaxConn(final Duration maxConnDuration) { - this.maxConnDuration = maxConnDuration; - } - - /** - * Sets the maximum lifetime in milliseconds of a connection after which the connection will always fail activation, - * passivation and validation. - * - * @param maxConnDuration - * A value of zero or less indicates an infinite lifetime. The default value is -1 milliseconds. - * @since 2.9.0 - * @deprecated Use {@link #setMaxConn(Duration)}. - */ - @Deprecated - public void setMaxConnLifetime(final Duration maxConnDuration) { - this.maxConnDuration = maxConnDuration; - } - - /** - * Sets the maximum lifetime in milliseconds of a connection after which the connection will always fail activation, - * passivation and validation. - * - * @param maxConnLifetimeMillis - * A value of zero or less indicates an infinite lifetime. The default value is -1. - * @deprecated Use {@link #setMaxConn(Duration)}. - */ - @Deprecated - public void setMaxConnLifetimeMillis(final long maxConnLifetimeMillis) { - setMaxConnLifetime(Duration.ofMillis(maxConnLifetimeMillis)); - } - - /** * Sets the database password used when creating new connections. * * @param userPassword * new password */ + @Override public synchronized void setPassword(final char[] userPassword) { this.userPassKey = new UserPassKey(userPassKey.getUserName(), userPassword); } @@ -420,61 +278,4 @@ builder.append("]"); return builder.toString(); } - - private void validateLifetime(final PooledObject p) throws SQLException { - Utils.validateLifetime(p, maxConnDuration); - } - - @Override - public boolean validateObject(final PooledObject p) { - try { - validateLifetime(p); - } catch (final Exception e) { - return false; - } - boolean valid = false; - final PooledConnection pconn = p.getObject().getPooledConnection(); - Connection conn = null; - validatingSet.add(pconn); - if (null == validationQuery) { - Duration timeoutDuration = validationQueryTimeoutDuration; - if (timeoutDuration.isNegative()) { - timeoutDuration = Duration.ZERO; - } - try { - conn = pconn.getConnection(); - valid = conn.isValid((int) timeoutDuration.getSeconds()); - } catch (final SQLException e) { - valid = false; - } finally { - Utils.closeQuietly((AutoCloseable) conn); - validatingSet.remove(pconn); - } - } else { - Statement stmt = null; - ResultSet rset = null; - // logical Connection from the PooledConnection must be closed - // before another one can be requested and closing it will - // generate an event. Keep track so we know not to return - // the PooledConnection - validatingSet.add(pconn); - try { - conn = pconn.getConnection(); - stmt = conn.createStatement(); - rset = stmt.executeQuery(validationQuery); - valid = rset.next(); - if (rollbackAfterValidation) { - conn.rollback(); - } - } catch (final Exception e) { - valid = false; - } finally { - Utils.closeQuietly((AutoCloseable) rset); - Utils.closeQuietly((AutoCloseable) stmt); - Utils.closeQuietly((AutoCloseable) conn); - validatingSet.remove(pconn); - } - } - return valid; - } } diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/dbcp/dbcp2/datasources/CharArray.java tomcat10-10.1.52/java/org/apache/tomcat/dbcp/dbcp2/datasources/CharArray.java --- tomcat10-10.1.40/java/org/apache/tomcat/dbcp/dbcp2/datasources/CharArray.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/dbcp/dbcp2/datasources/CharArray.java 2026-01-23 19:33:36.000000000 +0000 @@ -6,7 +6,7 @@ * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -23,19 +23,18 @@ import org.apache.tomcat.dbcp.dbcp2.Utils; /** - * A {@code char} array wrapper that does not reveal its contents inadvertently through toString(). In contrast to, for - * example, AtomicReference which toString()'s its contents. - * + * A {@code char} array wrapper that does not reveal its contents inadvertently through toString(). In contrast to, for example, AtomicReference which + * toString()'s its contents. + *

        * May contain null. + *

        * * @since 2.9.0 */ final class CharArray implements Serializable { - private static final long serialVersionUID = 1L; - static final CharArray NULL = new CharArray((char[]) null); - + private static final long serialVersionUID = 1L; private final char[] chars; CharArray(final char[] chars) { @@ -55,6 +54,18 @@ return Utils.toString(chars); } + /** + * Clears the content of the char array. + * + * @return {@code this} instance. + */ + CharArray clear() { + if (chars != null) { + Arrays.fill(chars, '\0'); + } + return this; + } + @Override public boolean equals(final Object obj) { if (this == obj) { @@ -80,5 +91,4 @@ public int hashCode() { return Arrays.hashCode(chars); } - } diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/dbcp/dbcp2/datasources/InstanceKeyDataSource.java tomcat10-10.1.52/java/org/apache/tomcat/dbcp/dbcp2/datasources/InstanceKeyDataSource.java --- tomcat10-10.1.40/java/org/apache/tomcat/dbcp/dbcp2/datasources/InstanceKeyDataSource.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/dbcp/dbcp2/datasources/InstanceKeyDataSource.java 2026-01-23 19:33:36.000000000 +0000 @@ -6,7 +6,7 @@ * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -41,30 +41,30 @@ /** *

        - * The base class for {@code SharedPoolDataSource} and {@code PerUserPoolDataSource}. Many of the + * The base class for {@link SharedPoolDataSource} and {@link PerUserPoolDataSource}. Many of the * configuration properties are shared and defined here. This class is declared public in order to allow particular * usage with commons-beanutils; do not make direct use of it outside of commons-dbcp2. *

        * *

        - * A J2EE container will normally provide some method of initializing the {@code DataSource} whose attributes are + * A J2EE container will normally provide some method of initializing the {@link DataSource} whose attributes are * presented as bean getters/setters and then deploying it via JNDI. It is then available to an application as a source * of pooled logical connections to the database. The pool needs a source of physical connections. This source is in the - * form of a {@code ConnectionPoolDataSource} that can be specified via the {@link #setDataSourceName(String)} used + * form of a {@link ConnectionPoolDataSource} that can be specified via the {@link #setDataSourceName(String)} used * to lookup the source via JNDI. *

        * *

        * Although normally used within a JNDI environment, A DataSource can be instantiated and initialized as any bean. In - * this case the {@code ConnectionPoolDataSource} will likely be instantiated in a similar manner. This class + * this case the {@link ConnectionPoolDataSource} will likely be instantiated in a similar manner. This class * allows the physical source of connections to be attached directly to this pool using the * {@link #setConnectionPoolDataSource(ConnectionPoolDataSource)} method. *

        * *

        * The dbcp package contains an adapter, {@link org.apache.tomcat.dbcp.dbcp2.cpdsadapter.DriverAdapterCPDS}, that can be - * used to allow the use of {@code DataSource}'s based on this class with JDBC driver implementations that do not - * supply a {@code ConnectionPoolDataSource}, but still provide a {@link java.sql.Driver} implementation. + * used to allow the use of {@link DataSource}'s based on this class with JDBC driver implementations that do not + * supply a {@link ConnectionPoolDataSource}, but still provide a {@link java.sql.Driver} implementation. *

        * *

        @@ -111,32 +111,70 @@ /** Instance key */ private String instanceKey; - // Pool properties - private boolean defaultBlockWhenExhausted = BaseObjectPoolConfig.DEFAULT_BLOCK_WHEN_EXHAUSTED; + /** Pool property defaults to {@link BaseObjectPoolConfig#DEFAULT_BLOCK_WHEN_EXHAUSTED}. */ + private volatile boolean defaultBlockWhenExhausted = BaseObjectPoolConfig.DEFAULT_BLOCK_WHEN_EXHAUSTED; + + /** Pool property defaults to {@link BaseObjectPoolConfig#DEFAULT_EVICTION_POLICY_CLASS_NAME}. */ private String defaultEvictionPolicyClassName = BaseObjectPoolConfig.DEFAULT_EVICTION_POLICY_CLASS_NAME; - private boolean defaultLifo = BaseObjectPoolConfig.DEFAULT_LIFO; - private int defaultMaxIdle = GenericKeyedObjectPoolConfig.DEFAULT_MAX_IDLE_PER_KEY; - private int defaultMaxTotal = GenericKeyedObjectPoolConfig.DEFAULT_MAX_TOTAL; + + /** Pool property defaults to {@link BaseObjectPoolConfig#DEFAULT_LIFO}. */ + private volatile boolean defaultLifo = BaseObjectPoolConfig.DEFAULT_LIFO; + + /** Pool property defaults to {@link GenericKeyedObjectPoolConfig#DEFAULT_MAX_IDLE_PER_KEY}. */ + private volatile int defaultMaxIdle = GenericKeyedObjectPoolConfig.DEFAULT_MAX_IDLE_PER_KEY; + + /** Pool property defaults to {@link GenericKeyedObjectPoolConfig#DEFAULT_MAX_TOTAL}. */ + private volatile int defaultMaxTotal = GenericKeyedObjectPoolConfig.DEFAULT_MAX_TOTAL; + + /** Pool property defaults to {@link BaseObjectPoolConfig#DEFAULT_MAX_WAIT}. */ private Duration defaultMaxWaitDuration = BaseObjectPoolConfig.DEFAULT_MAX_WAIT; + + /** Pool property defaults to {@link BaseObjectPoolConfig#DEFAULT_MIN_EVICTABLE_IDLE_DURATION}. */ private Duration defaultMinEvictableIdleDuration = BaseObjectPoolConfig.DEFAULT_MIN_EVICTABLE_IDLE_DURATION; - private int defaultMinIdle = GenericKeyedObjectPoolConfig.DEFAULT_MIN_IDLE_PER_KEY; - private int defaultNumTestsPerEvictionRun = BaseObjectPoolConfig.DEFAULT_NUM_TESTS_PER_EVICTION_RUN; + + /** Pool property defaults to {@link GenericKeyedObjectPoolConfig#DEFAULT_MIN_IDLE_PER_KEY}. */ + private volatile int defaultMinIdle = GenericKeyedObjectPoolConfig.DEFAULT_MIN_IDLE_PER_KEY; + + /** Pool property defaults to {@link BaseObjectPoolConfig#DEFAULT_NUM_TESTS_PER_EVICTION_RUN}. */ + private volatile int defaultNumTestsPerEvictionRun = BaseObjectPoolConfig.DEFAULT_NUM_TESTS_PER_EVICTION_RUN; + + /** Pool property defaults to {@link BaseObjectPoolConfig#DEFAULT_SOFT_MIN_EVICTABLE_IDLE_DURATION}. */ private Duration defaultSoftMinEvictableIdleDuration = BaseObjectPoolConfig.DEFAULT_SOFT_MIN_EVICTABLE_IDLE_DURATION; - private boolean defaultTestOnCreate = BaseObjectPoolConfig.DEFAULT_TEST_ON_CREATE; - private boolean defaultTestOnBorrow = BaseObjectPoolConfig.DEFAULT_TEST_ON_BORROW; - private boolean defaultTestOnReturn = BaseObjectPoolConfig.DEFAULT_TEST_ON_RETURN; - private boolean defaultTestWhileIdle = BaseObjectPoolConfig.DEFAULT_TEST_WHILE_IDLE; + + /** Pool property defaults to {@link BaseObjectPoolConfig#DEFAULT_TEST_ON_CREATE}. */ + private volatile boolean defaultTestOnCreate = BaseObjectPoolConfig.DEFAULT_TEST_ON_CREATE; + + /** Pool property defaults to {@link BaseObjectPoolConfig#DEFAULT_TEST_ON_BORROW}. */ + private volatile boolean defaultTestOnBorrow = BaseObjectPoolConfig.DEFAULT_TEST_ON_BORROW; + + /** Pool property defaults to {@link BaseObjectPoolConfig#DEFAULT_TEST_ON_RETURN}. */ + private volatile boolean defaultTestOnReturn = BaseObjectPoolConfig.DEFAULT_TEST_ON_RETURN; + + /** Pool property defaults to {@link BaseObjectPoolConfig#DEFAULT_TEST_WHILE_IDLE}. */ + private volatile boolean defaultTestWhileIdle = BaseObjectPoolConfig.DEFAULT_TEST_WHILE_IDLE; + + /** Pool property defaults to {@link BaseObjectPoolConfig#DEFAULT_DURATION_BETWEEN_EVICTION_RUNS}. */ private Duration defaultDurationBetweenEvictionRuns = BaseObjectPoolConfig.DEFAULT_DURATION_BETWEEN_EVICTION_RUNS; - // Connection factory properties + /** Connection factory property defaults to null. */ private String validationQuery; + + /** Connection factory property defaults to -1 seconds. */ private Duration validationQueryTimeoutDuration = Duration.ofSeconds(-1); - private boolean rollbackAfterValidation; + + /** Connection factory property defaults to false. */ + private volatile boolean rollbackAfterValidation; + + /** Connection factory property defaults to -1 milliseconds. */ private Duration maxConnDuration = Duration.ofMillis(-1); - // Connection properties + /** Connection property defaults to false. */ private Boolean defaultAutoCommit; - private int defaultTransactionIsolation = UNKNOWN_TRANSACTIONISOLATION; + + /** Connection property defaults to {@link #UNKNOWN_TRANSACTIONISOLATION}. */ + private volatile int defaultTransactionIsolation = UNKNOWN_TRANSACTIONISOLATION; + + /** Connection property defaults to false. */ private Boolean defaultReadOnly; /** @@ -198,7 +236,7 @@ public Connection getConnection(final String userName, final String userPassword) throws SQLException { if (instanceKey == null) { throw new SQLException("Must set the ConnectionPoolDataSource " - + "through setDataSourceName or setConnectionPoolDataSource" + " before calling getConnection."); + + "through setDataSourceName or setConnectionPoolDataSource before calling getConnection."); } getConnectionCalled = true; PooledConnectionAndInfo info = null; @@ -220,7 +258,7 @@ // Password has not changed, so refuse client, but return connection to the pool closeDueToException(info); throw new SQLException( - "Given password did not match password used" + " to create the PooledConnection.", ex); + "Given password did not match password used to create the PooledConnection.", ex); } catch (final javax.naming.NamingException ne) { throw new SQLException("NamingException encountered connecting to database", ne); } @@ -233,7 +271,7 @@ // Destroy and remove from pool manager.invalidate(info.getPooledConnection()); // Reset the password on the factory if using CPDSConnectionFactory - manager.setPassword(upkey.getPassword()); + manager.setPassword(upkey.getPasswordCharArray()); info = null; for (int i = 0; i < 10; i++) { // Bound the number of retries - only needed if bad instances return try { @@ -269,6 +307,12 @@ } } + /** + * Gets the pooled connection manager for the given key. + * + * @param upkey the key. + * @return the pooled connection manager for the given key. + */ protected abstract PooledConnectionManager getConnectionManager(UserPassKey upkey); /** @@ -416,11 +460,11 @@ } /** - * Gets the default value for {@link org.apache.tomcat.dbcp.pool2.impl.GenericObjectPool - * GenericObjectPool#getSoftMinEvictableIdleTimeMillis()} for each per user pool. + * Gets the default value for {@link + * GenericObjectPool#getSoftMinEvictableIdleDuration()} for each per user pool. * - * @return The default value for {@link org.apache.tomcat.dbcp.pool2.impl.GenericObjectPool - * GenericObjectPool#getSoftMinEvictableIdleTimeMillis()} for each per user pool. + * @return The default value for {@link + * GenericObjectPool#getSoftMinEvictableIdleDuration()} for each per user pool. * @since 2.10.0 */ public Duration getDefaultSoftMinEvictableIdleDuration() { @@ -428,10 +472,10 @@ } /** - * Gets the default value for {@link org.apache.tomcat.dbcp.pool2.impl.GenericObjectPool + * Gets the default value for {@link * GenericObjectPool#getSoftMinEvictableIdleTimeMillis()} for each per user pool. * - * @return The default value for {@link org.apache.tomcat.dbcp.pool2.impl.GenericObjectPool + * @return The default value for {@link * GenericObjectPool#getSoftMinEvictableIdleTimeMillis()} for each per user pool. * @deprecated Use {@link #getDefaultSoftMinEvictableIdleDuration()}. */ @@ -441,10 +485,10 @@ } /** - * Gets the default value for {@link org.apache.tomcat.dbcp.pool2.impl.GenericObjectPool + * Gets the default value for {@link * GenericObjectPool#getTestOnBorrow()} for each per user pool. * - * @return The default value for {@link org.apache.tomcat.dbcp.pool2.impl.GenericObjectPool + * @return The default value for {@link * GenericObjectPool#getTestOnBorrow()} for each per user pool. */ public boolean getDefaultTestOnBorrow() { @@ -452,10 +496,10 @@ } /** - * Gets the default value for {@link org.apache.tomcat.dbcp.pool2.impl.GenericObjectPool + * Gets the default value for {@link * GenericObjectPool#getTestOnCreate()} for each per user pool. * - * @return The default value for {@link org.apache.tomcat.dbcp.pool2.impl.GenericObjectPool + * @return The default value for {@link * GenericObjectPool#getTestOnCreate()} for each per user pool. */ public boolean getDefaultTestOnCreate() { @@ -463,10 +507,10 @@ } /** - * Gets the default value for {@link org.apache.tomcat.dbcp.pool2.impl.GenericObjectPool + * Gets the default value for {@link * GenericObjectPool#getTestOnReturn()} for each per user pool. * - * @return The default value for {@link org.apache.tomcat.dbcp.pool2.impl.GenericObjectPool + * @return The default value for {@link * GenericObjectPool#getTestOnReturn()} for each per user pool. */ public boolean getDefaultTestOnReturn() { @@ -474,10 +518,10 @@ } /** - * Gets the default value for {@link org.apache.tomcat.dbcp.pool2.impl.GenericObjectPool + * Gets the default value for {@link * GenericObjectPool#getTestWhileIdle()} for each per user pool. * - * @return The default value for {@link org.apache.tomcat.dbcp.pool2.impl.GenericObjectPool + * @return The default value for {@link * GenericObjectPool#getTestWhileIdle()} for each per user pool. */ public boolean getDefaultTestWhileIdle() { @@ -666,7 +710,7 @@ /** * Gets the value of defaultAutoCommit, which defines the state of connections handed out from this pool. The value * can be changed on the Connection using Connection.setAutoCommit(boolean). The default is {@code null} which - * will use the default value for the drive. + * will use the default value for the driver. * * @return value of defaultAutoCommit. */ @@ -677,7 +721,7 @@ /** * Gets the value of defaultReadOnly, which defines the state of connections handed out from this pool. The value * can be changed on the Connection using Connection.setReadOnly(boolean). The default is {@code null} which - * will use the default value for the drive. + * will use the default value for the driver. * * @return value of defaultReadOnly. */ @@ -686,7 +730,7 @@ } /** - * Whether a rollback will be issued after executing the SQL query that will be used to validate connections from + * Tests whether a rollback will be issued after executing the SQL query that will be used to validate connections from * this pool before returning them to the caller. * * @return true if a rollback will be issued after executing the validation query @@ -733,7 +777,7 @@ + "set using setConnectionPoolDataSource."); } if (this.dataSourceName != null) { - throw new IllegalStateException("The DataSourceName has already been set. " + "It cannot be altered."); + throw new IllegalStateException("The DataSourceName has already been set. It cannot be altered."); } this.dataSourceName = dataSourceName; instanceKey = InstanceKeyDataSourceFactory.registerNewInstance(this); @@ -742,7 +786,7 @@ /** * Sets the value of defaultAutoCommit, which defines the state of connections handed out from this pool. The value * can be changed on the Connection using Connection.setAutoCommit(boolean). The default is {@code null} which - * will use the default value for the drive. + * will use the default value for the driver. * * @param defaultAutoCommit * Value to assign to defaultAutoCommit. @@ -902,7 +946,7 @@ /** * Sets the value of defaultReadOnly, which defines the state of connections handed out from this pool. The value * can be changed on the Connection using Connection.setReadOnly(boolean). The default is {@code null} which - * will use the default value for the drive. + * will use the default value for the driver. * * @param defaultReadOnly * Value to assign to defaultReadOnly. @@ -913,12 +957,12 @@ } /** - * Sets the default value for {@link org.apache.tomcat.dbcp.pool2.impl.GenericObjectPool - * GenericObjectPool#getSoftMinEvictableIdleTimeMillis()} for each per user pool. + * Sets the default value for {@link + * GenericObjectPool#getSoftMinEvictableIdleDuration()} for each per user pool. * * @param defaultSoftMinEvictableIdleDuration - * The default value for {@link org.apache.tomcat.dbcp.pool2.impl.GenericObjectPool - * GenericObjectPool#getSoftMinEvictableIdleTimeMillis()} for each per user pool. + * The default value for {@link + * GenericObjectPool#getSoftMinEvictableIdleDuration()} for each per user pool. * @since 2.10.0 */ public void setDefaultSoftMinEvictableIdle(final Duration defaultSoftMinEvictableIdleDuration) { @@ -927,11 +971,11 @@ } /** - * Sets the default value for {@link org.apache.tomcat.dbcp.pool2.impl.GenericObjectPool + * Sets the default value for {@link * GenericObjectPool#getSoftMinEvictableIdleTimeMillis()} for each per user pool. * * @param softMinEvictableIdleTimeMillis - * The default value for {@link org.apache.tomcat.dbcp.pool2.impl.GenericObjectPool + * The default value for {@link * GenericObjectPool#getSoftMinEvictableIdleTimeMillis()} for each per user pool. * @deprecated Use {@link #setDefaultSoftMinEvictableIdle(Duration)}. */ @@ -942,11 +986,11 @@ } /** - * Sets the default value for {@link org.apache.tomcat.dbcp.pool2.impl.GenericObjectPool + * Sets the default value for {@link * GenericObjectPool#getTestOnBorrow()} for each per user pool. * * @param testOnBorrow - * The default value for {@link org.apache.tomcat.dbcp.pool2.impl.GenericObjectPool + * The default value for {@link * GenericObjectPool#getTestOnBorrow()} for each per user pool. */ public void setDefaultTestOnBorrow(final boolean testOnBorrow) { @@ -955,11 +999,11 @@ } /** - * Sets the default value for {@link org.apache.tomcat.dbcp.pool2.impl.GenericObjectPool + * Sets the default value for {@link * GenericObjectPool#getTestOnCreate()} for each per user pool. * * @param testOnCreate - * The default value for {@link org.apache.tomcat.dbcp.pool2.impl.GenericObjectPool + * The default value for {@link * GenericObjectPool#getTestOnCreate()} for each per user pool. */ public void setDefaultTestOnCreate(final boolean testOnCreate) { @@ -968,11 +1012,11 @@ } /** - * Sets the default value for {@link org.apache.tomcat.dbcp.pool2.impl.GenericObjectPool + * Sets the default value for {@link * GenericObjectPool#getTestOnReturn()} for each per user pool. * * @param testOnReturn - * The default value for {@link org.apache.tomcat.dbcp.pool2.impl.GenericObjectPool + * The default value for {@link * GenericObjectPool#getTestOnReturn()} for each per user pool. */ public void setDefaultTestOnReturn(final boolean testOnReturn) { @@ -981,11 +1025,11 @@ } /** - * Sets the default value for {@link org.apache.tomcat.dbcp.pool2.impl.GenericObjectPool + * Sets the default value for {@link * GenericObjectPool#getTestWhileIdle()} for each per user pool. * * @param testWhileIdle - * The default value for {@link org.apache.tomcat.dbcp.pool2.impl.GenericObjectPool + * The default value for {@link * GenericObjectPool#getTestWhileIdle()} for each per user pool. */ public void setDefaultTestWhileIdle(final boolean testWhileIdle) { @@ -1017,14 +1061,14 @@ public void setDefaultTransactionIsolation(final int defaultTransactionIsolation) { assertInitializationAllowed(); switch (defaultTransactionIsolation) { - case Connection.TRANSACTION_NONE: - case Connection.TRANSACTION_READ_COMMITTED: - case Connection.TRANSACTION_READ_UNCOMMITTED: - case Connection.TRANSACTION_REPEATABLE_READ: - case Connection.TRANSACTION_SERIALIZABLE: - break; - default: - throw new IllegalArgumentException(BAD_TRANSACTION_ISOLATION); + case Connection.TRANSACTION_NONE: + case Connection.TRANSACTION_READ_COMMITTED: + case Connection.TRANSACTION_READ_UNCOMMITTED: + case Connection.TRANSACTION_REPEATABLE_READ: + case Connection.TRANSACTION_SERIALIZABLE: + break; + default: + throw new IllegalArgumentException(BAD_TRANSACTION_ISOLATION); } this.defaultTransactionIsolation = defaultTransactionIsolation; } @@ -1143,7 +1187,7 @@ } /** - * Whether a rollback will be issued after executing the SQL query that will be used to validate connections from + * Sets whether a rollback will be issued after executing the SQL query that will be used to validate connections from * this pool before returning them to the caller. Default behavior is NOT to issue a rollback. The setting will only * have an effect if a validation query is set * @@ -1155,6 +1199,13 @@ this.rollbackAfterValidation = rollbackAfterValidation; } + /** + * Sets up the defaults for a given connection. + * + * @param connection The target connection. + * @param userName The user name for the connection. + * @throws SQLException if a database access error occurs or this method is called on a closed connection + */ protected abstract void setupDefaults(Connection connection, String userName) throws SQLException; /** @@ -1193,9 +1244,18 @@ this.validationQueryTimeoutDuration = Duration.ofSeconds(validationQueryTimeoutSeconds); } + /** + * Tests and returns whether a JNDI context can be created to lookup a ConnectionPoolDataSource to then access a PooledConnection connection. + * + * @param userName An optional user name, may be null. + * @param userPassword An optional user user password, may be null. + * @return A ConnectionPoolDataSource from a JNDI context. + * @throws javax.naming.NamingException if a naming exception is encountered. + * @throws SQLException if a ConnectionPoolDataSource or PooledConnection is not available. + */ protected ConnectionPoolDataSource testCPDS(final String userName, final String userPassword) throws javax.naming.NamingException, SQLException { - // The source of physical db connections + // The source of physical database connections ConnectionPoolDataSource cpds = this.dataSource; if (cpds == null) { Context ctx = null; @@ -1206,12 +1266,11 @@ } final Object ds = ctx.lookup(dataSourceName); if (!(ds instanceof ConnectionPoolDataSource)) { - throw new SQLException("Illegal configuration: " + "DataSource " + dataSourceName + " (" - + ds.getClass().getName() + ")" + " doesn't implement javax.sql.ConnectionPoolDataSource"); + throw new SQLException("Illegal configuration: DataSource " + dataSourceName + " (" + + ds.getClass().getName() + ") doesn't implement javax.sql.ConnectionPoolDataSource"); } cpds = (ConnectionPoolDataSource) ds; } - // try to get a connection with the supplied userName/password PooledConnection conn = null; try { @@ -1247,6 +1306,11 @@ return builder.toString(); } + /** + * Appends this instance's fields to a string builder. + * + * @param builder the target string builder. + */ protected void toStringFields(final StringBuilder builder) { builder.append("getConnectionCalled="); builder.append(getConnectionCalled); diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/dbcp/dbcp2/datasources/InstanceKeyDataSourceFactory.java tomcat10-10.1.52/java/org/apache/tomcat/dbcp/dbcp2/datasources/InstanceKeyDataSourceFactory.java --- tomcat10-10.1.40/java/org/apache/tomcat/dbcp/dbcp2/datasources/InstanceKeyDataSourceFactory.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/dbcp/dbcp2/datasources/InstanceKeyDataSourceFactory.java 2026-01-23 19:33:36.000000000 +0000 @@ -6,7 +6,7 @@ * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -37,7 +37,7 @@ import org.apache.tomcat.dbcp.dbcp2.Utils; /** - * A JNDI ObjectFactory which creates {@code SharedPoolDataSource}s or {@code PerUserPoolDataSource}s + * A JNDI ObjectFactory which creates {@link SharedPoolDataSource}s or {@link PerUserPoolDataSource}s * * @since 2.0 */ @@ -116,7 +116,7 @@ } } - private Boolean booleanValueOf(RefAddr refAddr) { + private Boolean booleanValueOf(final RefAddr refAddr) { return Boolean.valueOf(toString(refAddr)); } @@ -340,11 +340,11 @@ } } - private Duration toDurationFromMillis(RefAddr refAddr) { + private Duration toDurationFromMillis(final RefAddr refAddr) { return Duration.ofMillis(parseLong(refAddr)); } - private Duration toDurationFromSeconds(RefAddr refAddr) { + private Duration toDurationFromSeconds(final RefAddr refAddr) { return Duration.ofSeconds(parseInt(refAddr)); } diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/dbcp/dbcp2/datasources/KeyedCPDSConnectionFactory.java tomcat10-10.1.52/java/org/apache/tomcat/dbcp/dbcp2/datasources/KeyedCPDSConnectionFactory.java --- tomcat10-10.1.40/java/org/apache/tomcat/dbcp/dbcp2/datasources/KeyedCPDSConnectionFactory.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/dbcp/dbcp2/datasources/KeyedCPDSConnectionFactory.java 2026-01-23 19:33:36.000000000 +0000 @@ -6,7 +6,7 @@ * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -17,21 +17,14 @@ package org.apache.tomcat.dbcp.dbcp2.datasources; import java.sql.Connection; -import java.sql.ResultSet; import java.sql.SQLException; -import java.sql.Statement; import java.time.Duration; -import java.util.Collections; -import java.util.Map; -import java.util.Set; -import java.util.concurrent.ConcurrentHashMap; import javax.sql.ConnectionEvent; import javax.sql.ConnectionEventListener; import javax.sql.ConnectionPoolDataSource; import javax.sql.PooledConnection; -import org.apache.tomcat.dbcp.dbcp2.Utils; import org.apache.tomcat.dbcp.pool2.KeyedObjectPool; import org.apache.tomcat.dbcp.pool2.KeyedPooledObjectFactory; import org.apache.tomcat.dbcp.pool2.PooledObject; @@ -42,31 +35,14 @@ * * @since 2.0 */ -final class KeyedCPDSConnectionFactory implements KeyedPooledObjectFactory, - ConnectionEventListener, PooledConnectionManager { +final class KeyedCPDSConnectionFactory extends AbstractConnectionFactory + implements KeyedPooledObjectFactory, ConnectionEventListener, PooledConnectionManager { - private static final String NO_KEY_MESSAGE = "close() was called on a Connection, but " - + "I have no record of the underlying PooledConnection."; - - private final ConnectionPoolDataSource cpds; - private final String validationQuery; - private final Duration validationQueryTimeoutDuration; - private final boolean rollbackAfterValidation; + private static final String NO_KEY_MESSAGE = "close() was called on a Connection, but I have no record of the underlying PooledConnection."; private KeyedObjectPool pool; - private Duration maxConnLifetime = Duration.ofMillis(-1); - - /** - * Map of PooledConnections for which close events are ignored. Connections are muted when they are being validated. - */ - private final Set validatingSet = Collections.newSetFromMap(new ConcurrentHashMap<>()); - - /** - * Map of PooledConnectionAndInfo instances - */ - private final Map pcMap = new ConcurrentHashMap<>(); /** - * Creates a new {@code KeyedPoolableConnectionFactory}. + * Creates a new {@code KeyedCPDSConnectionFactory}. * * @param cpds * the ConnectionPoolDataSource from which to obtain PooledConnections @@ -74,44 +50,20 @@ * a query to use to {@link #validateObject validate} {@link Connection}s. Should return at least one * row. May be {@code null} in which case3 {@link Connection#isValid(int)} will be used to validate * connections. - * @param validationQueryTimeoutSeconds + * @param validationQueryTimeoutDuration * The Duration to allow for the validation query to complete * @param rollbackAfterValidation * whether a rollback should be issued after {@link #validateObject validating} {@link Connection}s. * @since 2.10.0 */ KeyedCPDSConnectionFactory(final ConnectionPoolDataSource cpds, final String validationQuery, - final Duration validationQueryTimeoutSeconds, final boolean rollbackAfterValidation) { - this.cpds = cpds; - this.validationQuery = validationQuery; - this.validationQueryTimeoutDuration = validationQueryTimeoutSeconds; - this.rollbackAfterValidation = rollbackAfterValidation; - } - - /** - * Creates a new {@code KeyedPoolableConnectionFactory}. - * - * @param cpds - * the ConnectionPoolDataSource from which to obtain PooledConnections - * @param validationQuery - * a query to use to {@link #validateObject validate} {@link Connection}s. Should return at least one - * row. May be {@code null} in which case3 {@link Connection#isValid(int)} will be used to validate - * connections. - * @param validationQueryTimeoutSeconds - * The time, in seconds, to allow for the validation query to complete - * @param rollbackAfterValidation - * whether a rollback should be issued after {@link #validateObject validating} {@link Connection}s. - * @deprecated Use {@link #KeyedCPDSConnectionFactory(ConnectionPoolDataSource, String, Duration, boolean)}. - */ - @Deprecated - KeyedCPDSConnectionFactory(final ConnectionPoolDataSource cpds, final String validationQuery, - final int validationQueryTimeoutSeconds, final boolean rollbackAfterValidation) { - this(cpds, validationQuery, Duration.ofSeconds(validationQueryTimeoutSeconds), rollbackAfterValidation); + final Duration validationQueryTimeoutDuration, final boolean rollbackAfterValidation) { + super(cpds, validationQuery, validationQueryTimeoutDuration, rollbackAfterValidation); } @Override - public void activateObject(final UserPassKey key, final PooledObject p) throws SQLException { - validateLifetime(p); + public void activateObject(final UserPassKey ignored, final PooledObject pooledObject) throws SQLException { + validateLifetime(pooledObject); } /** @@ -146,7 +98,7 @@ try { pool.returnObject(pci.getUserPassKey(), pci); } catch (final Exception e) { - System.err.println("CLOSING DOWN CONNECTION AS IT COULD " + "NOT BE RETURNED TO THE POOL"); + System.err.println("CLOSING DOWN CONNECTION AS IT COULD NOT BE RETURNED TO THE POOL"); pc.removeConnectionEventListener(this); try { pool.invalidateObject(pci.getUserPassKey(), pci); @@ -185,8 +137,8 @@ * Closes the PooledConnection and stops listening for events from it. */ @Override - public void destroyObject(final UserPassKey key, final PooledObject p) throws SQLException { - final PooledConnection pooledConnection = p.getObject().getPooledConnection(); + public void destroyObject(final UserPassKey ignored, final PooledObject pooledObject) throws SQLException { + final PooledConnection pooledConnection = pooledObject.getObject().getPooledConnection(); pooledConnection.removeConnectionEventListener(this); pcMap.remove(pooledConnection); pooledConnection.close(); @@ -241,62 +193,28 @@ } else { pooledConnection = cpds.getPooledConnection(userName, password); } - if (pooledConnection == null) { throw new IllegalStateException("Connection pool data source returned null from getPooledConnection"); } - // should we add this object as a listener or the pool. // consider the validateObject method in decision pooledConnection.addConnectionEventListener(this); final PooledConnectionAndInfo pci = new PooledConnectionAndInfo(pooledConnection, userPassKey); pcMap.put(pooledConnection, pci); - return new DefaultPooledObject<>(pci); } @Override - public void passivateObject(final UserPassKey key, final PooledObject p) throws SQLException { - validateLifetime(p); - } - - /** - * Sets the maximum lifetime of a connection after which the connection will always fail activation, - * passivation and validation. - * - * @param maxConnLifetimeMillis - * A value of zero or less indicates an infinite lifetime. The default value is -1 milliseconds. - * @since 2.10.0 - */ - public void setMaxConn(final Duration maxConnLifetimeMillis) { - this.maxConnLifetime = maxConnLifetimeMillis; + public void passivateObject(final UserPassKey ignored, final PooledObject pooledObject) throws SQLException { + validateLifetime(pooledObject); } /** - * Sets the maximum lifetime of a connection after which the connection will always fail activation, - * passivation and validation. - * - * @param maxConnLifetimeMillis - * A value of zero or less indicates an infinite lifetime. The default value is -1 milliseconds. - * @since 2.9.0 - * @deprecated Use {@link #setMaxConn(Duration)}. + * Does nothing. This factory does not cache user credentials. */ - @Deprecated - public void setMaxConnLifetime(final Duration maxConnLifetimeMillis) { - this.maxConnLifetime = maxConnLifetimeMillis; - } - - /** - * Sets the maximum lifetime in milliseconds of a connection after which the connection will always fail activation, - * passivation and validation. - * - * @param maxConnLifetimeMillis - * A value of zero or less indicates an infinite lifetime. The default value is -1. - * @deprecated Use {@link #setMaxConnLifetime(Duration)}. - */ - @Deprecated - public void setMaxConnLifetimeMillis(final long maxConnLifetimeMillis) { - setMaxConn(Duration.ofMillis(maxConnLifetimeMillis)); + @Override + public void setPassword(final char[] password) { + // Does nothing. This factory does not cache user credentials. } /** @@ -311,69 +229,21 @@ this.pool = pool; } - private void validateLifetime(final PooledObject pooledObject) throws SQLException { - Utils.validateLifetime(pooledObject, maxConnLifetime); - } - /** * Validates a pooled connection. + *

        + * A query validation timeout greater than 0 and less than 1 second is converted to 1 second. + *

        * - * @param key + * @param ignored * ignored * @param pooledObject * wrapped {@code PooledConnectionAndInfo} containing the connection to validate * @return true if validation succeeds + * @throws ArithmeticException if the query validation timeout does not fit as seconds in an int. */ @Override - public boolean validateObject(final UserPassKey key, final PooledObject pooledObject) { - try { - validateLifetime(pooledObject); - } catch (final Exception e) { - return false; - } - boolean valid = false; - final PooledConnection pooledConn = pooledObject.getObject().getPooledConnection(); - Connection conn = null; - validatingSet.add(pooledConn); - if (null == validationQuery) { - Duration timeoutDuration = validationQueryTimeoutDuration; - if (timeoutDuration.isNegative()) { - timeoutDuration = Duration.ZERO; - } - try { - conn = pooledConn.getConnection(); - valid = conn.isValid((int) timeoutDuration.getSeconds()); - } catch (final SQLException e) { - valid = false; - } finally { - Utils.closeQuietly((AutoCloseable) conn); - validatingSet.remove(pooledConn); - } - } else { - Statement stmt = null; - ResultSet rset = null; - // logical Connection from the PooledConnection must be closed - // before another one can be requested and closing it will - // generate an event. Keep track so we know not to return - // the PooledConnection - validatingSet.add(pooledConn); - try { - conn = pooledConn.getConnection(); - stmt = conn.createStatement(); - rset = stmt.executeQuery(validationQuery); - valid = rset.next(); - if (rollbackAfterValidation) { - conn.rollback(); - } - } catch (final Exception e) { - valid = false; - } finally { - Utils.closeQuietly((AutoCloseable) rset); - Utils.closeQuietly((AutoCloseable) stmt); - Utils.closeQuietly((AutoCloseable) conn); - validatingSet.remove(pooledConn); - } - } - return valid; + public boolean validateObject(final UserPassKey ignored, final PooledObject pooledObject) { + return super.validateObject(pooledObject); } } diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/dbcp/dbcp2/datasources/PerUserPoolDataSource.java tomcat10-10.1.52/java/org/apache/tomcat/dbcp/dbcp2/datasources/PerUserPoolDataSource.java --- tomcat10-10.1.40/java/org/apache/tomcat/dbcp/dbcp2/datasources/PerUserPoolDataSource.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/dbcp/dbcp2/datasources/PerUserPoolDataSource.java 2026-01-23 19:33:36.000000000 +0000 @@ -6,7 +6,7 @@ * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -30,6 +30,7 @@ import javax.naming.Reference; import javax.naming.StringRefAddr; import javax.sql.ConnectionPoolDataSource; +import javax.sql.DataSource; import org.apache.juli.logging.Log; import org.apache.juli.logging.LogFactory; @@ -41,7 +42,7 @@ /** *

        - * A pooling {@code DataSource} appropriate for deployment within J2EE environment. There are many configuration + * A pooling {@link DataSource} appropriate for deployment within J2EE environment. There are many configuration * options, most of which are defined in the parent class. This datasource uses individual pools per user, and some * properties can be set specifically for a given user, if the deployment environment can support initialization of * mapped properties. So for example, a pool of admin or write-access Connections can be guaranteed a certain number of @@ -641,7 +642,7 @@ } /** - * Returns a {@code PerUserPoolDataSource} {@link Reference}. + * Returns a {@link PerUserPoolDataSource} {@link Reference}. */ @Override public Reference getReference() throws NamingException { @@ -684,7 +685,7 @@ // the factory with the pool, so we do not have to do so // explicitly) final CPDSConnectionFactory factory = new CPDSConnectionFactory(cpds, getValidationQuery(), getValidationQueryTimeoutDuration(), - isRollbackAfterValidation(), userName, password); + isRollbackAfterValidation(), userName, Utils.toCharArray(password)); factory.setMaxConn(getMaxConnDuration()); // Create an object pool to contain our PooledConnections final GenericObjectPool pool = new GenericObjectPool<>(factory); diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/dbcp/dbcp2/datasources/PerUserPoolDataSourceFactory.java tomcat10-10.1.52/java/org/apache/tomcat/dbcp/dbcp2/datasources/PerUserPoolDataSourceFactory.java --- tomcat10-10.1.40/java/org/apache/tomcat/dbcp/dbcp2/datasources/PerUserPoolDataSourceFactory.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/dbcp/dbcp2/datasources/PerUserPoolDataSourceFactory.java 2026-01-23 19:33:36.000000000 +0000 @@ -6,7 +6,7 @@ * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -24,13 +24,20 @@ import javax.naming.Reference; /** - * A JNDI ObjectFactory which creates {@code SharedPoolDataSource}s + * A JNDI ObjectFactory which creates {@link SharedPoolDataSource}s * * @since 2.0 */ public class PerUserPoolDataSourceFactory extends InstanceKeyDataSourceFactory { private static final String PER_USER_POOL_CLASSNAME = PerUserPoolDataSource.class.getName(); + /** + * Constructs a new instance. + */ + public PerUserPoolDataSourceFactory() { + // empty + } + @SuppressWarnings("unchecked") // Avoid warnings on deserialization @Override protected InstanceKeyDataSource getNewInstance(final Reference ref) throws IOException, ClassNotFoundException { diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/dbcp/dbcp2/datasources/PoolKey.java tomcat10-10.1.52/java/org/apache/tomcat/dbcp/dbcp2/datasources/PoolKey.java --- tomcat10-10.1.40/java/org/apache/tomcat/dbcp/dbcp2/datasources/PoolKey.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/dbcp/dbcp2/datasources/PoolKey.java 2026-01-23 19:33:36.000000000 +0000 @@ -6,7 +6,7 @@ * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -40,10 +40,7 @@ if (this == obj) { return true; } - if (obj == null) { - return false; - } - if (getClass() != obj.getClass()) { + if (obj == null || getClass() != obj.getClass()) { return false; } final PoolKey other = (PoolKey) obj; diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/dbcp/dbcp2/datasources/PooledConnectionAndInfo.java tomcat10-10.1.52/java/org/apache/tomcat/dbcp/dbcp2/datasources/PooledConnectionAndInfo.java --- tomcat10-10.1.40/java/org/apache/tomcat/dbcp/dbcp2/datasources/PooledConnectionAndInfo.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/dbcp/dbcp2/datasources/PooledConnectionAndInfo.java 2026-01-23 19:33:36.000000000 +0000 @@ -6,7 +6,7 @@ * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/dbcp/dbcp2/datasources/PooledConnectionManager.java tomcat10-10.1.52/java/org/apache/tomcat/dbcp/dbcp2/datasources/PooledConnectionManager.java --- tomcat10-10.1.40/java/org/apache/tomcat/dbcp/dbcp2/datasources/PooledConnectionManager.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/dbcp/dbcp2/datasources/PooledConnectionManager.java 2026-01-23 19:33:36.000000000 +0000 @@ -6,7 +6,7 @@ * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -14,6 +14,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.tomcat.dbcp.dbcp2.datasources; import java.sql.SQLException; @@ -31,9 +32,9 @@ * Closes the connection pool associated with the given user. * * @param userName - * user name + * user name. * @throws SQLException - * if an error occurs closing idle connections in the pool + * if an error occurs closing idle connections in the pool. */ void closePool(String userName) throws SQLException; @@ -41,27 +42,27 @@ * Closes the PooledConnection and remove it from the connection pool to which it belongs, adjusting pool counters. * * @param pc - * PooledConnection to be invalidated + * PooledConnection to be invalidated. * @throws SQLException - * if an SQL error occurs closing the connection + * if an SQL error occurs closing the connection. */ void invalidate(PooledConnection pc) throws SQLException; -// /** -// * Sets the database password used when creating connections. -// * -// * @param password password used when authenticating to the database -// * @since 2.10.0 -// */ -// default void setPassword(char[] password) { -// setPassword(String.copyValueOf(password)); -// } + /** + * Sets the database password used when creating connections. + * + * @param password password used when authenticating to the database. + * @since 2.14.0 + */ + default void setPassword(final char[] password) { + setPassword(String.copyValueOf(password)); + } /** * Sets the database password used when creating connections. * * @param password - * password used when authenticating to the database + * password used when authenticating to the database. */ void setPassword(String password); diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/dbcp/dbcp2/datasources/SharedPoolDataSource.java tomcat10-10.1.52/java/org/apache/tomcat/dbcp/dbcp2/datasources/SharedPoolDataSource.java --- tomcat10-10.1.40/java/org/apache/tomcat/dbcp/dbcp2/datasources/SharedPoolDataSource.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/dbcp/dbcp2/datasources/SharedPoolDataSource.java 2026-01-23 19:33:36.000000000 +0000 @@ -6,7 +6,7 @@ * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -25,6 +25,7 @@ import javax.naming.Reference; import javax.naming.StringRefAddr; import javax.sql.ConnectionPoolDataSource; +import javax.sql.DataSource; import org.apache.tomcat.dbcp.pool2.KeyedObjectPool; import org.apache.tomcat.dbcp.pool2.impl.GenericKeyedObjectPool; @@ -32,7 +33,7 @@ /** *

        - * A pooling {@code DataSource} appropriate for deployment within J2EE environment. There are many configuration + * A pooling {@link DataSource} appropriate for deployment within J2EE environment. There are many configuration * options, most of which are defined in the parent class. All users (based on user name) share a single maximum number * of Connections in this data source. *

        @@ -54,7 +55,7 @@ /** * Max total defaults to {@link GenericKeyedObjectPoolConfig#DEFAULT_MAX_TOTAL}. */ - private int maxTotal = GenericKeyedObjectPoolConfig.DEFAULT_MAX_TOTAL; + private volatile int maxTotal = GenericKeyedObjectPoolConfig.DEFAULT_MAX_TOTAL; /** * Maps user credentials to pooled connection with credentials. diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/dbcp/dbcp2/datasources/SharedPoolDataSourceFactory.java tomcat10-10.1.52/java/org/apache/tomcat/dbcp/dbcp2/datasources/SharedPoolDataSourceFactory.java --- tomcat10-10.1.40/java/org/apache/tomcat/dbcp/dbcp2/datasources/SharedPoolDataSourceFactory.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/dbcp/dbcp2/datasources/SharedPoolDataSourceFactory.java 2026-01-23 19:33:36.000000000 +0000 @@ -6,7 +6,7 @@ * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -20,7 +20,7 @@ import javax.naming.Reference; /** - * A JNDI ObjectFactory which creates {@code SharedPoolDataSource}s + * A JNDI ObjectFactory which creates {@link SharedPoolDataSource}s * * @since 2.0 */ diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/dbcp/dbcp2/datasources/UserPassKey.java tomcat10-10.1.52/java/org/apache/tomcat/dbcp/dbcp2/datasources/UserPassKey.java --- tomcat10-10.1.40/java/org/apache/tomcat/dbcp/dbcp2/datasources/UserPassKey.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/dbcp/dbcp2/datasources/UserPassKey.java 2026-01-23 19:33:36.000000000 +0000 @@ -6,7 +6,7 @@ * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -26,7 +26,7 @@ * Holds a user name and password pair. Serves as a poolable object key for the {@link KeyedObjectPool} backing a * {@link SharedPoolDataSource}. Two instances with the same user name are considered equal. This ensures that there * will be only one keyed pool for each user in the pool. The password is used (along with the user name) by the - * {@code KeyedCPDSConnectionFactory} when creating new connections. + * {@link KeyedCPDSConnectionFactory} when creating new connections. *

        * *

        @@ -60,6 +60,17 @@ } /** + * Clears the content of the name and password. + * + * @return {@code this} instance. + */ + UserPassKey clear() { + name.clear(); + password.clear(); + return this; + } + + /** * Only takes the user name into account. */ @Override @@ -67,10 +78,7 @@ if (this == obj) { return true; } - if (obj == null) { - return false; - } - if (getClass() != obj.getClass()) { + if (obj == null || getClass() != obj.getClass()) { return false; } final UserPassKey other = (UserPassKey) obj; diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/dbcp/dbcp2/datasources/package-info.java tomcat10-10.1.52/java/org/apache/tomcat/dbcp/dbcp2/datasources/package-info.java --- tomcat10-10.1.40/java/org/apache/tomcat/dbcp/dbcp2/datasources/package-info.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/dbcp/dbcp2/datasources/package-info.java 2026-01-23 19:33:36.000000000 +0000 @@ -6,7 +6,7 @@ * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/dbcp/dbcp2/managed/BasicManagedDataSource.java tomcat10-10.1.52/java/org/apache/tomcat/dbcp/dbcp2/managed/BasicManagedDataSource.java --- tomcat10-10.1.40/java/org/apache/tomcat/dbcp/dbcp2/managed/BasicManagedDataSource.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/dbcp/dbcp2/managed/BasicManagedDataSource.java 2026-01-23 19:33:36.000000000 +0000 @@ -6,7 +6,7 @@ * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -67,8 +67,15 @@ /** Transaction Synchronization Registry */ private transient TransactionSynchronizationRegistry transactionSynchronizationRegistry; + /** + * Constructs a new instance. + */ + public BasicManagedDataSource() { + // empty + } + @Override - protected ConnectionFactory createConnectionFactory() throws SQLException { + protected synchronized ConnectionFactory createConnectionFactory() throws SQLException { if (transactionManager == null) { throw new SQLException("Transaction manager must be set before a connection can be created"); } diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/dbcp/dbcp2/managed/DataSourceXAConnectionFactory.java tomcat10-10.1.52/java/org/apache/tomcat/dbcp/dbcp2/managed/DataSourceXAConnectionFactory.java --- tomcat10-10.1.40/java/org/apache/tomcat/dbcp/dbcp2/managed/DataSourceXAConnectionFactory.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/dbcp/dbcp2/managed/DataSourceXAConnectionFactory.java 2026-01-23 19:33:36.000000000 +0000 @@ -6,7 +6,7 @@ * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -158,15 +158,35 @@ @Override public Connection createConnection() throws SQLException { // create a new XAConnection - final XAConnection xaConnection; - if (userName == null) { - xaConnection = xaDataSource.getXAConnection(); - } else { - xaConnection = xaDataSource.getXAConnection(userName, Utils.toString(userPassword)); + XAConnection xaConnection = null; + Connection connection = null; + final XAResource xaResource; + try { + if (userName == null) { + xaConnection = xaDataSource.getXAConnection(); + } else { + xaConnection = xaDataSource.getXAConnection(userName, Utils.toString(userPassword)); + } + // get the real connection and XAResource from the connection + connection = xaConnection.getConnection(); + xaResource = xaConnection.getXAResource(); + } catch (final SQLException sqle) { + if (connection != null) { + try { + connection.close(); + } catch (final SQLException ignored) { + // Ignore + } + } + if (xaConnection != null) { + try { + xaConnection.close(); + } catch (final SQLException ignored) { + // Ignore + } + } + throw sqle; } - // get the real connection and XAResource from the connection - final Connection connection = xaConnection.getConnection(); - final XAResource xaResource = xaConnection.getXAResource(); // register the XA resource for the connection transactionRegistry.registerConnection(connection, xaResource); // The Connection we're returning is a handle on the XAConnection. diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/dbcp/dbcp2/managed/LocalXAConnectionFactory.java tomcat10-10.1.52/java/org/apache/tomcat/dbcp/dbcp2/managed/LocalXAConnectionFactory.java --- tomcat10-10.1.40/java/org/apache/tomcat/dbcp/dbcp2/managed/LocalXAConnectionFactory.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/dbcp/dbcp2/managed/LocalXAConnectionFactory.java 2026-01-23 19:33:36.000000000 +0000 @@ -6,7 +6,7 @@ * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -103,7 +103,7 @@ connection.commit(); } } catch (final SQLException e) { - throw (XAException) new XAException().initCause(e); + throw newXAException("Commit failed.", e); } finally { try { connection.setAutoCommit(originalAutoCommit); @@ -180,6 +180,10 @@ return this == xaResource; } + private XAException newXAException(final String message, final SQLException cause) { + return (XAException) new XAException(message).initCause(cause); + } + /** * This method does nothing since the LocalXAConnection does not support two-phase-commit. This method will * return XAResource.XA_RDONLY if the connection isReadOnly(). This assumes that the physical connection is @@ -242,7 +246,7 @@ try { connection.rollback(); } catch (final SQLException e) { - throw (XAException) new XAException().initCause(e); + throw newXAException("Rollback failed.", e); } finally { try { connection.setAutoCommit(originalAutoCommit); @@ -282,12 +286,10 @@ public synchronized void start(final Xid xid, final int flag) throws XAException { if (flag == TMNOFLAGS) { // first time in this transaction - // make sure we aren't already in another tx if (this.currentXid != null) { throw new XAException("Already enlisted in another transaction with xid " + xid); } - // save off the current auto commit flag, so it can be restored after the transaction completes try { originalAutoCommit = connection.getAutoCommit(); @@ -295,20 +297,16 @@ // no big deal, just assume it was off originalAutoCommit = true; } - // update the auto commit flag try { connection.setAutoCommit(false); } catch (final SQLException e) { - throw (XAException) new XAException("Count not turn off auto commit for a XA transaction") - .initCause(e); + throw newXAException("Count not turn off auto commit for a XA transaction", e); } - this.currentXid = xid; } else if (flag == TMRESUME) { if (!xid.equals(this.currentXid)) { - throw new XAException("Attempting to resume in different transaction: expected " + this.currentXid - + ", but was " + xid); + throw new XAException("Attempting to resume in different transaction: expected " + this.currentXid + ", but was " + xid); } } else { throw new XAException("Unknown start flag " + flag); diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/dbcp/dbcp2/managed/ManagedConnection.java tomcat10-10.1.52/java/org/apache/tomcat/dbcp/dbcp2/managed/ManagedConnection.java --- tomcat10-10.1.40/java/org/apache/tomcat/dbcp/dbcp2/managed/ManagedConnection.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/dbcp/dbcp2/managed/ManagedConnection.java 2026-01-23 19:33:36.000000000 +0000 @@ -6,7 +6,7 @@ * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -51,6 +51,14 @@ * @since 2.0 */ protected class CompletionListener implements TransactionContextListener { + + /** + * Constructs a new instance. + */ + public CompletionListener() { + // empty + } + @Override public void afterCompletion(final TransactionContext completedContext, final boolean committed) { if (completedContext == transactionContext) { @@ -207,27 +215,23 @@ lock.lock(); try { transactionContext.completeTransaction(); + // If we were using a shared connection, clear the reference now that + // the transaction has completed + if (isSharedConnection) { + setDelegate(null); + isSharedConnection = false; + } } finally { lock.unlock(); } - - // If we were using a shared connection, clear the reference now that - // the transaction has completed - if (isSharedConnection) { - setDelegate(null); - isSharedConnection = false; - } - // autoCommit may have been changed directly on the underlying connection clearCachedState(); - // If this connection was closed during the transaction and there is // still a delegate present close it final Connection delegate = getDelegateInternal(); if (isClosedInternal() && delegate != null) { try { setDelegate(null); - if (!delegate.isClosed()) { delegate.close(); } @@ -253,15 +257,12 @@ // our listener is called. In that rare case, trigger the transaction complete call now transactionComplete(); } - // the existing transaction context ended (or we didn't have one), get the active transaction context transactionContext = transactionRegistry.getActiveTransactionContext(); - // if there is an active transaction context, and it already has a shared connection, use it if (transactionContext != null && transactionContext.getSharedConnection() != null) { // A connection for the connection factory has already been enrolled // in the transaction, replace our delegate with the enrolled connection - // return current connection to the pool final C connection = getDelegateInternal(); setDelegate(null); @@ -277,17 +278,14 @@ } } } - // add a listener to the transaction context transactionContext.addTransactionContextListener(new CompletionListener()); - // Set our delegate to the shared connection. Note that this will // always be of type C since it has been shared by another // connection from the same pool. @SuppressWarnings("unchecked") final C shared = (C) transactionContext.getSharedConnection(); setDelegate(shared); - // remember that we are using a shared connection, so it can be cleared after the // transaction completes isSharedConnection = true; @@ -303,12 +301,10 @@ throw new SQLException("Unable to acquire a new connection from the pool", e); } } - // if we have a transaction, out delegate becomes the shared delegate if (transactionContext != null) { // add a listener to the transaction context transactionContext.addTransactionContextListener(new CompletionListener()); - // register our connection as the shared connection try { transactionContext.setSharedConnection(connection); diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/dbcp/dbcp2/managed/ManagedDataSource.java tomcat10-10.1.52/java/org/apache/tomcat/dbcp/dbcp2/managed/ManagedDataSource.java --- tomcat10-10.1.40/java/org/apache/tomcat/dbcp/dbcp2/managed/ManagedDataSource.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/dbcp/dbcp2/managed/ManagedDataSource.java 2026-01-23 19:33:36.000000000 +0000 @@ -6,7 +6,7 @@ * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/dbcp/dbcp2/managed/PoolableManagedConnection.java tomcat10-10.1.52/java/org/apache/tomcat/dbcp/dbcp2/managed/PoolableManagedConnection.java --- tomcat10-10.1.40/java/org/apache/tomcat/dbcp/dbcp2/managed/PoolableManagedConnection.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/dbcp/dbcp2/managed/PoolableManagedConnection.java 2026-01-23 19:33:36.000000000 +0000 @@ -6,7 +6,7 @@ * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/dbcp/dbcp2/managed/PoolableManagedConnectionFactory.java tomcat10-10.1.52/java/org/apache/tomcat/dbcp/dbcp2/managed/PoolableManagedConnectionFactory.java --- tomcat10-10.1.40/java/org/apache/tomcat/dbcp/dbcp2/managed/PoolableManagedConnectionFactory.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/dbcp/dbcp2/managed/PoolableManagedConnectionFactory.java 2026-01-23 19:33:36.000000000 +0000 @@ -6,7 +6,7 @@ * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/dbcp/dbcp2/managed/SynchronizationAdapter.java tomcat10-10.1.52/java/org/apache/tomcat/dbcp/dbcp2/managed/SynchronizationAdapter.java --- tomcat10-10.1.40/java/org/apache/tomcat/dbcp/dbcp2/managed/SynchronizationAdapter.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/dbcp/dbcp2/managed/SynchronizationAdapter.java 2026-01-23 19:33:36.000000000 +0000 @@ -6,7 +6,7 @@ * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/dbcp/dbcp2/managed/TransactionContext.java tomcat10-10.1.52/java/org/apache/tomcat/dbcp/dbcp2/managed/TransactionContext.java --- tomcat10-10.1.40/java/org/apache/tomcat/dbcp/dbcp2/managed/TransactionContext.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/dbcp/dbcp2/managed/TransactionContext.java 2026-01-23 19:33:36.000000000 +0000 @@ -6,7 +6,7 @@ * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/dbcp/dbcp2/managed/TransactionContextListener.java tomcat10-10.1.52/java/org/apache/tomcat/dbcp/dbcp2/managed/TransactionContextListener.java --- tomcat10-10.1.40/java/org/apache/tomcat/dbcp/dbcp2/managed/TransactionContextListener.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/dbcp/dbcp2/managed/TransactionContextListener.java 2026-01-23 19:33:36.000000000 +0000 @@ -6,7 +6,7 @@ * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/dbcp/dbcp2/managed/TransactionRegistry.java tomcat10-10.1.52/java/org/apache/tomcat/dbcp/dbcp2/managed/TransactionRegistry.java --- tomcat10-10.1.40/java/org/apache/tomcat/dbcp/dbcp2/managed/TransactionRegistry.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/dbcp/dbcp2/managed/TransactionRegistry.java 2026-01-23 19:33:36.000000000 +0000 @@ -6,7 +6,7 @@ * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/dbcp/dbcp2/managed/XAConnectionFactory.java tomcat10-10.1.52/java/org/apache/tomcat/dbcp/dbcp2/managed/XAConnectionFactory.java --- tomcat10-10.1.40/java/org/apache/tomcat/dbcp/dbcp2/managed/XAConnectionFactory.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/dbcp/dbcp2/managed/XAConnectionFactory.java 2026-01-23 19:33:36.000000000 +0000 @@ -6,7 +6,7 @@ * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/dbcp/dbcp2/managed/package-info.java tomcat10-10.1.52/java/org/apache/tomcat/dbcp/dbcp2/managed/package-info.java --- tomcat10-10.1.40/java/org/apache/tomcat/dbcp/dbcp2/managed/package-info.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/dbcp/dbcp2/managed/package-info.java 2026-01-23 19:33:36.000000000 +0000 @@ -6,7 +6,7 @@ * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -29,7 +29,6 @@ * transaction is committed or rolled back the enlisted connections are * committed or rolled back. *

        - * *

        * This package supports full XADataSources and non-XA data sources using * local transaction semantics. non-XA data sources commit and rollback as diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/dbcp/dbcp2/package-info.java tomcat10-10.1.52/java/org/apache/tomcat/dbcp/dbcp2/package-info.java --- tomcat10-10.1.40/java/org/apache/tomcat/dbcp/dbcp2/package-info.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/dbcp/dbcp2/package-info.java 2026-01-23 19:33:36.000000000 +0000 @@ -6,7 +6,7 @@ * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/dbcp/pool2/BaseObject.java tomcat10-10.1.52/java/org/apache/tomcat/dbcp/pool2/BaseObject.java --- tomcat10-10.1.40/java/org/apache/tomcat/dbcp/pool2/BaseObject.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/dbcp/pool2/BaseObject.java 2026-01-23 19:33:36.000000000 +0000 @@ -6,7 +6,7 @@ * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -23,6 +23,13 @@ */ public abstract class BaseObject { + /** + * Constructs a new instance. + */ + public BaseObject() { + // empty + } + @Override public String toString() { final StringBuilder builder = new StringBuilder(); diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/dbcp/pool2/BaseObjectPool.java tomcat10-10.1.52/java/org/apache/tomcat/dbcp/pool2/BaseObjectPool.java --- tomcat10-10.1.40/java/org/apache/tomcat/dbcp/pool2/BaseObjectPool.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/dbcp/pool2/BaseObjectPool.java 2026-01-23 19:33:36.000000000 +0000 @@ -6,7 +6,7 @@ * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -33,6 +33,13 @@ private volatile boolean closed; /** + * Constructs a new instance. + */ + public BaseObjectPool() { + // empty + } + + /** * Not supported in this base implementation. Subclasses should override * this behavior. * diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/dbcp/pool2/DestroyMode.java tomcat10-10.1.52/java/org/apache/tomcat/dbcp/pool2/DestroyMode.java --- tomcat10-10.1.40/java/org/apache/tomcat/dbcp/pool2/DestroyMode.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/dbcp/pool2/DestroyMode.java 2026-01-23 19:33:36.000000000 +0000 @@ -6,7 +6,7 @@ * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/dbcp/pool2/KeyedObjectPool.java tomcat10-10.1.52/java/org/apache/tomcat/dbcp/pool2/KeyedObjectPool.java --- tomcat10-10.1.40/java/org/apache/tomcat/dbcp/pool2/KeyedObjectPool.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/dbcp/pool2/KeyedObjectPool.java 2026-01-23 19:33:36.000000000 +0000 @@ -6,7 +6,7 @@ * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/dbcp/pool2/KeyedPooledObjectFactory.java tomcat10-10.1.52/java/org/apache/tomcat/dbcp/pool2/KeyedPooledObjectFactory.java --- tomcat10-10.1.40/java/org/apache/tomcat/dbcp/pool2/KeyedPooledObjectFactory.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/dbcp/pool2/KeyedPooledObjectFactory.java 2026-01-23 19:33:36.000000000 +0000 @@ -6,7 +6,7 @@ * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -62,7 +62,7 @@ * While clients of a {@link KeyedObjectPool} borrow and return instances of * the underlying value type V, the factory methods act on instances of * {@link PooledObject PooledObject<V>}. These are the object wrappers that - * pools use to track and maintain state informations about the objects that + * pools use to track and maintain state information about the objects that * they manage. *

        * diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/dbcp/pool2/ObjectPool.java tomcat10-10.1.52/java/org/apache/tomcat/dbcp/pool2/ObjectPool.java --- tomcat10-10.1.40/java/org/apache/tomcat/dbcp/pool2/ObjectPool.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/dbcp/pool2/ObjectPool.java 2026-01-23 19:33:36.000000000 +0000 @@ -6,7 +6,7 @@ * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/dbcp/pool2/PoolUtils.java tomcat10-10.1.52/java/org/apache/tomcat/dbcp/pool2/PoolUtils.java --- tomcat10-10.1.40/java/org/apache/tomcat/dbcp/pool2/PoolUtils.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/dbcp/pool2/PoolUtils.java 2026-01-23 19:33:36.000000000 +0000 @@ -6,7 +6,7 @@ * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -23,6 +23,7 @@ import java.util.Map; import java.util.Timer; import java.util.TimerTask; +import java.util.concurrent.locks.ReentrantLock; import java.util.concurrent.locks.ReentrantReadWriteLock; import java.util.concurrent.locks.ReentrantReadWriteLock.ReadLock; import java.util.concurrent.locks.ReentrantReadWriteLock.WriteLock; @@ -46,6 +47,9 @@ * frequently. */ private static final class ErodingFactor { + + private static final float MAX_INTERVAL = 15f; + /** Determines frequency of "erosion" events */ private final float factor; @@ -53,7 +57,9 @@ private transient volatile long nextShrinkMillis; /** High water mark - largest numIdle encountered */ - private transient volatile int idleHighWaterMark; + private transient volatile int idleHighWaterMark = 1; + + private final ReentrantLock lock = new ReentrantLock(); /** * Creates a new ErodingFactor with the given erosion factor. @@ -61,10 +67,9 @@ * @param factor * erosion factor */ - ErodingFactor(final float factor) { + private ErodingFactor(final float factor) { this.factor = factor; - nextShrinkMillis = System.currentTimeMillis() + (long) (900000 * factor); // now + 15 min * factor - idleHighWaterMark = 1; + nextShrinkMillis = System.currentTimeMillis() + (long) (900_000 * factor); // now + 15 min * factor } /** @@ -72,7 +77,7 @@ * * @return next shrink time */ - public long getNextShrink() { + private long getNextShrink() { return nextShrinkMillis; } @@ -81,7 +86,7 @@ */ @Override public String toString() { - return "ErodingFactor{" + "factor=" + factor + + return "ErodingFactor{factor=" + factor + ", idleHighWaterMark=" + idleHighWaterMark + '}'; } @@ -95,11 +100,14 @@ */ public void update(final long nowMillis, final int numIdle) { final int idle = Math.max(0, numIdle); - idleHighWaterMark = Math.max(idle, idleHighWaterMark); - final float maxInterval = 15f; - final float minutes = maxInterval + - (1f - maxInterval) / idleHighWaterMark * idle; - nextShrinkMillis = nowMillis + (long) (minutes * 60000f * factor); + lock.lock(); + try { + idleHighWaterMark = Math.max(idle, idleHighWaterMark); + final float minutes = MAX_INTERVAL + (1f - MAX_INTERVAL) / idleHighWaterMark * idle; + nextShrinkMillis = nowMillis + (long) (minutes * 60000f * factor); + } finally { + lock.unlock(); + } } } /** @@ -129,7 +137,7 @@ * events * @see #erodingFactor */ - protected ErodingKeyedObjectPool(final KeyedObjectPool keyedPool, + private ErodingKeyedObjectPool(final KeyedObjectPool keyedPool, final ErodingFactor erodingFactor) { if (keyedPool == null) { throw new IllegalArgumentException( @@ -150,7 +158,7 @@ * events * @see #erodingFactor */ - ErodingKeyedObjectPool(final KeyedObjectPool keyedPool, + private ErodingKeyedObjectPool(final KeyedObjectPool keyedPool, final float factor) { this(keyedPool, new ErodingFactor(factor)); } @@ -315,7 +323,7 @@ */ @Override public String toString() { - return "ErodingKeyedObjectPool{" + "factor=" + + return "ErodingKeyedObjectPool{factor=" + erodingFactor + ", keyedPool=" + keyedPool + '}'; } } @@ -346,7 +354,7 @@ * events * @see #factor */ - ErodingObjectPool(final ObjectPool pool, final float factor) { + private ErodingObjectPool(final ObjectPool pool, final float factor) { this.pool = pool; this.factor = new ErodingFactor(factor); } @@ -355,7 +363,7 @@ * {@inheritDoc} */ @Override - public void addObject() throws Exception{ + public void addObject() throws Exception { pool.addObject(); } @@ -457,7 +465,7 @@ */ @Override public String toString() { - return "ErodingObjectPool{" + "factor=" + factor + ", pool=" + + return "ErodingObjectPool{factor=" + factor + ", pool=" + pool + '}'; } } @@ -486,7 +494,7 @@ * @param factor * erosion factor */ - ErodingPerKeyKeyedObjectPool(final KeyedObjectPool keyedPool, final float factor) { + private ErodingPerKeyKeyedObjectPool(final KeyedObjectPool keyedPool, final float factor) { super(keyedPool, null); this.factor = factor; } @@ -506,7 +514,7 @@ */ @Override public String toString() { - return "ErodingPerKeyKeyedObjectPool{" + "factor=" + factor + + return "ErodingPerKeyKeyedObjectPool{factor=" + factor + ", keyedPool=" + getKeyedPool() + '}'; } } @@ -1731,7 +1739,7 @@ * @return a synchronized view of the specified KeyedPooledObjectFactory. */ public static KeyedPooledObjectFactory synchronizedKeyedPooledFactory( - final KeyedPooledObjectFactory keyedFactory) { + final KeyedPooledObjectFactory keyedFactory) { return new SynchronizedKeyedPooledObjectFactory<>(keyedFactory); } diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/dbcp/pool2/PooledObject.java tomcat10-10.1.52/java/org/apache/tomcat/dbcp/pool2/PooledObject.java --- tomcat10-10.1.40/java/org/apache/tomcat/dbcp/pool2/PooledObject.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/dbcp/pool2/PooledObject.java 2026-01-23 19:33:36.000000000 +0000 @@ -6,7 +6,7 @@ * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -34,14 +34,37 @@ public interface PooledObject extends Comparable> { /** - * Tests whether the given PooledObject is null or contains a null. + * Gets the wrapped object or null. * - * @param pooledObject the PooledObject to test. - * @return whether the given PooledObject is null or contains a null. + * @param the type of object in the pool. + * @param pooledObject the PooledObject to unwrap, may be null. + * @return the wrapped object or null. + * @since 2.13.0 + */ + static T getObject(final PooledObject pooledObject) { + return pooledObject != null ? pooledObject.getObject() : null; + } + + /** + * Tests whether the given PooledObject is null or wraps a null. + * + * @param pooledObject the PooledObject to test, may be null. + * @return whether the given PooledObject is null or wraps a null. * @since 2.12.0 */ static boolean isNull(final PooledObject pooledObject) { - return pooledObject == null || pooledObject.getObject() == null; + return getObject(pooledObject) == null; + } + + /** + * Tests whether the given PooledObject isn't null and doesn't wraps a null. + * + * @param pooledObject the PooledObject to test, may be null. + * @return whether the given PooledObject isn't null and doesn't wraps a null. + * @since 2.13.0 + */ + static boolean nonNull(final PooledObject pooledObject) { + return getObject(pooledObject) != null; } /** diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/dbcp/pool2/PooledObjectFactory.java tomcat10-10.1.52/java/org/apache/tomcat/dbcp/pool2/PooledObjectFactory.java --- tomcat10-10.1.40/java/org/apache/tomcat/dbcp/pool2/PooledObjectFactory.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/dbcp/pool2/PooledObjectFactory.java 2026-01-23 19:33:36.000000000 +0000 @@ -6,7 +6,7 @@ * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -70,85 +70,85 @@ */ public interface PooledObjectFactory { - /** - * Reinitializes an instance to be returned by the pool. - * - * @param p a {@code PooledObject} wrapping the instance to be activated - * @throws Exception if there is a problem activating {@code obj}, - * this exception may be swallowed by the pool. - * - * @see #destroyObject - */ - void activateObject(PooledObject p) throws Exception; - - /** - * Destroys an instance no longer needed by the pool, using the default (NORMAL) - * DestroyMode. - *

        - * It is important for implementations of this method to be aware that there - * is no guarantee about what state {@code obj} will be in and the - * implementation should be prepared to handle unexpected errors. - *

        - *

        - * Also, an implementation must take in to consideration that instances lost - * to the garbage collector may never be destroyed. - *

        - * - * @param p a {@code PooledObject} wrapping the instance to be destroyed - * @throws Exception should be avoided as it may be swallowed by - * the pool implementation. - * - * @see #validateObject - * @see ObjectPool#invalidateObject - */ - void destroyObject(PooledObject p) throws Exception; - - /** - * Destroys an instance no longer needed by the pool, using the provided - * DestroyMode. - * - * @param p a {@code PooledObject} wrapping the instance to be destroyed - * @param destroyMode DestroyMode providing context to the factory - * @throws Exception should be avoided as it may be swallowed by - * the pool implementation. - * - * @see #validateObject - * @see ObjectPool#invalidateObject - * @see #destroyObject(PooledObject) - * @see DestroyMode - * @since 2.9.0 - */ - default void destroyObject(final PooledObject p, final DestroyMode destroyMode) throws Exception { - destroyObject(p); - } - - /** - * Creates an instance that can be served by the pool and wrap it in a - * {@link PooledObject} to be managed by the pool. - * - * @return a {@code PooledObject} wrapping an instance that can be served by the pool, not null. - * @throws Exception if there is a problem creating a new instance, - * this will be propagated to the code requesting an object. - */ - PooledObject makeObject() throws Exception; - - /** - * Uninitializes an instance to be returned to the idle object pool. - * - * @param p a {@code PooledObject} wrapping the instance to be passivated - * @throws Exception if there is a problem passivating {@code obj}, - * this exception may be swallowed by the pool. - * - * @see #destroyObject - */ - void passivateObject(PooledObject p) throws Exception; - - /** - * Ensures that the instance is safe to be returned by the pool. - * - * @param p a {@code PooledObject} wrapping the instance to be validated - * @return {@code false} if {@code obj} is not valid and should - * be dropped from the pool, {@code true} otherwise. - */ - boolean validateObject(PooledObject p); + /** + * Reinitializes an instance to be returned by the pool. + * + * @param p a {@code PooledObject} wrapping the instance to be activated + * @throws Exception if there is a problem activating {@code obj}, + * this exception may be swallowed by the pool. + * + * @see #destroyObject + */ + void activateObject(PooledObject p) throws Exception; + + /** + * Destroys an instance no longer needed by the pool, using the default (NORMAL) + * DestroyMode. + *

        + * It is important for implementations of this method to be aware that there + * is no guarantee about what state {@code obj} will be in and the + * implementation should be prepared to handle unexpected errors. + *

        + *

        + * Also, an implementation must take in to consideration that instances lost + * to the garbage collector may never be destroyed. + *

        + * + * @param p a {@code PooledObject} wrapping the instance to be destroyed + * @throws Exception should be avoided as it may be swallowed by + * the pool implementation. + * + * @see #validateObject + * @see ObjectPool#invalidateObject + */ + void destroyObject(PooledObject p) throws Exception; + + /** + * Destroys an instance no longer needed by the pool, using the provided + * DestroyMode. + * + * @param p a {@code PooledObject} wrapping the instance to be destroyed + * @param destroyMode DestroyMode providing context to the factory + * @throws Exception should be avoided as it may be swallowed by + * the pool implementation. + * + * @see #validateObject + * @see ObjectPool#invalidateObject + * @see #destroyObject(PooledObject) + * @see DestroyMode + * @since 2.9.0 + */ + default void destroyObject(final PooledObject p, final DestroyMode destroyMode) throws Exception { + destroyObject(p); + } + + /** + * Creates an instance that can be served by the pool and wrap it in a + * {@link PooledObject} to be managed by the pool. + * + * @return a {@code PooledObject} wrapping an instance that can be served by the pool, not null. + * @throws Exception if there is a problem creating a new instance, + * this will be propagated to the code requesting an object. + */ + PooledObject makeObject() throws Exception; + + /** + * Uninitializes an instance to be returned to the idle object pool. + * + * @param p a {@code PooledObject} wrapping the instance to be passivated + * @throws Exception if there is a problem passivating {@code obj}, + * this exception may be swallowed by the pool. + * + * @see #destroyObject + */ + void passivateObject(PooledObject p) throws Exception; + + /** + * Ensures that the instance is safe to be returned by the pool. + * + * @param p a {@code PooledObject} wrapping the instance to be validated + * @return {@code false} if {@code obj} is not valid and should + * be dropped from the pool, {@code true} otherwise. + */ + boolean validateObject(PooledObject p); } diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/dbcp/pool2/PooledObjectState.java tomcat10-10.1.52/java/org/apache/tomcat/dbcp/pool2/PooledObjectState.java --- tomcat10-10.1.40/java/org/apache/tomcat/dbcp/pool2/PooledObjectState.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/dbcp/pool2/PooledObjectState.java 2026-01-23 19:33:36.000000000 +0000 @@ -6,7 +6,7 @@ * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/dbcp/pool2/SwallowedExceptionListener.java tomcat10-10.1.52/java/org/apache/tomcat/dbcp/pool2/SwallowedExceptionListener.java --- tomcat10-10.1.40/java/org/apache/tomcat/dbcp/pool2/SwallowedExceptionListener.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/dbcp/pool2/SwallowedExceptionListener.java 2026-01-23 19:33:36.000000000 +0000 @@ -6,7 +6,7 @@ * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/dbcp/pool2/TrackedUse.java tomcat10-10.1.52/java/org/apache/tomcat/dbcp/pool2/TrackedUse.java --- tomcat10-10.1.40/java/org/apache/tomcat/dbcp/pool2/TrackedUse.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/dbcp/pool2/TrackedUse.java 2026-01-23 19:33:36.000000000 +0000 @@ -6,7 +6,7 @@ * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/dbcp/pool2/UsageTracking.java tomcat10-10.1.52/java/org/apache/tomcat/dbcp/pool2/UsageTracking.java --- tomcat10-10.1.40/java/org/apache/tomcat/dbcp/pool2/UsageTracking.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/dbcp/pool2/UsageTracking.java 2026-01-23 19:33:36.000000000 +0000 @@ -6,7 +6,7 @@ * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/dbcp/pool2/impl/AbandonedConfig.java tomcat10-10.1.52/java/org/apache/tomcat/dbcp/pool2/impl/AbandonedConfig.java --- tomcat10-10.1.40/java/org/apache/tomcat/dbcp/pool2/impl/AbandonedConfig.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/dbcp/pool2/impl/AbandonedConfig.java 2026-01-23 19:33:36.000000000 +0000 @@ -6,7 +6,7 @@ * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/dbcp/pool2/impl/BaseGenericObjectPool.java tomcat10-10.1.52/java/org/apache/tomcat/dbcp/pool2/impl/BaseGenericObjectPool.java --- tomcat10-10.1.40/java/org/apache/tomcat/dbcp/pool2/impl/BaseGenericObjectPool.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/dbcp/pool2/impl/BaseGenericObjectPool.java 2026-01-23 19:33:36.000000000 +0000 @@ -6,7 +6,7 @@ * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -205,41 +205,53 @@ * @param type of objects in the pool */ static class IdentityWrapper { + + /** + * Creates a new instance for the object inside a {@link PooledObject}. + * + * @param The type of the object in the {@link PooledObject}. + * @param p The {@link PooledObject}. + * @return a new instance. + */ + static IdentityWrapper unwrap(final PooledObject p) { + return new IdentityWrapper<>(p.getObject()); + } + /** Wrapped object */ - private final T instance; + private final T object; /** * Constructs a wrapper for an instance. * - * @param instance object to wrap + * @param object object to wrap */ - IdentityWrapper(final T instance) { - this.instance = instance; + IdentityWrapper(final T object) { + this.object = object; } @Override @SuppressWarnings("rawtypes") public boolean equals(final Object other) { - return other instanceof IdentityWrapper && ((IdentityWrapper) other).instance == instance; + return other instanceof IdentityWrapper && ((IdentityWrapper) other).object == object; } /** * @return the wrapped object */ - public T getObject() { - return instance; + T getObject() { + return object; } @Override public int hashCode() { - return System.identityHashCode(instance); + return System.identityHashCode(object); } @Override public String toString() { final StringBuilder builder = new StringBuilder(); builder.append("IdentityWrapper [instance="); - builder.append(instance); + builder.append(object); builder.append("]"); return builder.toString(); } @@ -395,6 +407,7 @@ private volatile SwallowedExceptionListener swallowedExceptionListener; private volatile boolean messageStatistics; + private volatile boolean collectDetailedStatistics = BaseObjectPoolConfig.DEFAULT_COLLECT_DETAILED_STATISTICS; /** Additional configuration properties for abandoned object tracking. */ protected volatile AbandonedConfig abandonedConfig; @@ -483,6 +496,16 @@ } /** + * Returns the duration since the given start time. + * + * @param startInstant the start time + * @return the duration since the given start time + */ + final Duration durationSince(final Instant startInstant) { + return Duration.between(startInstant, Instant.now()); + } + + /** * Tries to ensure that the configured minimum number of idle instances are * available in the pool. * @throws Exception if an error occurs creating idle instances @@ -525,6 +548,20 @@ } /** + * Gets whether detailed timing statistics collection is enabled. + * When {@code false}, the pool will not collect detailed timing statistics for + * mean active time, mean idle time, and mean borrow wait time, + * improving performance under high load. + * + * @return {@code true} if detailed statistics collection is enabled, + * {@code false} if disabled for improved performance. + * @since 2.13.0 + */ + public boolean getCollectDetailedStatistics() { + return collectDetailedStatistics; + } + + /** * Gets the total number of objects created for this pool over the lifetime of * the pool. * @return the created object count @@ -977,7 +1014,6 @@ * removal is configured for this pool; Integer.MAX_VALUE otherwise. * * @see AbandonedConfig#getRemoveAbandonedTimeoutDuration() - * @see AbandonedConfig#getRemoveAbandonedTimeoutDuration() * @deprecated Use {@link #getRemoveAbandonedTimeoutDuration()}. * @since 2.11.0 */ @@ -1226,8 +1262,9 @@ } /** - * Tests whether this pool instance been closed. - * @return {@code true} when this pool has been closed. + * Tests whether this pool instance is closed. + * + * @return {@code true} when this pool is closed. */ public final boolean isClosed() { return closed; @@ -1258,7 +1295,7 @@ } while (!registered) { try { - ObjectName objName; + final ObjectName objName; // Skip the numeric suffix for the first pool in case there is // only one so the names are cleaner. if (i == 1) { @@ -1349,6 +1386,21 @@ } /** + * Sets whether detailed timing statistics collection is enabled. + * When {@code false}, the pool will not collect detailed timing statistics, + * improving performance under high load at the cost of reduced monitoring capabilities. + *

        + * This setting affects data collection for mean active time, mean idle time, and mean borrow wait time. + *

        + * + * @param collectDetailedStatistics whether to collect detailed statistics. + * @since 2.13.0 + */ + public void setCollectDetailedStatistics(final boolean collectDetailedStatistics) { + this.collectDetailedStatistics = collectDetailedStatistics; + } + + /** * Sets the receiver with the given configuration. * * @param config Initialization source. @@ -1374,6 +1426,7 @@ setEvictionPolicy(policy); } setEvictorShutdownTimeout(config.getEvictorShutdownTimeoutDuration()); + setCollectDetailedStatistics(config.getCollectDetailedStatistics()); } /** @@ -1945,6 +1998,7 @@ startEvictor(Duration.ofMillis(-1L)); } + /** * Swallows an exception and notifies the configured listener for swallowed * exceptions queue. @@ -2045,17 +2099,19 @@ */ final void updateStatsBorrow(final PooledObject p, final Duration waitDuration) { borrowedCount.incrementAndGet(); - idleTimes.add(p.getIdleDuration()); - waitTimes.add(waitDuration); - - // lock-free optimistic-locking maximum - Duration currentMaxDuration; - do { - currentMaxDuration = maxBorrowWaitDuration.get(); - if (currentMaxDuration.compareTo(waitDuration) >= 0) { - break; - } - } while (!maxBorrowWaitDuration.compareAndSet(currentMaxDuration, waitDuration)); + // Only collect detailed statistics if enabled + if (collectDetailedStatistics) { + idleTimes.add(p.getIdleDuration()); + waitTimes.add(waitDuration); + // lock-free optimistic-locking maximum + Duration currentMaxDuration; + do { + currentMaxDuration = maxBorrowWaitDuration.get(); + if (currentMaxDuration.compareTo(waitDuration) >= 0) { + break; + } + } while (!maxBorrowWaitDuration.compareAndSet(currentMaxDuration, waitDuration)); + } } /** @@ -2066,7 +2122,25 @@ */ final void updateStatsReturn(final Duration activeTime) { returnedCount.incrementAndGet(); - activeTimes.add(activeTime); + // Only collect detailed statistics if enabled + if (collectDetailedStatistics) { + activeTimes.add(activeTime); + } + } + + /** + * Waits for notification on the given object for the specified duration. + * Duration.ZERO causes the thread to wait indefinitely. + * + * @param obj the object to wait on + * @param duration the duration to wait + * @throws InterruptedException if interrupted while waiting + * @throws IllegalArgumentException if the duration is negative + */ + final void wait(final Object obj, final Duration duration) throws InterruptedException { + if (!duration.isNegative()) { + obj.wait(duration.toMillis(), duration.getNano() % 1_000_000); + } } } diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/dbcp/pool2/impl/BaseObjectPoolConfig.java tomcat10-10.1.52/java/org/apache/tomcat/dbcp/pool2/impl/BaseObjectPoolConfig.java --- tomcat10-10.1.40/java/org/apache/tomcat/dbcp/pool2/impl/BaseObjectPoolConfig.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/dbcp/pool2/impl/BaseObjectPoolConfig.java 2026-01-23 19:33:36.000000000 +0000 @@ -6,7 +6,7 @@ * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -254,6 +254,19 @@ */ public static final String DEFAULT_EVICTION_POLICY_CLASS_NAME = DefaultEvictionPolicy.class.getName(); + /** + * The default value for the {@code collectDetailedStatistics} configuration + * attribute. When {@code true}, the pool will collect detailed timing statistics + * for monitoring purposes. When {@code false}, detailed statistics collection + * is disabled, improving performance under high load. + *

        + * This setting affects data collection for mean active time, mean idle time, and mean borrow wait time. + *

        + * + * @since 2.13.0 + */ + public static final boolean DEFAULT_COLLECT_DETAILED_STATISTICS = true; + private boolean lifo = DEFAULT_LIFO; private boolean fairness = DEFAULT_FAIRNESS; @@ -291,6 +304,15 @@ private String jmxNameBase = DEFAULT_JMX_NAME_BASE; + private boolean collectDetailedStatistics = DEFAULT_COLLECT_DETAILED_STATISTICS; + + /** + * Constructs a new instance. + */ + public BaseObjectPoolConfig() { + // empty + } + /** * Gets the value for the {@code blockWhenExhausted} configuration attribute for pools created with this configuration instance. * @@ -303,6 +325,23 @@ } /** + * Gets the value for the {@code collectDetailedStatistics} configuration attribute + * for pools created with this configuration instance. + *

        + * This setting affects data collection for mean active time, mean idle time, and mean borrow wait time. + *

        + * + * @return {@code true} if detailed statistics collection is enabled, + * {@code false} if disabled for improved performance. + * @see GenericObjectPool#getCollectDetailedStatistics() + * @see GenericKeyedObjectPool#getCollectDetailedStatistics() + * @since 2.13.0 + */ + public boolean getCollectDetailedStatistics() { + return collectDetailedStatistics; + } + + /** * Gets the value for the {@code timeBetweenEvictionRuns} configuration attribute for pools created with this configuration instance. * * @return The current setting of {@code timeBetweenEvictionRuns} for this configuration instance @@ -624,6 +663,25 @@ } /** + * Sets the value for the {@code collectDetailedStatistics} configuration attribute + * for pools created with this configuration instance. When {@code false}, the pool + * will not collect detailed timing statistics, improving performance under high load + * at the cost of reduced monitoring capabilities. + *

        + * This setting affects data collection for mean active time, mean idle time, and mean borrow wait time. + *

        + * + * @param collectDetailedStatistics The new setting of {@code collectDetailedStatistics} + * for this configuration instance. + * @see GenericObjectPool#getCollectDetailedStatistics() + * @see GenericKeyedObjectPool#getCollectDetailedStatistics() + * @since 2.13.0 + */ + public void setCollectDetailedStatistics(final boolean collectDetailedStatistics) { + this.collectDetailedStatistics = collectDetailedStatistics; + } + + /** * Sets the value for the {@code evictionPolicyClass} configuration attribute for pools created with this configuration instance. * * @param evictionPolicy The new setting of {@code evictionPolicyClass} for this configuration instance @@ -953,5 +1011,7 @@ builder.append(jmxNamePrefix); builder.append(", jmxNameBase="); builder.append(jmxNameBase); + builder.append(", collectDetailedStatistics="); + builder.append(collectDetailedStatistics); } } diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/dbcp/pool2/impl/CallStack.java tomcat10-10.1.52/java/org/apache/tomcat/dbcp/pool2/impl/CallStack.java --- tomcat10-10.1.40/java/org/apache/tomcat/dbcp/pool2/impl/CallStack.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/dbcp/pool2/impl/CallStack.java 2026-01-23 19:33:36.000000000 +0000 @@ -6,7 +6,7 @@ * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/dbcp/pool2/impl/DefaultEvictionPolicy.java tomcat10-10.1.52/java/org/apache/tomcat/dbcp/pool2/impl/DefaultEvictionPolicy.java --- tomcat10-10.1.40/java/org/apache/tomcat/dbcp/pool2/impl/DefaultEvictionPolicy.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/dbcp/pool2/impl/DefaultEvictionPolicy.java 2026-01-23 19:33:36.000000000 +0000 @@ -6,7 +6,7 @@ * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -31,7 +31,7 @@ * {@link GenericKeyedObjectPoolConfig#getMinIdlePerKey()} idle objects in * the pool and the object has been idle for longer than * {@link GenericObjectPool#getSoftMinEvictableIdleDuration()} / - * {@link GenericKeyedObjectPool#getSoftMinEvictableIdleDuration()} + * {@link GenericKeyedObjectPool#getSoftMinEvictableIdleDuration()} *
      *

      * This class is immutable and thread-safe. @@ -42,6 +42,13 @@ */ public class DefaultEvictionPolicy implements EvictionPolicy { + /** + * Constructs a new instance. + */ + public DefaultEvictionPolicy() { + // empty + } + @Override public boolean evict(final EvictionConfig config, final PooledObject underTest, final int idleCount) { // @formatter:off diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/dbcp/pool2/impl/DefaultPooledObject.java tomcat10-10.1.52/java/org/apache/tomcat/dbcp/pool2/impl/DefaultPooledObject.java --- tomcat10-10.1.40/java/org/apache/tomcat/dbcp/pool2/impl/DefaultPooledObject.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/dbcp/pool2/impl/DefaultPooledObject.java 2026-01-23 19:33:36.000000000 +0000 @@ -6,7 +6,7 @@ * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/dbcp/pool2/impl/DefaultPooledObjectInfo.java tomcat10-10.1.52/java/org/apache/tomcat/dbcp/pool2/impl/DefaultPooledObjectInfo.java --- tomcat10-10.1.40/java/org/apache/tomcat/dbcp/pool2/impl/DefaultPooledObjectInfo.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/dbcp/pool2/impl/DefaultPooledObjectInfo.java 2026-01-23 19:33:36.000000000 +0000 @@ -6,7 +6,7 @@ * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/dbcp/pool2/impl/DefaultPooledObjectInfoMBean.java tomcat10-10.1.52/java/org/apache/tomcat/dbcp/pool2/impl/DefaultPooledObjectInfoMBean.java --- tomcat10-10.1.40/java/org/apache/tomcat/dbcp/pool2/impl/DefaultPooledObjectInfoMBean.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/dbcp/pool2/impl/DefaultPooledObjectInfoMBean.java 2026-01-23 19:33:36.000000000 +0000 @@ -6,7 +6,7 @@ * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/dbcp/pool2/impl/EvictionConfig.java tomcat10-10.1.52/java/org/apache/tomcat/dbcp/pool2/impl/EvictionConfig.java --- tomcat10-10.1.40/java/org/apache/tomcat/dbcp/pool2/impl/EvictionConfig.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/dbcp/pool2/impl/EvictionConfig.java 2026-01-23 19:33:36.000000000 +0000 @@ -6,7 +6,7 @@ * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/dbcp/pool2/impl/EvictionPolicy.java tomcat10-10.1.52/java/org/apache/tomcat/dbcp/pool2/impl/EvictionPolicy.java --- tomcat10-10.1.40/java/org/apache/tomcat/dbcp/pool2/impl/EvictionPolicy.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/dbcp/pool2/impl/EvictionPolicy.java 2026-01-23 19:33:36.000000000 +0000 @@ -6,7 +6,7 @@ * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -23,7 +23,7 @@ * DefaultEvictionPolicy} for a pool, users must provide an implementation of * this interface that provides the required eviction policy. * - * @param the type of objects in the pool + * @param the type of objects in the pool. * @since 2.0 */ public interface EvictionPolicy { diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/dbcp/pool2/impl/EvictionTimer.java tomcat10-10.1.52/java/org/apache/tomcat/dbcp/pool2/impl/EvictionTimer.java --- tomcat10-10.1.40/java/org/apache/tomcat/dbcp/pool2/impl/EvictionTimer.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/dbcp/pool2/impl/EvictionTimer.java 2026-01-23 19:33:36.000000000 +0000 @@ -6,7 +6,7 @@ * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -21,6 +21,7 @@ import java.security.PrivilegedAction; import java.time.Duration; import java.util.HashMap; +import java.util.Iterator; import java.util.Map.Entry; import java.util.concurrent.ScheduledFuture; import java.util.concurrent.ScheduledThreadPoolExecutor; @@ -32,7 +33,7 @@ *

      * This class is currently implemented using {@link ScheduledThreadPoolExecutor}. This implementation may change in any * future release. This class keeps track of how many pools are using it. If no pools are using the timer, it is - * cancelled. This prevents a thread being left running which, in application server environments, can lead to memory + * canceled. This prevents a thread being left running which, in application server environments, can lead to memory * leads and/or prevent applications from shutting down or reloading cleanly. *

      *

      @@ -73,11 +74,17 @@ @Override public void run() { synchronized (EvictionTimer.class) { - for (final Entry.Evictor>, WeakRunner.Evictor>> entry : TASK_MAP - .entrySet()) { + /* + * Need to use iterator over TASK_MAP so entries can be removed when iterating without triggering a + * ConcurrentModificationException. + */ + final Iterator.Evictor>, WeakRunner.Evictor>>> iterator = + TASK_MAP.entrySet().iterator(); + while (iterator.hasNext()) { + final Entry.Evictor>, WeakRunner.Evictor>> entry = iterator.next(); if (entry.getKey().get() == null) { executor.remove(entry.getValue()); - TASK_MAP.remove(entry.getKey()); + iterator.remove(); } } if (TASK_MAP.isEmpty() && executor != null) { @@ -104,7 +111,7 @@ * @param ref the reference to track. */ private WeakRunner(final WeakReference ref) { - this.ref = ref; + this.ref = ref; } @Override @@ -113,8 +120,10 @@ if (task != null) { task.run(); } else { - executor.remove(this); - TASK_MAP.remove(ref); + synchronized (EvictionTimer.class) { + executor.remove(this); + TASK_MAP.remove(ref); + } } } } @@ -124,13 +133,13 @@ /** Keys are weak references to tasks, values are runners managed by executor. */ private static final HashMap< - WeakReference.Evictor>, - WeakRunner.Evictor>> TASK_MAP = new HashMap<>(); // @GuardedBy("EvictionTimer.class") + WeakReference.Evictor>, + WeakRunner.Evictor>> TASK_MAP = new HashMap<>(); // @GuardedBy("EvictionTimer.class") /** * Removes the specified eviction task from the timer. * - * @param evictor Task to be cancelled. + * @param evictor Task to be canceled. * @param timeout If the associated executor is no longer required, how * long should this thread wait for the executor to * terminate? @@ -195,8 +204,8 @@ * server environments. * * @param task Task to be scheduled. - * @param delay Delay in milliseconds before task is executed. - * @param period Time in milliseconds between executions. + * @param delay Duration before task is executed. + * @param period Duration between executions. */ static synchronized void schedule( final BaseGenericObjectPool.Evictor task, final Duration delay, final Duration period) { diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/dbcp/pool2/impl/GenericKeyedObjectPool.java tomcat10-10.1.52/java/org/apache/tomcat/dbcp/pool2/impl/GenericKeyedObjectPool.java --- tomcat10-10.1.40/java/org/apache/tomcat/dbcp/pool2/impl/GenericKeyedObjectPool.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/dbcp/pool2/impl/GenericKeyedObjectPool.java 2026-01-23 19:33:36.000000000 +0000 @@ -6,7 +6,7 @@ * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -28,8 +28,8 @@ import java.util.NoSuchElementException; import java.util.Objects; import java.util.TreeMap; +import java.util.concurrent.BlockingDeque; import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicLong; @@ -128,16 +128,16 @@ * @param fairness true means client threads waiting to borrow / return instances * will be served as if waiting in a FIFO queue. */ - ObjectDeque(final boolean fairness) { + private ObjectDeque(final boolean fairness) { idleObjects = new LinkedBlockingDeque<>(fairness); } /** * Gets all the objects for the current key. * - * @return All the objects + * @return All the objects, */ - public Map, PooledObject> getAllObjects() { + Map, PooledObject> getAllObjects() { return allObjects; } @@ -145,27 +145,27 @@ * Gets the number of instances created - number destroyed. * Should always be less than or equal to maxTotalPerKey. * - * @return The net instance addition count for this deque + * @return The net instance addition count for this deque. */ - public AtomicInteger getCreateCount() { + AtomicInteger getCreateCount() { return createCount; } /** * Gets the idle objects for the current key. * - * @return The idle objects + * @return The idle objects. */ - public LinkedBlockingDeque> getIdleObjects() { + LinkedBlockingDeque> getIdleObjects() { return idleObjects; } /** * Gets the number of threads with an interest registered in this key. * - * @return The number of threads with a registered interest in this key + * @return The number of threads with a registered interest in this key. */ - public AtomicLong getNumInterested() { + AtomicLong getNumInterested() { return numInterested; } @@ -201,6 +201,12 @@ private volatile int maxTotalPerKey = GenericKeyedObjectPoolConfig.DEFAULT_MAX_TOTAL_PER_KEY; + private volatile boolean reuseCapacityOnReturn = + GenericKeyedObjectPoolConfig.DEFAULT_REUSE_CAPACITY_ON_RETURN; + + private volatile boolean reuseCapacityOnMaintenance = + GenericKeyedObjectPoolConfig.DEFAULT_REUSE_CAPACITY_ON_MAINTENANCE; + private final KeyedPooledObjectFactory factory; private final boolean fairness; @@ -209,8 +215,13 @@ * My hash of sub-pools (ObjectQueue). The list of keys must be kept * in step with {@link #poolKeyList} using {@link #keyLock} to ensure any * changes to the list of current keys is made in a thread-safe manner. + * + * Correct operation of the pool requires that a Map implementation is used that + * supports concurrent read and write (e.g. ensureMinIdle() iterates over the key set + * while other threads may be adding or removing keys) therefore explicitly define + * this field as ConcurrentHashMap rather than Map. */ - private final Map> poolMap = + private final ConcurrentHashMap> poolMap = new ConcurrentHashMap<>(); // @GuardedBy("keyLock") for write access (and some read access) /* @@ -298,9 +309,9 @@ * @throws Exception If the associated factory fails to passivate the object */ private void addIdleObject(final K key, final PooledObject p) throws Exception { - if (!PooledObject.isNull(p)) { + if (PooledObject.nonNull(p)) { factory.passivateObject(key, p); - final LinkedBlockingDeque> idleObjects = poolMap.get(key).getIdleObjects(); + final BlockingDeque> idleObjects = poolMap.get(key).getIdleObjects(); if (getLifo()) { idleObjects.addFirst(p); } else { @@ -330,9 +341,18 @@ @Override public void addObject(final K key) throws Exception { assertOpen(); - register(key); + final ObjectDeque objectDeque = register(key); try { - addIdleObject(key, create(key)); + // Attempt create and add only if there is capacity to add + // > to the overall instance count + // > to the pool under the key + final int maxtTotalPerKey = getMaxTotalPerKey(); + final int maxTotal = getMaxTotal(); + if ((maxTotal < 0 || getNumActive() + getNumIdle() < maxTotal) + && (maxtTotalPerKey < 0 || objectDeque.allObjects.size() < maxtTotalPerKey)) { + // Attempt to create and add a new instance under key + addIdleObject(key, create(key, getMaxWaitDuration())); + } } finally { deregister(key); } @@ -400,8 +420,8 @@ *

      * * @param key pool key - * @param borrowMaxWaitMillis The time to wait in milliseconds for an object - * to become available + * @param maxWaitDuration The time to wait for an object to become + * available * * @return object instance from the keyed pool * @throws NoSuchElementException if a keyed object instance cannot be @@ -409,10 +429,12 @@ * * @throws Exception if a keyed object instance cannot be returned due to an * error + * @since 2.12.2 */ - public T borrowObject(final K key, final long borrowMaxWaitMillis) throws Exception { + public T borrowObject(final K key, final Duration maxWaitDuration) throws Exception { assertOpen(); - + final Instant startInstant = Instant.now(); + Duration remainingWaitDuration = maxWaitDuration; final AbandonedConfig ac = this.abandonedConfig; if (ac != null && ac.getRemoveAbandonedOnBorrow() && getNumIdle() < 2 && getNumActive() > getMaxTotal() - 3) { @@ -426,27 +448,28 @@ final boolean blockWhenExhausted = getBlockWhenExhausted(); boolean create; - final Instant waitTime = Instant.now(); final ObjectDeque objectDeque = register(key); try { while (p == null) { + remainingWaitDuration = maxWaitDuration.minus(durationSince(startInstant)); create = false; p = objectDeque.getIdleObjects().pollFirst(); if (p == null) { - p = create(key); - if (!PooledObject.isNull(p)) { + p = create(key, remainingWaitDuration); + if (PooledObject.nonNull(p)) { create = true; } + remainingWaitDuration = maxWaitDuration.minus(durationSince(startInstant)); } if (blockWhenExhausted) { if (PooledObject.isNull(p)) { - p = borrowMaxWaitMillis < 0 ? objectDeque.getIdleObjects().takeFirst(): - objectDeque.getIdleObjects().pollFirst(borrowMaxWaitMillis, TimeUnit.MILLISECONDS); + p = maxWaitDuration.isNegative() ? objectDeque.getIdleObjects().takeFirst() + : objectDeque.getIdleObjects().pollFirst(remainingWaitDuration); } if (PooledObject.isNull(p)) { throw new NoSuchElementException(appendStats( - "Timeout waiting for idle object, borrowMaxWaitMillis=" + borrowMaxWaitMillis)); + "Timeout waiting for idle object, borrowMaxWaitMillis=" + maxWaitDuration.toMillis())); } } else if (PooledObject.isNull(p)) { throw new NoSuchElementException(appendStats("Pool exhausted")); @@ -455,7 +478,7 @@ p = null; } - if (!PooledObject.isNull(p)) { + if (PooledObject.nonNull(p)) { try { factory.activateObject(key, p); } catch (final Exception e) { @@ -466,12 +489,13 @@ } p = null; if (create) { - final NoSuchElementException nsee = new NoSuchElementException(appendStats("Unable to activate object")); + final NoSuchElementException nsee = new NoSuchElementException( + appendStats("Unable to activate object")); nsee.initCause(e); throw nsee; } } - if (!PooledObject.isNull(p) && getTestOnBorrow()) { + if (PooledObject.nonNull(p) && getTestOnBorrow()) { boolean validate = false; Throwable validationThrowable = null; try { @@ -502,11 +526,78 @@ deregister(key); } - updateStatsBorrow(p, Duration.between(waitTime, Instant.now())); + updateStatsBorrow(p, Duration.between(startInstant, Instant.now())); return p.getObject(); } + + /** + * Borrows an object from the sub-pool associated with the given key using + * the specified waiting time which only applies if + * {@link #getBlockWhenExhausted()} is true. + *

      + * If there is one or more idle instances available in the sub-pool + * associated with the given key, then an idle instance will be selected + * based on the value of {@link #getLifo()}, activated and returned. If + * activation fails, or {@link #getTestOnBorrow() testOnBorrow} is set to + * {@code true} and validation fails, the instance is destroyed and the + * next available instance is examined. This continues until either a valid + * instance is returned or there are no more idle instances available. + *

      + *

      + * If there are no idle instances available in the sub-pool associated with + * the given key, behavior depends on the {@link #getMaxTotalPerKey() + * maxTotalPerKey}, {@link #getMaxTotal() maxTotal}, and (if applicable) + * {@link #getBlockWhenExhausted()} and the value passed in to the + * {@code borrowMaxWaitMillis} parameter. If the number of instances checked + * out from the sub-pool under the given key is less than + * {@code maxTotalPerKey} and the total number of instances in + * circulation (under all keys) is less than {@code maxTotal}, a new + * instance is created, activated and (if applicable) validated and returned + * to the caller. If validation fails, a {@code NoSuchElementException} + * will be thrown. If the factory returns null when creating an instance, + * a {@code NullPointerException} is thrown. + *

      + *

      + * If the associated sub-pool is exhausted (no available idle instances and + * no capacity to create new ones), this method will either block + * ({@link #getBlockWhenExhausted()} is true) or throw a + * {@code NoSuchElementException} + * ({@link #getBlockWhenExhausted()} is false). + * The length of time that this method will block when + * {@link #getBlockWhenExhausted()} is true is determined by the value + * passed in to the {@code borrowMaxWait} parameter. + *

      + *

      + * When {@code maxTotal} is set to a positive value and this method is + * invoked when at the limit with no idle instances available under the requested + * key, an attempt is made to create room by clearing the oldest 15% of the + * elements from the keyed sub-pools. + *

      + *

      + * When the pool is exhausted, multiple calling threads may be + * simultaneously blocked waiting for instances to become available. A + * "fairness" algorithm has been implemented to ensure that threads receive + * available instances in request arrival order. + *

      + * + * @param key pool key + * @param maxWaitMillis The time to wait in milliseconds for an object to become + * available + * + * @return object instance from the keyed pool + * @throws NoSuchElementException if a keyed object instance cannot be + * returned because the pool is exhausted. + * + * @throws Exception if a keyed object instance cannot be returned due to an + * error + */ + + public T borrowObject(final K key, final long maxWaitMillis) throws Exception { + return borrowObject(key, Duration.ofMillis(maxWaitMillis)); + } + /** * Calculate the number of objects that need to be created to attempt to * maintain the minimum number of idle objects while not exceeded the limits @@ -607,7 +698,7 @@ final ObjectDeque objectDeque = register(key); int freedCapacity = 0; try { - final LinkedBlockingDeque> idleObjects = objectDeque.getIdleObjects(); + final BlockingDeque> idleObjects = objectDeque.getIdleObjects(); PooledObject p = idleObjects.poll(); while (p != null) { try { @@ -698,7 +789,7 @@ jmxUnregister(); // Release any threads that were waiting for an object - poolMap.values().forEach(e -> e.getIdleObjects().interuptTakeWaiters()); + poolMap.values().forEach(e -> e.getIdleObjects().interruptTakeWaiters()); // This clear cleans up the keys now any waiting threads have been // interrupted clear(); @@ -708,11 +799,16 @@ /** * Creates a new pooled object or null. * - * @param key Key associated with new pooled object. + * @param key Key associated with new pooled object. + * @param maxWaitDuration The time to wait in this method. If negative or ZERO, + * this method may wait indefinitely. * @return The new, wrapped pooled object. May return null. * @throws Exception If the objection creation fails. */ - private PooledObject create(final K key) throws Exception { + private PooledObject create(final K key, final Duration maxWaitDuration) throws Exception { + final Instant startInstant = Instant.now(); + Duration remainingWaitDuration = maxWaitDuration.isNegative() ? Duration.ZERO : maxWaitDuration; + int maxTotalPerKeySave = getMaxTotalPerKey(); // Per key if (maxTotalPerKeySave < 0) { maxTotalPerKeySave = Integer.MAX_VALUE; @@ -744,6 +840,7 @@ // call the factory Boolean create = null; while (create == null) { + remainingWaitDuration = maxWaitDuration.isNegative() ? Duration.ZERO : maxWaitDuration.minus(durationSince(startInstant)); synchronized (objectDeque.makeObjectCountLock) { final long newCreateCount = objectDeque.getCreateCount().incrementAndGet(); // Check against the per key limit @@ -757,12 +854,13 @@ // create a new object. Return and wait for an object to // be returned. create = Boolean.FALSE; - } else { + } else if (!remainingWaitDuration.isNegative()) { // There are makeObject() calls in progress that might // bring the pool to capacity. Those calls might also // fail so wait until they complete and then re-test if // the pool is at capacity or not. - objectDeque.makeObjectCountLock.wait(); + objectDeque.makeObjectCountLock.wait(remainingWaitDuration.toMillis(), + remainingWaitDuration.getNano() % 1_000_000); } } else { // The pool is not at capacity. Create a new object. @@ -808,7 +906,7 @@ } createdCount.incrementAndGet(); - objectDeque.getAllObjects().put(new IdentityWrapper<>(p.getObject()), p); + objectDeque.getAllObjects().put(IdentityWrapper.unwrap(p), p); return p; } @@ -857,13 +955,13 @@ /** * Destroy the wrapped, pooled object. * - * @param key The key associated with the object to destroy. + * @param key The key associated with the object to destroy * @param toDestroy The wrapped object to be destroyed * @param always Should the object be destroyed even if it is not currently * in the set of idle objects for the given key - * @param destroyMode DestroyMode context provided to the factory + * @param destroyMode {@link DestroyMode} context provided to the factory * @return {@code true} if the object was destroyed, otherwise {@code false} - * @throws Exception If the object destruction failed + * @throws Exception If the factory throws an exception during destruction */ private boolean destroy(final K key, final PooledObject toDestroy, final boolean always, final DestroyMode destroyMode) throws Exception { @@ -881,7 +979,7 @@ } } if (isIdle || always) { - objectDeque.getAllObjects().remove(new IdentityWrapper<>(toDestroy.getObject())); + objectDeque.getAllObjects().remove(IdentityWrapper.unwrap(toDestroy)); toDestroy.invalidate(); try { @@ -1086,8 +1184,6 @@ } } underTest.endEvictionTest(idleObjects); - // TODO - May need to add code here once additional - // states are used } } } @@ -1096,6 +1192,9 @@ if (ac != null && ac.getRemoveAbandonedOnMaintenance()) { removeAbandoned(ac); } + if (reuseCapacityOnMaintenance) { + reuseCapacity(); + } } /** @@ -1258,6 +1357,32 @@ return result; } + /** + * Gets whether to call {@link #reuseCapacity()} during pool maintenance (eviction). + * When true, the pool will attempt to reuse freed capacity at the end of each + * eviction run. + * + * @return {@code true} if capacity reuse is enabled during maintenance, {@code false} otherwise + * @see #setReuseCapacityOnMaintenance(boolean) + * @since 2.13.0 + */ + public boolean getReuseCapacityOnMaintenance() { + return reuseCapacityOnMaintenance; + } + + /** + * Gets whether to call {@link #reuseCapacity()} when returning objects to the pool. + * When true, the pool will check if there are threads waiting to borrow objects + * and attempt to reuse the capacity freed by the return operation. + * + * @return {@code true} if capacity reuse is enabled on return, {@code false} otherwise + * @see #setReuseCapacityOnReturn(boolean) + * @since 2.13.0 + */ + public boolean getReuseCapacityOnReturn() { + return reuseCapacityOnReturn; + } + @SuppressWarnings("boxing") // Commons Pool uses auto-boxing @Override String getStatsString() { @@ -1333,7 +1458,7 @@ * to be borrowed) and active (currently borrowed). *

      * Note: This is named listAllObjects so it is presented as an operation via - * JMX. That means it won't be invoked unless the explicitly requested + * JMX. That means it won't be invoked unless explicitly requested * whereas all attributes will be automatically requested when viewing the * attributes for an object in a tool like JConsole. *

      @@ -1505,7 +1630,7 @@ } final int maxIdle = getMaxIdlePerKey(); - final LinkedBlockingDeque> idleObjects = objectDeque.getIdleObjects(); + final BlockingDeque> idleObjects = objectDeque.getIdleObjects(); if (isClosed() || maxIdle > -1 && maxIdle <= idleObjects.size()) { try { @@ -1527,7 +1652,7 @@ } } } finally { - if (hasBorrowWaiters()) { + if (reuseCapacityOnReturn && hasBorrowWaiters()) { reuseCapacity(); } updateStatsReturn(activeTime); @@ -1550,7 +1675,7 @@ private void reuseCapacity() { final int maxTotalPerKeySave = getMaxTotalPerKey(); int maxQueueLength = 0; - LinkedBlockingDeque> mostLoadedPool = null; + BlockingDeque> mostLoadedPool = null; K mostLoadedKey = null; // Find the most loaded pool that could take a new instance @@ -1571,7 +1696,7 @@ try { // If there is no capacity to add, create will return null // and addIdleObject will no-op. - addIdleObject(mostLoadedKey, create(mostLoadedKey)); + addIdleObject(mostLoadedKey, create(mostLoadedKey, Duration.ZERO)); } catch (final Exception e) { swallowException(e); } finally { @@ -1585,7 +1710,7 @@ *

      * Always activates {@link #reuseCapacity()} at least once. * - * @param newCapacity number of new instances to attempt to create. + * @param newCapacity number of times to call {@link #reuseCapacity()} */ private void reuseCapacity(final int newCapacity) { final int bound = newCapacity < 1 ? 1 : newCapacity; @@ -1606,6 +1731,8 @@ setMaxTotalPerKey(conf.getMaxTotalPerKey()); setMaxTotal(conf.getMaxTotal()); setMinIdlePerKey(conf.getMinIdlePerKey()); + setReuseCapacityOnReturn(conf.getReuseCapacityOnReturn()); + setReuseCapacityOnMaintenance(conf.getReuseCapacityOnMaintenance()); } /** @@ -1662,6 +1789,34 @@ this.minIdlePerKey = minIdlePerKey; } + /** + * Sets whether to call {@link #reuseCapacity()} during pool maintenance (eviction). + * When enabled, the pool will attempt to reuse capacity at the end of each + * eviction run. + * + * @param reuseCapacityOnMaintenance {@code true} to enable capacity reuse during + * maintenance, {@code false} to disable + * @see #getReuseCapacityOnMaintenance() + * @since 2.13.0 + */ + public void setReuseCapacityOnMaintenance(final boolean reuseCapacityOnMaintenance) { + this.reuseCapacityOnMaintenance = reuseCapacityOnMaintenance; + } + + /** + * Sets whether to call {@link #reuseCapacity()} when returning objects to the pool. + * When enabled, the pool will check if there are threads waiting to borrow objects + * and attempt to reuse capacity (across pools) on return. + * + * @param reuseCapacityOnReturn {@code true} to enable capacity reuse on return, + * {@code false} to disable + * @see #getReuseCapacityOnReturn() + * @since 2.13.0 + */ + public void setReuseCapacityOnReturn(final boolean reuseCapacityOnReturn) { + this.reuseCapacityOnReturn = reuseCapacityOnReturn; + } + @Override protected void toStringAppendFields(final StringBuilder builder) { super.toStringAppendFields(builder); @@ -1689,6 +1844,10 @@ builder.append(evictionKey); builder.append(", abandonedConfig="); builder.append(abandonedConfig); + builder.append(", reuseCapacityOnReturn="); + builder.append(reuseCapacityOnReturn); + builder.append(", reuseCapacityOnMaintenance="); + builder.append(reuseCapacityOnMaintenance); } /** diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/dbcp/pool2/impl/GenericKeyedObjectPoolConfig.java tomcat10-10.1.52/java/org/apache/tomcat/dbcp/pool2/impl/GenericKeyedObjectPoolConfig.java --- tomcat10-10.1.40/java/org/apache/tomcat/dbcp/pool2/impl/GenericKeyedObjectPoolConfig.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/dbcp/pool2/impl/GenericKeyedObjectPoolConfig.java 2026-01-23 19:33:36.000000000 +0000 @@ -6,7 +6,7 @@ * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -58,6 +58,22 @@ */ public static final int DEFAULT_MAX_IDLE_PER_KEY = 8; + /** + * The default value for the {@code reuseCapacityOnReturn} configuration attribute: {@value}. + * + * @see GenericKeyedObjectPool#getReuseCapacityOnReturn() + * @since 2.13.0 + */ + public static final boolean DEFAULT_REUSE_CAPACITY_ON_RETURN = true; + + /** + * The default value for the {@code reuseCapacityOnMaintenance} configuration attribute: {@value}. + * + * @see GenericKeyedObjectPool#getReuseCapacityOnMaintenance() + * @since 2.13.0 + */ + public static final boolean DEFAULT_REUSE_CAPACITY_ON_MAINTENANCE = false; + private int minIdlePerKey = DEFAULT_MIN_IDLE_PER_KEY; private int maxIdlePerKey = DEFAULT_MAX_IDLE_PER_KEY; @@ -66,6 +82,10 @@ private int maxTotal = DEFAULT_MAX_TOTAL; + private boolean reuseCapacityOnReturn = DEFAULT_REUSE_CAPACITY_ON_RETURN; + + private boolean reuseCapacityOnMaintenance = DEFAULT_REUSE_CAPACITY_ON_MAINTENANCE; + /** * Constructs a new configuration with default settings. */ @@ -135,6 +155,34 @@ } /** + * Gets the value for the {@code reuseCapacityOnMaintenance} configuration attribute + * for pools created with this configuration instance. + * + * @return The current setting of {@code reuseCapacityOnMaintenance} for this + * configuration instance + * + * @see GenericKeyedObjectPool#getReuseCapacityOnMaintenance() + * @since 2.13.0 + */ + public boolean getReuseCapacityOnMaintenance() { + return reuseCapacityOnMaintenance; + } + + /** + * Gets the value for the {@code reuseCapacityOnReturn} configuration attribute + * for pools created with this configuration instance. + * + * @return The current setting of {@code reuseCapacityOnReturn} for this + * configuration instance + * + * @see GenericKeyedObjectPool#getReuseCapacityOnReturn() + * @since 2.13.0 + */ + public boolean getReuseCapacityOnReturn() { + return reuseCapacityOnReturn; + } + + /** * Sets the value for the {@code maxIdlePerKey} configuration attribute for * pools created with this configuration instance. * @@ -186,6 +234,34 @@ this.minIdlePerKey = minIdlePerKey; } + /** + * Sets the value for the {@code reuseCapacityOnMaintenance} configuration attribute for + * pools created with this configuration instance. + * + * @param reuseCapacityOnMaintenance The new setting of {@code reuseCapacityOnMaintenance} + * for this configuration instance + * + * @see GenericKeyedObjectPool#setReuseCapacityOnMaintenance(boolean) + * @since 2.13.0 + */ + public void setReuseCapacityOnMaintenance(final boolean reuseCapacityOnMaintenance) { + this.reuseCapacityOnMaintenance = reuseCapacityOnMaintenance; + } + + /** + * Sets the value for the {@code reuseCapacityOnReturn} configuration attribute for + * pools created with this configuration instance. + * + * @param reuseCapacityOnReturn The new setting of {@code reuseCapacityOnReturn} + * for this configuration instance + * + * @see GenericKeyedObjectPool#setReuseCapacityOnReturn(boolean) + * @since 2.13.0 + */ + public void setReuseCapacityOnReturn(final boolean reuseCapacityOnReturn) { + this.reuseCapacityOnReturn = reuseCapacityOnReturn; + } + @Override protected void toStringAppendFields(final StringBuilder builder) { super.toStringAppendFields(builder); @@ -197,5 +273,9 @@ builder.append(maxTotalPerKey); builder.append(", maxTotal="); builder.append(maxTotal); + builder.append(", reuseCapacityOnReturn="); + builder.append(reuseCapacityOnReturn); + builder.append(", reuseCapacityOnMaintenance="); + builder.append(reuseCapacityOnMaintenance); } } diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/dbcp/pool2/impl/GenericKeyedObjectPoolMXBean.java tomcat10-10.1.52/java/org/apache/tomcat/dbcp/pool2/impl/GenericKeyedObjectPoolMXBean.java --- tomcat10-10.1.40/java/org/apache/tomcat/dbcp/pool2/impl/GenericKeyedObjectPoolMXBean.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/dbcp/pool2/impl/GenericKeyedObjectPoolMXBean.java 2026-01-23 19:33:36.000000000 +0000 @@ -6,7 +6,7 @@ * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/dbcp/pool2/impl/GenericObjectPool.java tomcat10-10.1.52/java/org/apache/tomcat/dbcp/pool2/impl/GenericObjectPool.java --- tomcat10-10.1.40/java/org/apache/tomcat/dbcp/pool2/impl/GenericObjectPool.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/dbcp/pool2/impl/GenericObjectPool.java 2026-01-23 19:33:36.000000000 +0000 @@ -6,7 +6,7 @@ * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -82,13 +82,7 @@ // JMX specific attributes private static final String ONAME_BASE = - "org.apache.commons.pool2:type=GenericObjectPool,name="; - - private static void wait(final Object obj, final Duration duration) throws InterruptedException { - if (!duration.isNegative()) { - obj.wait(duration.toMillis(), duration.getNano() % 1_000_000); - } - } + "org.apache.commons.pool2:type=GenericObjectPool,name="; private volatile String factoryType; @@ -102,17 +96,17 @@ * All of the objects currently associated with this pool in any state. It * excludes objects that have been destroyed. The size of * {@link #allObjects} will always be less than or equal to {@link - * #_maxActive}. Map keys are pooled objects, values are the PooledObject + * #getMaxTotal()}. Map keys are pooled objects, values are the PooledObject * wrappers used internally by the pool. */ private final ConcurrentHashMap, PooledObject> allObjects = new ConcurrentHashMap<>(); /* * The combined count of the currently created objects and those in the - * process of being created. Under load, it may exceed {@link #_maxActive} + * process of being created. Under load, it may exceed {@link #getMaxTotal()} * if multiple threads try and create a new object at the same time but * {@link #create()} will ensure that there are never more than - * {@link #_maxActive} objects created at any one time. + * {@link #getMaxTotal()} objects created at any one time. */ private final AtomicLong createCount = new AtomicLong(); @@ -188,7 +182,7 @@ * @throws Exception If the factory fails to passivate the object */ private void addIdleObject(final PooledObject p) throws Exception { - if (!PooledObject.isNull(p)) { + if (PooledObject.nonNull(p)) { factory.passivateObject(p); if (getLifo()) { idleObjects.addFirst(p); @@ -199,10 +193,11 @@ } /** - * Creates an object, and place it into the pool. addObject() is useful for + * Creates an object, and places it into the pool. addObject() is useful for * "pre-loading" a pool with idle objects. *

      - * If there is no capacity available to add to the pool, this is a no-op + * If there is no capacity available to add to the pool, or there are already + * {@link #getMaxIdle()} idle instances in the pool, this is a no-op * (no exception, no impact to the pool). *

      *

      @@ -217,11 +212,16 @@ if (factory == null) { throw new IllegalStateException("Cannot add objects without a factory."); } - addIdleObject(create(getMaxWaitDuration())); + final int localMaxIdle = getMaxIdle(); + final int localMaxTotal = getMaxTotal(); + if ((localMaxIdle < 0 || getNumIdle() < localMaxIdle) && + (localMaxTotal < 0 || createCount.get() < localMaxTotal)) { + addIdleObject(create(getMaxWaitDuration())); + } } /** - * Equivalent to {@link #borrowObject(long) + * Equivalent to {@link #borrowObject(Duration) * borrowObject}({@link #getMaxWaitDuration()}). * * {@inheritDoc} @@ -246,8 +246,8 @@ *

      * If there are no idle instances available in the pool, behavior depends on * the {@link #getMaxTotal() maxTotal}, (if applicable) - * {@link #getBlockWhenExhausted()} and the value passed in to the - * {@code borrowMaxWaitMillis} parameter. If the number of instances + * {@link #getBlockWhenExhausted()} and the value passed in the + * {@code maxWaitDuration} parameter. If the number of instances * checked out from the pool is less than {@code maxTotal,} a new * instance is created, activated and (if applicable) validated and returned * to the caller. If validation fails, a {@code NoSuchElementException} @@ -261,8 +261,9 @@ * {@code NoSuchElementException} (if * {@link #getBlockWhenExhausted()} is false). The length of time that this * method will block when {@link #getBlockWhenExhausted()} is true is - * determined by the value passed in to the {@code borrowMaxWaitMillis} - * parameter. + * determined by the value passed in to the {@code maxWaitDuration} + * parameter. Passing a negative duration will cause this method to block + * indefinitely until an object becomes available. *

      *

      * When the pool is exhausted, multiple calling threads may be @@ -271,17 +272,17 @@ * available instances in request arrival order. *

      * - * @param borrowMaxWaitDuration The time to wait for an object to become available, not null. + * @param maxWaitDuration The time to wait for an object to become available, not null. * @return object instance from the pool * @throws NoSuchElementException if an instance cannot be returned * @throws Exception if an object instance cannot be returned due to an error * @since 2.10.0 */ - public T borrowObject(final Duration borrowMaxWaitDuration) throws Exception { + public T borrowObject(final Duration maxWaitDuration) throws Exception { assertOpen(); final Instant startInstant = Instant.now(); - final boolean negativeDuration = borrowMaxWaitDuration.isNegative(); - Duration remainingWaitDuration = borrowMaxWaitDuration; + final boolean negativeDuration = maxWaitDuration.isNegative(); + Duration remainingWaitDuration = maxWaitDuration; final AbandonedConfig ac = this.abandonedConfig; if (ac != null && ac.getRemoveAbandonedOnBorrow() && getNumIdle() < 2 && getNumActive() > getMaxTotal() - 3) { removeAbandoned(ac); @@ -292,22 +293,22 @@ final boolean blockWhenExhausted = getBlockWhenExhausted(); boolean create; while (p == null) { - remainingWaitDuration = remainingWaitDuration.minus(durationSince(startInstant)); + remainingWaitDuration = maxWaitDuration.minus(durationSince(startInstant)); create = false; p = idleObjects.pollFirst(); if (p == null) { p = create(remainingWaitDuration); - if (!PooledObject.isNull(p)) { + if (PooledObject.nonNull(p)) { create = true; } } if (blockWhenExhausted) { if (PooledObject.isNull(p)) { + remainingWaitDuration = maxWaitDuration.minus(durationSince(startInstant)); p = negativeDuration ? idleObjects.takeFirst() : idleObjects.pollFirst(remainingWaitDuration); } if (PooledObject.isNull(p)) { - throw new NoSuchElementException(appendStats( - "Timeout waiting for idle object, borrowMaxWaitDuration=" + remainingWaitDuration)); + throw new NoSuchElementException(appendStats("Timeout waiting for idle object, maxWaitDuration=" + remainingWaitDuration)); } } else if (PooledObject.isNull(p)) { throw new NoSuchElementException(appendStats("Pool exhausted")); @@ -326,8 +327,7 @@ } p = null; if (create) { - final NoSuchElementException nsee = new NoSuchElementException( - appendStats("Unable to activate object")); + final NoSuchElementException nsee = new NoSuchElementException(appendStats("Unable to activate object")); nsee.initCause(e); throw nsee; } @@ -350,8 +350,7 @@ } p = null; if (create) { - final NoSuchElementException nsee = new NoSuchElementException( - appendStats("Unable to validate object")); + final NoSuchElementException nsee = new NoSuchElementException(appendStats("Unable to validate object")); nsee.initCause(validationThrowable); throw nsee; } @@ -363,10 +362,6 @@ return p.getObject(); } - private Duration durationSince(final Instant startInstant) { - return Duration.between(startInstant, Instant.now()); - } - /** * Borrows an object from the pool using the specific waiting time which only * applies if {@link #getBlockWhenExhausted()} is true. @@ -383,7 +378,7 @@ * If there are no idle instances available in the pool, behavior depends on * the {@link #getMaxTotal() maxTotal}, (if applicable) * {@link #getBlockWhenExhausted()} and the value passed in to the - * {@code borrowMaxWaitMillis} parameter. If the number of instances + * {@code maxWaitMillis} parameter. If the number of instances * checked out from the pool is less than {@code maxTotal,} a new * instance is created, activated and (if applicable) validated and returned * to the caller. If validation fails, a {@code NoSuchElementException} @@ -397,8 +392,9 @@ * {@code NoSuchElementException} (if * {@link #getBlockWhenExhausted()} is false). The length of time that this * method will block when {@link #getBlockWhenExhausted()} is true is - * determined by the value passed in to the {@code borrowMaxWaitMillis} - * parameter. + * determined by the value passed in to the {@code maxWaitMillis} + * parameter. Passing a negative duration will cause this method to block + * indefinitely until an object becomes available. *

      *

      * When the pool is exhausted, multiple calling threads may be @@ -407,15 +403,17 @@ * available instances in request arrival order. *

      * - * @param borrowMaxWaitMillis The time to wait in milliseconds for an object + * @param maxWaitMillis The time to wait in milliseconds for an object * to become available * @return object instance from the pool * @throws NoSuchElementException if an instance cannot be returned * @throws Exception if an object instance cannot be returned due to an * error + * @deprecated Use {@link #borrowObject(Duration)}. */ - public T borrowObject(final long borrowMaxWaitMillis) throws Exception { - return borrowObject(Duration.ofMillis(borrowMaxWaitMillis)); + @Deprecated + public T borrowObject(final long maxWaitMillis) throws Exception { + return borrowObject(Duration.ofMillis(maxWaitMillis)); } /** @@ -481,7 +479,7 @@ jmxUnregister(); // Release any threads that were waiting for an object - idleObjects.interuptTakeWaiters(); + idleObjects.interruptTakeWaiters(); } } @@ -495,13 +493,13 @@ * If the factory makeObject returns null, this method throws a NullPointerException. *

      * - * @param maxWaitDuration The time to wait for an object to become available. + * @param maxWaitDurationRequest The time to wait for capacity to create. * @return The new wrapped pooled object or null. - * @throws Exception if the object factory's {@code makeObject} fails + * @throws Exception if the object factory's {@code makeObject} fails. */ - private PooledObject create(final Duration maxWaitDuration) throws Exception { + private PooledObject create(final Duration maxWaitDurationRequest) throws Exception { final Instant startInstant = Instant.now(); - Duration remainingWaitDuration = maxWaitDuration.isNegative() ? Duration.ZERO : maxWaitDuration; + final Duration maxWaitDuration = maxWaitDurationRequest.isNegative() ? Duration.ZERO : maxWaitDurationRequest; int localMaxTotal = getMaxTotal(); // This simplifies the code later in this method if (localMaxTotal < 0) { @@ -516,7 +514,7 @@ Boolean create = null; while (create == null) { // remainingWaitDuration handles spurious wakeup from wait(). - remainingWaitDuration = remainingWaitDuration.minus(durationSince(startInstant)); + final Duration remainingWaitDuration = maxWaitDuration.minus(durationSince(startInstant)); synchronized (makeObjectCountLock) { final long newCreateCount = createCount.incrementAndGet(); if (newCreateCount > localMaxTotal) { @@ -580,7 +578,7 @@ } createdCount.incrementAndGet(); - allObjects.put(new IdentityWrapper<>(p.getObject()), p); + allObjects.put(IdentityWrapper.unwrap(p), p); return p; } @@ -595,7 +593,7 @@ private void destroy(final PooledObject toDestroy, final DestroyMode destroyMode) throws Exception { toDestroy.invalidate(); idleObjects.remove(toDestroy); - allObjects.remove(new IdentityWrapper<>(toDestroy.getObject())); + allObjects.remove(IdentityWrapper.unwrap(toDestroy)); try { factory.destroyObject(toDestroy, destroyMode); } finally { @@ -604,6 +602,7 @@ } } + /** * Tries to ensure that {@code idleCount} idle instances exist in the pool. *

      @@ -760,8 +759,6 @@ } } underTest.endEvictionTest(idleObjects); - // TODO - May need to add code here once additional - // states are used } } } @@ -917,7 +914,8 @@ * {@inheritDoc} *

      * Activation of this method decrements the active count and attempts to destroy the instance, using the provided - * {@link DestroyMode}. + * {@link DestroyMode}. To ensure liveness of the pool, {@link #addObject()} is called to replace the invalidated + * instance. *

      * * @throws Exception if an exception occurs destroying the object @@ -938,7 +936,9 @@ destroy(p, destroyMode); } } - ensureIdle(1, false); + if (!isClosed()) { + addObject(); + } } /** @@ -957,11 +957,12 @@ public Set listAllObjects() { return allObjects.values().stream().map(DefaultPooledObjectInfo::new).collect(Collectors.toSet()); } + /** * Tries to ensure that {@link #getMinIdle()} idle instances are available * in the pool. * - * @throws Exception If the associated factory throws an exception + * @throws Exception If the associated factory throws an exception. * @since 2.4 */ public void preparePool() throws Exception { @@ -973,7 +974,10 @@ /** * Recovers abandoned objects which have been checked out but - * not used since longer than the removeAbandonedTimeout. + * not used since longer than the removeAbandonedTimeout. For each object + * deemed abandoned, {@link #invalidateObject(Object)} is called. This + * results in the object being destroyed and then {@link #addObject()} is + * called to try to replace it. * * @param abandonedConfig The configuration to use to identify abandoned objects */ @@ -1021,75 +1025,76 @@ } return; // Object was abandoned and removed } + synchronized (p) { + markReturningState(p); - markReturningState(p); - - final Duration activeTime = p.getActiveDuration(); + final Duration activeTime = p.getActiveDuration(); - if (getTestOnReturn() && !factory.validateObject(p)) { - try { - destroy(p, DestroyMode.NORMAL); - } catch (final Exception e) { - swallowException(e); - } - try { - ensureIdle(1, false); - } catch (final Exception e) { - swallowException(e); + if (getTestOnReturn() && !factory.validateObject(p)) { + try { + destroy(p, DestroyMode.NORMAL); + } catch (final Exception e) { + swallowException(e); + } + try { + ensureIdle(1, false); + } catch (final Exception e) { + swallowException(e); + } + updateStatsReturn(activeTime); + return; } - updateStatsReturn(activeTime); - return; - } - try { - factory.passivateObject(p); - } catch (final Exception e1) { - swallowException(e1); try { - destroy(p, DestroyMode.NORMAL); - } catch (final Exception e) { - swallowException(e); - } - try { - ensureIdle(1, false); - } catch (final Exception e) { - swallowException(e); + factory.passivateObject(p); + } catch (final Exception e1) { + swallowException(e1); + try { + destroy(p, DestroyMode.NORMAL); + } catch (final Exception e) { + swallowException(e); + } + try { + ensureIdle(1, false); + } catch (final Exception e) { + swallowException(e); + } + updateStatsReturn(activeTime); + return; } - updateStatsReturn(activeTime); - return; - } - if (!p.deallocate()) { - throw new IllegalStateException( - "Object has already been returned to this pool or is invalid"); - } - - final int maxIdleSave = getMaxIdle(); - if (isClosed() || maxIdleSave > -1 && maxIdleSave <= idleObjects.size()) { - try { - destroy(p, DestroyMode.NORMAL); - } catch (final Exception e) { - swallowException(e); - } - try { - ensureIdle(1, false); - } catch (final Exception e) { - swallowException(e); + if (!p.deallocate()) { + throw new IllegalStateException( + "Object has already been returned to this pool or is invalid"); } - } else { - if (getLifo()) { - idleObjects.addFirst(p); + + final int maxIdleSave = getMaxIdle(); + if (isClosed() || maxIdleSave > -1 && maxIdleSave <= idleObjects.size()) { + try { + destroy(p, DestroyMode.NORMAL); + } catch (final Exception e) { + swallowException(e); + } + try { + ensureIdle(1, false); + } catch (final Exception e) { + swallowException(e); + } } else { - idleObjects.addLast(p); - } - if (isClosed()) { - // Pool closed while object was being added to idle objects. - // Make sure the returned object is destroyed rather than left - // in the idle object pool (which would effectively be a leak) - clear(); + if (getLifo()) { + idleObjects.addFirst(p); + } else { + idleObjects.addLast(p); + } + if (isClosed()) { + // Pool closed while object was being added to idle objects. + // Make sure the returned object is destroyed rather than left + // in the idle object pool (which would effectively be a leak) + clear(); + } } + updateStatsReturn(activeTime); } - updateStatsReturn(activeTime); } /** diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/dbcp/pool2/impl/GenericObjectPoolConfig.java tomcat10-10.1.52/java/org/apache/tomcat/dbcp/pool2/impl/GenericObjectPoolConfig.java --- tomcat10-10.1.40/java/org/apache/tomcat/dbcp/pool2/impl/GenericObjectPoolConfig.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/dbcp/pool2/impl/GenericObjectPoolConfig.java 2026-01-23 19:33:36.000000000 +0000 @@ -6,7 +6,7 @@ * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -57,6 +57,13 @@ private int minIdle = DEFAULT_MIN_IDLE; + /** + * Constructs a new instance. + */ + public GenericObjectPoolConfig() { + // empty + } + @SuppressWarnings("unchecked") @Override public GenericObjectPoolConfig clone() { diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/dbcp/pool2/impl/GenericObjectPoolMXBean.java tomcat10-10.1.52/java/org/apache/tomcat/dbcp/pool2/impl/GenericObjectPoolMXBean.java --- tomcat10-10.1.40/java/org/apache/tomcat/dbcp/pool2/impl/GenericObjectPoolMXBean.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/dbcp/pool2/impl/GenericObjectPoolMXBean.java 2026-01-23 19:33:36.000000000 +0000 @@ -6,7 +6,7 @@ * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/dbcp/pool2/impl/InterruptibleReentrantLock.java tomcat10-10.1.52/java/org/apache/tomcat/dbcp/pool2/impl/InterruptibleReentrantLock.java --- tomcat10-10.1.40/java/org/apache/tomcat/dbcp/pool2/impl/InterruptibleReentrantLock.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/dbcp/pool2/impl/InterruptibleReentrantLock.java 2026-01-23 19:33:36.000000000 +0000 @@ -6,7 +6,7 @@ * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -37,18 +37,18 @@ * Constructs a new InterruptibleReentrantLock with the given fairness policy. * * @param fairness true means threads should acquire contended locks as if - * waiting in a FIFO queue + * waiting in a FIFO queue. */ InterruptibleReentrantLock(final boolean fairness) { super(fairness); } /** - * Interrupts the threads that are waiting on a specific condition + * Interrupts the threads that are waiting on a specific condition. * * @param condition the condition on which the threads are waiting. */ - public void interruptWaiters(final Condition condition) { + void interruptWaiters(final Condition condition) { getWaitingThreads(condition).forEach(Thread::interrupt); } } diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/dbcp/pool2/impl/LinkedBlockingDeque.java tomcat10-10.1.52/java/org/apache/tomcat/dbcp/pool2/impl/LinkedBlockingDeque.java --- tomcat10-10.1.40/java/org/apache/tomcat/dbcp/pool2/impl/LinkedBlockingDeque.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/dbcp/pool2/impl/LinkedBlockingDeque.java 2026-01-23 19:33:36.000000000 +0000 @@ -6,7 +6,7 @@ * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -22,10 +22,10 @@ import java.time.Duration; import java.util.AbstractQueue; import java.util.Collection; -import java.util.Deque; import java.util.Iterator; import java.util.NoSuchElementException; import java.util.Objects; +import java.util.concurrent.BlockingDeque; import java.util.concurrent.TimeUnit; import java.util.concurrent.locks.Condition; @@ -66,7 +66,7 @@ * @since 2.0 */ final class LinkedBlockingDeque extends AbstractQueue - implements Deque, Serializable { + implements BlockingDeque, Serializable { /* * Implemented as a simple doubly-linked list protected by a @@ -101,7 +101,7 @@ /** * The next node to return in next() */ - Node next; + Node next; /** * nextItem holds on to item fields because once we claim that @@ -223,18 +223,26 @@ /** Descending iterator */ private final class DescendingItr extends AbstractItr { @Override - Node firstNode() { return last; } + Node firstNode() { + return last; + } @Override - Node nextNode(final Node n) { return n.prev; } + Node nextNode(final Node n) { + return n.prev; + } } /** Forward iterator */ private final class Itr extends AbstractItr { @Override - Node firstNode() { return first; } + Node firstNode() { + return first; + } @Override - Node nextNode(final Node n) { return n.next; } + Node nextNode(final Node n) { + return n.next; } + } /** * Doubly-linked list node class. @@ -471,6 +479,7 @@ * @throws NullPointerException if c is null * @throws IllegalArgumentException if c is this instance */ + @Override public int drainTo(final Collection c) { return drainTo(c, Integer.MAX_VALUE); } @@ -490,6 +499,7 @@ * @throws NullPointerException if c is null * @throws IllegalArgumentException if c is this instance */ + @Override public int drainTo(final Collection collection, final int maxElements) { Objects.requireNonNull(collection, "collection"); if (collection == this) { @@ -547,10 +557,10 @@ * * @return number of threads waiting on this deque's notEmpty condition. */ - public int getTakeQueueLength() { + int getTakeQueueLength() { lock.lock(); try { - return lock.getWaitQueueLength(notEmpty); + return lock.getWaitQueueLength(notEmpty); } finally { lock.unlock(); } @@ -562,7 +572,7 @@ * * @return true if there is at least one thread waiting on this deque's notEmpty condition. */ - public boolean hasTakeWaiters() { + boolean hasTakeWaiters() { lock.lock(); try { return lock.hasWaiters(notEmpty); @@ -575,7 +585,7 @@ * Interrupts the threads currently waiting to take an object from the pool. See disclaimer on accuracy in * {@link java.util.concurrent.locks.ReentrantLock#getWaitingThreads(Condition)}. */ - public void interuptTakeWaiters() { + void interruptTakeWaiters() { lock.lock(); try { lock.interruptWaiters(notEmpty); @@ -685,6 +695,7 @@ * @throws InterruptedException if the thread is interrupted whilst waiting * for space */ + @Override public boolean offer(final E e, final long timeout, final TimeUnit unit) throws InterruptedException { return offerLast(e, timeout, unit); } @@ -711,7 +722,7 @@ * @throws InterruptedException if the thread is interrupted whilst waiting * for space */ - public boolean offerFirst(final E e, final Duration timeout) throws InterruptedException { + boolean offerFirst(final E e, final Duration timeout) throws InterruptedException { Objects.requireNonNull(e, "e"); long nanos = timeout.toNanos(); lock.lockInterruptibly(); @@ -740,6 +751,7 @@ * @throws InterruptedException if the thread is interrupted whilst waiting * for space */ + @Override public boolean offerFirst(final E e, final long timeout, final TimeUnit unit) throws InterruptedException { return offerFirst(e, PoolImplUtils.toDuration(timeout, unit)); } @@ -795,6 +807,7 @@ * @throws InterruptedException if the thread is interrupted whist waiting * for space */ + @Override public boolean offerLast(final E e, final long timeout, final TimeUnit unit) throws InterruptedException { return offerLast(e, PoolImplUtils.toDuration(timeout, unit)); } @@ -856,6 +869,7 @@ * @return the unlinked element * @throws InterruptedException if the current thread is interrupted */ + @Override public E poll(final long timeout, final TimeUnit unit) throws InterruptedException { return pollFirst(timeout, unit); } @@ -904,6 +918,7 @@ * @return the unlinked element * @throws InterruptedException if the current thread is interrupted */ + @Override public E pollFirst(final long timeout, final TimeUnit unit) throws InterruptedException { return pollFirst(PoolImplUtils.toDuration(timeout, unit)); } @@ -926,7 +941,7 @@ * @return the unlinked element * @throws InterruptedException if the current thread is interrupted */ - public E pollLast(final Duration timeout) + E pollLast(final Duration timeout) throws InterruptedException { long nanos = timeout.toNanos(); lock.lockInterruptibly(); @@ -953,6 +968,7 @@ * @return the unlinked element * @throws InterruptedException if the current thread is interrupted */ + @Override public E pollLast(final long timeout, final TimeUnit unit) throws InterruptedException { return pollLast(PoolImplUtils.toDuration(timeout, unit)); @@ -981,6 +997,7 @@ * @throws InterruptedException if the thread is interrupted whilst waiting * for space */ + @Override public void put(final E e) throws InterruptedException { putLast(e); } @@ -994,6 +1011,7 @@ * @throws InterruptedException if the thread is interrupted whilst waiting * for space */ + @Override public void putFirst(final E e) throws InterruptedException { Objects.requireNonNull(e, "e"); lock.lock(); @@ -1015,6 +1033,7 @@ * @throws InterruptedException if the thread is interrupted whilst waiting * for space */ + @Override public void putLast(final E e) throws InterruptedException { Objects.requireNonNull(e, "e"); lock.lock(); @@ -1030,12 +1049,11 @@ // Stack methods /** - * Reconstitutes this deque from a stream (that is, - * deserialize it). + * Reconstitutes this deque from a stream (that is, deserialize it). + * * @param s the stream */ - private void readObject(final ObjectInputStream s) - throws IOException, ClassNotFoundException { + private void readObject(final ObjectInputStream s) throws IOException, ClassNotFoundException { s.defaultReadObject(); count = 0; first = null; @@ -1043,7 +1061,7 @@ // Read in all elements and place in queue for (;;) { @SuppressWarnings("unchecked") - final E item = (E)s.readObject(); + final E item = (E) s.readObject(); if (item == null) { break; } @@ -1066,6 +1084,7 @@ * * @return The number of additional elements the queue is able to accept */ + @Override public int remainingCapacity() { lock.lock(); try { @@ -1238,6 +1257,7 @@ * @return the unlinked element * @throws InterruptedException if the current thread is interrupted */ + @Override public E take() throws InterruptedException { return takeFirst(); } @@ -1249,6 +1269,7 @@ * @return the unlinked element * @throws InterruptedException if the current thread is interrupted */ + @Override public E takeFirst() throws InterruptedException { lock.lock(); try { @@ -1269,6 +1290,7 @@ * @return the unlinked element * @throws InterruptedException if the current thread is interrupted */ + @Override public E takeLast() throws InterruptedException { lock.lock(); try { @@ -1319,12 +1341,11 @@ lock.lock(); try { if (a.length < count) { - a = (T[])java.lang.reflect.Array.newInstance - (a.getClass().getComponentType(), count); + a = (T[]) java.lang.reflect.Array.newInstance(a.getClass().getComponentType(), count); } int k = 0; for (Node p = first; p != null; p = p.next) { - a[k++] = (T)p.item; + a[k++] = (T) p.item; } if (a.length > k) { a[k] = null; @@ -1362,9 +1383,8 @@ p.next = n; n.prev = p; x.item = null; - // Don't mess with x's links. They may still be in use by - // an iterator. - --count; + // Don't mess with x's links. They may still be in use by an iterator. + --count; notFull.signal(); } } diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/dbcp/pool2/impl/NoOpCallStack.java tomcat10-10.1.52/java/org/apache/tomcat/dbcp/pool2/impl/NoOpCallStack.java --- tomcat10-10.1.40/java/org/apache/tomcat/dbcp/pool2/impl/NoOpCallStack.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/dbcp/pool2/impl/NoOpCallStack.java 2026-01-23 19:33:36.000000000 +0000 @@ -6,7 +6,7 @@ * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -27,7 +27,7 @@ public class NoOpCallStack implements CallStack { /** - * Singleton instance. + * The singleton instance. */ public static final CallStack INSTANCE = new NoOpCallStack(); diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/dbcp/pool2/impl/PoolImplUtils.java tomcat10-10.1.52/java/org/apache/tomcat/dbcp/pool2/impl/PoolImplUtils.java --- tomcat10-10.1.40/java/org/apache/tomcat/dbcp/pool2/impl/PoolImplUtils.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/dbcp/pool2/impl/PoolImplUtils.java 2026-01-23 19:33:36.000000000 +0000 @@ -6,7 +6,7 @@ * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -197,22 +197,22 @@ static ChronoUnit toChronoUnit(final TimeUnit timeUnit) { // TODO when using Java >= 9: Use TimeUnit.toChronoUnit(). switch (Objects.requireNonNull(timeUnit)) { - case NANOSECONDS: - return ChronoUnit.NANOS; - case MICROSECONDS: - return ChronoUnit.MICROS; - case MILLISECONDS: - return ChronoUnit.MILLIS; - case SECONDS: - return ChronoUnit.SECONDS; - case MINUTES: - return ChronoUnit.MINUTES; - case HOURS: - return ChronoUnit.HOURS; - case DAYS: - return ChronoUnit.DAYS; - default: - throw new IllegalArgumentException(timeUnit.toString()); + case NANOSECONDS: + return ChronoUnit.NANOS; + case MICROSECONDS: + return ChronoUnit.MICROS; + case MILLISECONDS: + return ChronoUnit.MILLIS; + case SECONDS: + return ChronoUnit.SECONDS; + case MINUTES: + return ChronoUnit.MINUTES; + case HOURS: + return ChronoUnit.HOURS; + case DAYS: + return ChronoUnit.DAYS; + default: + throw new IllegalArgumentException(timeUnit.toString()); } } diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/dbcp/pool2/impl/PooledSoftReference.java tomcat10-10.1.52/java/org/apache/tomcat/dbcp/pool2/impl/PooledSoftReference.java --- tomcat10-10.1.40/java/org/apache/tomcat/dbcp/pool2/impl/PooledSoftReference.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/dbcp/pool2/impl/PooledSoftReference.java 2026-01-23 19:33:36.000000000 +0000 @@ -6,7 +6,7 @@ * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/dbcp/pool2/impl/SoftReferenceObjectPool.java tomcat10-10.1.52/java/org/apache/tomcat/dbcp/pool2/impl/SoftReferenceObjectPool.java --- tomcat10-10.1.40/java/org/apache/tomcat/dbcp/pool2/impl/SoftReferenceObjectPool.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/dbcp/pool2/impl/SoftReferenceObjectPool.java 2026-01-23 19:33:36.000000000 +0000 @@ -6,7 +6,7 @@ * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -23,6 +23,7 @@ import java.util.Iterator; import java.util.NoSuchElementException; import java.util.Optional; +import java.util.concurrent.BlockingDeque; import org.apache.tomcat.dbcp.pool2.BaseObjectPool; import org.apache.tomcat.dbcp.pool2.ObjectPool; @@ -62,12 +63,11 @@ private long createCount; // @GuardedBy("this") /** Idle references - waiting to be borrowed */ - private final LinkedBlockingDeque> idleReferences = - new LinkedBlockingDeque<>(); + private final BlockingDeque> idleReferences = new LinkedBlockingDeque<>(); /** All references - checked out or waiting to be borrowed. */ private final ArrayList> allReferences = - new ArrayList<>(); + new ArrayList<>(); /** * Constructs a {@code SoftReferenceObjectPool} with the specified factory. @@ -262,7 +262,7 @@ } /** - * Destroys a {@code PooledSoftReference} and removes it from the idle and all + * Destroys a {@link PooledSoftReference} and removes it from the idle and all * references pools. * * @param toDestroy PooledSoftReference to destroy @@ -329,7 +329,7 @@ final PooledSoftReference ref = findReference(obj); if (ref == null) { throw new IllegalStateException( - "Object to invalidate is not currently part of this pool"); + "Object to invalidate is not currently part of this pool"); } if (factory != null) { destroy(ref); @@ -392,7 +392,7 @@ final PooledSoftReference ref = findReference(obj); if (ref == null) { throw new IllegalStateException( - "Returned object not currently part of this pool"); + "Returned object not currently part of this pool"); } if (factory != null) { if (!factory.validateObject(ref)) { diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/dbcp/pool2/impl/ThrowableCallStack.java tomcat10-10.1.52/java/org/apache/tomcat/dbcp/pool2/impl/ThrowableCallStack.java --- tomcat10-10.1.40/java/org/apache/tomcat/dbcp/pool2/impl/ThrowableCallStack.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/dbcp/pool2/impl/ThrowableCallStack.java 2026-01-23 19:33:36.000000000 +0000 @@ -6,7 +6,7 @@ * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -42,7 +42,7 @@ /** * Constructs a new instance with its message set to the now instant. */ - Snapshot() { + private Snapshot() { this(Instant.now()); } diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/jni/AprStatus.java tomcat10-10.1.52/java/org/apache/tomcat/jni/AprStatus.java --- tomcat10-10.1.40/java/org/apache/tomcat/jni/AprStatus.java 1970-01-01 00:00:00.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/jni/AprStatus.java 2026-01-23 19:33:36.000000000 +0000 @@ -0,0 +1,89 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.tomcat.jni; + +import java.util.concurrent.locks.ReentrantReadWriteLock; + +/** + * Holds APR status without the need to load other classes. + */ +public class AprStatus { + private static volatile boolean aprInitialized = false; + private static volatile boolean aprAvailable = false; + private static volatile boolean useOpenSSL = true; + private static volatile boolean instanceCreated = false; + private static volatile int openSSLVersion = 0; + private static ReentrantReadWriteLock statusLock = new ReentrantReadWriteLock(); + + public static boolean isAprInitialized() { + return aprInitialized; + } + + public static boolean isAprAvailable() { + return aprAvailable; + } + + public static boolean getUseOpenSSL() { + return useOpenSSL; + } + + public static boolean isInstanceCreated() { + return instanceCreated; + } + + public static void setAprInitialized(boolean aprInitialized) { + AprStatus.aprInitialized = aprInitialized; + } + + public static void setAprAvailable(boolean aprAvailable) { + AprStatus.aprAvailable = aprAvailable; + } + + public static void setUseOpenSSL(boolean useOpenSSL) { + AprStatus.useOpenSSL = useOpenSSL; + } + + public static void setInstanceCreated(boolean instanceCreated) { + AprStatus.instanceCreated = instanceCreated; + } + + /** + * @return the openSSLVersion + */ + public static int getOpenSSLVersion() { + return openSSLVersion; + } + + /** + * @param openSSLVersion the openSSLVersion to set + */ + public static void setOpenSSLVersion(int openSSLVersion) { + AprStatus.openSSLVersion = openSSLVersion; + } + + /** + * Code that changes the status of the APR library MUST hold the write lock while making any changes. + *

      + * Code that needs the status to be consistent for an operation must hold the read lock for the duration of that + * operation. + * + * @return The read/write lock for APR library status + */ + public static ReentrantReadWriteLock getStatusLock() { + return statusLock; + } +} diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/jni/Buffer.java tomcat10-10.1.52/java/org/apache/tomcat/jni/Buffer.java --- tomcat10-10.1.40/java/org/apache/tomcat/jni/Buffer.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/jni/Buffer.java 2026-01-23 19:33:36.000000000 +0000 @@ -19,8 +19,7 @@ import java.nio.ByteBuffer; /** - * Provides utilities related to the use of directly allocated - * {@link ByteBuffer} instances with native code. + * Provides utilities related to the use of directly allocated {@link ByteBuffer} instances with native code. */ public class Buffer { diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/jni/CertificateVerifier.java tomcat10-10.1.52/java/org/apache/tomcat/jni/CertificateVerifier.java --- tomcat10-10.1.40/java/org/apache/tomcat/jni/CertificateVerifier.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/jni/CertificateVerifier.java 2026-01-23 19:33:36.000000000 +0000 @@ -22,13 +22,14 @@ public interface CertificateVerifier { /** - * Returns {@code true} if the passed in certificate chain could be verified and so the handshake - * should be successful, {@code false} otherwise. + * Returns {@code true} if the passed in certificate chain could be verified and so the handshake should be + * successful, {@code false} otherwise. * - * @param ssl the SSL instance - * @param x509 the {@code X509} certificate chain - * @param authAlgorithm the auth algorithm - * @return verified {@code true} if verified successful, {@code false} otherwise + * @param ssl the SSL instance + * @param x509 the {@code X509} certificate chain + * @param authAlgorithm the auth algorithm + * + * @return verified {@code true} if verified successful, {@code false} otherwise */ boolean verify(long ssl, byte[][] x509, String authAlgorithm); } diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/jni/FileInfo.java tomcat10-10.1.52/java/org/apache/tomcat/jni/FileInfo.java --- tomcat10-10.1.40/java/org/apache/tomcat/jni/FileInfo.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/jni/FileInfo.java 2026-01-23 19:33:36.000000000 +0000 @@ -17,10 +17,9 @@ package org.apache.tomcat.jni; /** - * Tomcat Native 1.2.33 and earlier won't initialise unless this class is - * present. This dummy class ensures initialisation gets as far as being able to - * check the version of the Tomcat Native library and reporting a version error - * if 1.2.33 or earlier is present. + * Tomcat Native 1.2.33 and earlier won't initialise unless this class is present. This dummy class ensures + * initialisation gets as far as being able to check the version of the Tomcat Native library and reporting a version + * error if 1.2.33 or earlier is present. */ public class FileInfo { diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/jni/Library.java tomcat10-10.1.52/java/org/apache/tomcat/jni/Library.java --- tomcat10-10.1.40/java/org/apache/tomcat/jni/Library.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/jni/Library.java 2026-01-23 19:33:36.000000000 +0000 @@ -21,7 +21,7 @@ public final class Library { /* Default library names - use 2.x in preference to 1.x if both are available */ - private static final String [] NAMES = {"tcnative-2", "libtcnative-2", "tcnative-1", "libtcnative-1"}; + private static final String[] NAMES = { "tcnative-2", "libtcnative-2", "tcnative-1", "libtcnative-1" }; /* System property used to define CATALINA_HOME */ private static final String CATALINA_HOME_PROP = "catalina.home"; /* @@ -56,7 +56,7 @@ } if (!loaded) { String path = System.getProperty("java.library.path"); - String [] paths = path.split(File.pathSeparator); + String[] paths = path.split(File.pathSeparator); for (String value : NAMES) { try { System.loadLibrary(value); @@ -88,12 +88,11 @@ names.append(name); names.append(", "); } - throw new LibraryNotFoundError(names.substring(0, names.length() -2), err.toString()); + throw new LibraryNotFoundError(names.substring(0, names.length() - 2), err.toString()); } } - private Library(String libraryName) - { + private Library(String libraryName) { System.loadLibrary(libraryName); } @@ -101,43 +100,45 @@ * Create Tomcat Native's global APR pool. This has to be the first call to TCN library. */ private static native boolean initialize(); + /** * Destroys Tomcat Native's global APR pool. This has to be the last call to TCN library. This will destroy any APR * root pools that have not been explicitly destroyed. */ public static native void terminate(); + /* Internal function for loading APR Features */ private static native int version(int what); /* TCN_MAJOR_VERSION */ - public static int TCN_MAJOR_VERSION = 0; + public static int TCN_MAJOR_VERSION = 0; /* TCN_MINOR_VERSION */ - public static int TCN_MINOR_VERSION = 0; + public static int TCN_MINOR_VERSION = 0; /* TCN_PATCH_VERSION */ - public static int TCN_PATCH_VERSION = 0; + public static int TCN_PATCH_VERSION = 0; /* TCN_IS_DEV_VERSION */ public static int TCN_IS_DEV_VERSION = 0; /* APR_MAJOR_VERSION */ - public static int APR_MAJOR_VERSION = 0; + public static int APR_MAJOR_VERSION = 0; /* APR_MINOR_VERSION */ - public static int APR_MINOR_VERSION = 0; + public static int APR_MINOR_VERSION = 0; /* APR_PATCH_VERSION */ - public static int APR_PATCH_VERSION = 0; + public static int APR_PATCH_VERSION = 0; /* APR_IS_DEV_VERSION */ public static int APR_IS_DEV_VERSION = 0; /* TCN_VERSION_STRING */ public static native String versionString(); + /* APR_VERSION_STRING */ public static native String aprVersionString(); /** - * Setup any APR internal data structures. This MUST be the first function - * called for any APR library. + * Setup any APR internal data structures. This MUST be the first function called for any APR library. + * * @param libraryName the name of the library to load * - * @return {@code true} if the native code was initialized successfully - * otherwise {@code false} + * @return {@code true} if the native code was initialized successfully otherwise {@code false} * * @throws Exception if a problem occurred during initialization */ @@ -148,18 +149,17 @@ } else { _instance = new Library(libraryName); } - TCN_MAJOR_VERSION = version(0x01); - TCN_MINOR_VERSION = version(0x02); - TCN_PATCH_VERSION = version(0x03); + TCN_MAJOR_VERSION = version(0x01); + TCN_MINOR_VERSION = version(0x02); + TCN_PATCH_VERSION = version(0x03); TCN_IS_DEV_VERSION = version(0x04); - APR_MAJOR_VERSION = version(0x11); - APR_MINOR_VERSION = version(0x12); - APR_PATCH_VERSION = version(0x13); + APR_MAJOR_VERSION = version(0x11); + APR_MINOR_VERSION = version(0x12); + APR_PATCH_VERSION = version(0x13); APR_IS_DEV_VERSION = version(0x14); if (APR_MAJOR_VERSION < 1) { - throw new UnsatisfiedLinkError("Unsupported APR Version (" + - aprVersionString() + ")"); + throw new UnsatisfiedLinkError("Unsupported APR Version (" + aprVersionString() + ")"); } } return initialize(); diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/jni/LibraryNotFoundError.java tomcat10-10.1.52/java/org/apache/tomcat/jni/LibraryNotFoundError.java --- tomcat10-10.1.40/java/org/apache/tomcat/jni/LibraryNotFoundError.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/jni/LibraryNotFoundError.java 2026-01-23 19:33:36.000000000 +0000 @@ -23,17 +23,15 @@ private final String libraryNames; /** - * @param libraryNames A list of the file names of the native libraries that - * failed to load - * @param errors A list of the error messages received when trying to load - * each of the libraries + * @param libraryNames A list of the file names of the native libraries that failed to load + * @param errors A list of the error messages received when trying to load each of the libraries */ - public LibraryNotFoundError(String libraryNames, String errors){ + public LibraryNotFoundError(String libraryNames, String errors) { super(errors); this.libraryNames = libraryNames; } - public String getLibraryNames(){ + public String getLibraryNames() { return libraryNames; } } diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/jni/Pool.java tomcat10-10.1.52/java/org/apache/tomcat/jni/Pool.java --- tomcat10-10.1.40/java/org/apache/tomcat/jni/Pool.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/jni/Pool.java 2026-01-23 19:33:36.000000000 +0000 @@ -17,26 +17,23 @@ package org.apache.tomcat.jni; /** - * Provides access to APR memory pools which are used to manage memory - * allocations for natively created instances. + * Provides access to APR memory pools which are used to manage memory allocations for natively created instances. */ public class Pool { /** * Create a new pool. * - * @param parent The parent pool. If this is 0, the new pool is a root pool. - * If it is non-zero, the new pool will inherit all of its - * parent pool's attributes, except the apr_pool_t will be a - * sub-pool. + * @param parent The parent pool. If this is 0, the new pool is a root pool. If it is non-zero, the new pool will + * inherit all of its parent pool's attributes, except the apr_pool_t will be a sub-pool. * * @return The pool we have just created. - */ + */ public static native long create(long parent); /** - * Destroy the pool. This takes similar action as apr_pool_clear() and then - * frees all the memory. This will actually free the memory. + * Destroy the pool. This takes similar action as apr_pool_clear() and then frees all the memory. This will actually + * free the memory. * * @param pool The pool to destroy */ diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/jni/SSL.java tomcat10-10.1.52/java/org/apache/tomcat/jni/SSL.java --- tomcat10-10.1.40/java/org/apache/tomcat/jni/SSL.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/jni/SSL.java 2026-01-23 19:33:36.000000000 +0000 @@ -21,61 +21,62 @@ /* * Type definitions mostly from mod_ssl */ - public static final int UNSET = -1; + public static final int UNSET = -1; /* * Define the certificate algorithm types */ public static final int SSL_ALGO_UNKNOWN = 0; - public static final int SSL_ALGO_RSA = (1<<0); - public static final int SSL_ALGO_DSA = (1<<1); - public static final int SSL_ALGO_ALL = (SSL_ALGO_RSA|SSL_ALGO_DSA); - - public static final int SSL_AIDX_RSA = 0; - public static final int SSL_AIDX_DSA = 1; - public static final int SSL_AIDX_ECC = 3; - public static final int SSL_AIDX_MAX = 4; + public static final int SSL_ALGO_RSA = (1 << 0); + public static final int SSL_ALGO_DSA = (1 << 1); + public static final int SSL_ALGO_ALL = (SSL_ALGO_RSA | SSL_ALGO_DSA); + + public static final int SSL_AIDX_RSA = 0; + public static final int SSL_AIDX_DSA = 1; + public static final int SSL_AIDX_ECC = 3; + public static final int SSL_AIDX_MAX = 4; /* * Define IDs for the temporary RSA keys and DH params */ - public static final int SSL_TMP_KEY_RSA_512 = 0; + public static final int SSL_TMP_KEY_RSA_512 = 0; public static final int SSL_TMP_KEY_RSA_1024 = 1; public static final int SSL_TMP_KEY_RSA_2048 = 2; public static final int SSL_TMP_KEY_RSA_4096 = 3; - public static final int SSL_TMP_KEY_DH_512 = 4; - public static final int SSL_TMP_KEY_DH_1024 = 5; - public static final int SSL_TMP_KEY_DH_2048 = 6; - public static final int SSL_TMP_KEY_DH_4096 = 7; - public static final int SSL_TMP_KEY_MAX = 8; + public static final int SSL_TMP_KEY_DH_512 = 4; + public static final int SSL_TMP_KEY_DH_1024 = 5; + public static final int SSL_TMP_KEY_DH_2048 = 6; + public static final int SSL_TMP_KEY_DH_4096 = 7; + public static final int SSL_TMP_KEY_MAX = 8; /* * Define the SSL options */ - public static final int SSL_OPT_NONE = 0; - public static final int SSL_OPT_RELSET = (1<<0); - public static final int SSL_OPT_STDENVVARS = (1<<1); - public static final int SSL_OPT_EXPORTCERTDATA = (1<<3); - public static final int SSL_OPT_FAKEBASICAUTH = (1<<4); - public static final int SSL_OPT_STRICTREQUIRE = (1<<5); - public static final int SSL_OPT_OPTRENEGOTIATE = (1<<6); - public static final int SSL_OPT_ALL = (SSL_OPT_STDENVVARS|SSL_OPT_EXPORTCERTDATA|SSL_OPT_FAKEBASICAUTH|SSL_OPT_STRICTREQUIRE|SSL_OPT_OPTRENEGOTIATE); + public static final int SSL_OPT_NONE = 0; + public static final int SSL_OPT_RELSET = (1 << 0); + public static final int SSL_OPT_STDENVVARS = (1 << 1); + public static final int SSL_OPT_EXPORTCERTDATA = (1 << 3); + public static final int SSL_OPT_FAKEBASICAUTH = (1 << 4); + public static final int SSL_OPT_STRICTREQUIRE = (1 << 5); + public static final int SSL_OPT_OPTRENEGOTIATE = (1 << 6); + public static final int SSL_OPT_ALL = (SSL_OPT_STDENVVARS | SSL_OPT_EXPORTCERTDATA | SSL_OPT_FAKEBASICAUTH | + SSL_OPT_STRICTREQUIRE | SSL_OPT_OPTRENEGOTIATE); /* * Define the SSL Protocol options */ - public static final int SSL_PROTOCOL_NONE = 0; - public static final int SSL_PROTOCOL_SSLV2 = (1<<0); - public static final int SSL_PROTOCOL_SSLV3 = (1<<1); - public static final int SSL_PROTOCOL_TLSV1 = (1<<2); - public static final int SSL_PROTOCOL_TLSV1_1 = (1<<3); - public static final int SSL_PROTOCOL_TLSV1_2 = (1<<4); - public static final int SSL_PROTOCOL_TLSV1_3 = (1<<5); + public static final int SSL_PROTOCOL_NONE = 0; + public static final int SSL_PROTOCOL_SSLV2 = (1 << 0); + public static final int SSL_PROTOCOL_SSLV3 = (1 << 1); + public static final int SSL_PROTOCOL_TLSV1 = (1 << 2); + public static final int SSL_PROTOCOL_TLSV1_1 = (1 << 3); + public static final int SSL_PROTOCOL_TLSV1_2 = (1 << 4); + public static final int SSL_PROTOCOL_TLSV1_3 = (1 << 5); public static final int SSL_PROTOCOL_ALL; static { if (version() >= 0x1010100f) { - SSL_PROTOCOL_ALL = (SSL_PROTOCOL_TLSV1 | SSL_PROTOCOL_TLSV1_1 | SSL_PROTOCOL_TLSV1_2 | - SSL_PROTOCOL_TLSV1_3); + SSL_PROTOCOL_ALL = + (SSL_PROTOCOL_TLSV1 | SSL_PROTOCOL_TLSV1_1 | SSL_PROTOCOL_TLSV1_2 | SSL_PROTOCOL_TLSV1_3); } else { SSL_PROTOCOL_ALL = (SSL_PROTOCOL_TLSV1 | SSL_PROTOCOL_TLSV1_1 | SSL_PROTOCOL_TLSV1_2); } @@ -85,154 +86,159 @@ /* * Define the SSL verify levels */ - public static final int SSL_CVERIFY_UNSET = UNSET; - public static final int SSL_CVERIFY_NONE = 0; - public static final int SSL_CVERIFY_OPTIONAL = 1; - public static final int SSL_CVERIFY_REQUIRE = 2; + public static final int SSL_CVERIFY_UNSET = UNSET; + public static final int SSL_CVERIFY_NONE = 0; + public static final int SSL_CVERIFY_OPTIONAL = 1; + public static final int SSL_CVERIFY_REQUIRE = 2; public static final int SSL_CVERIFY_OPTIONAL_NO_CA = 3; - /* Use either SSL_VERIFY_NONE or SSL_VERIFY_PEER, the last 2 options - * are 'ored' with SSL_VERIFY_PEER if they are desired + /* + * Use either SSL_VERIFY_NONE or SSL_VERIFY_PEER, the last 2 options are 'ored' with SSL_VERIFY_PEER if they are + * desired */ - public static final int SSL_VERIFY_NONE = 0; - public static final int SSL_VERIFY_PEER = 1; + public static final int SSL_VERIFY_NONE = 0; + public static final int SSL_VERIFY_PEER = 1; public static final int SSL_VERIFY_FAIL_IF_NO_PEER_CERT = 2; - public static final int SSL_VERIFY_CLIENT_ONCE = 4; - public static final int SSL_VERIFY_PEER_STRICT = (SSL_VERIFY_PEER|SSL_VERIFY_FAIL_IF_NO_PEER_CERT); + public static final int SSL_VERIFY_CLIENT_ONCE = 4; + public static final int SSL_VERIFY_PEER_STRICT = (SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT); - public static final int SSL_OP_MICROSOFT_SESS_ID_BUG = 0x00000001; - public static final int SSL_OP_NETSCAPE_CHALLENGE_BUG = 0x00000002; + public static final int SSL_OP_MICROSOFT_SESS_ID_BUG = 0x00000001; + public static final int SSL_OP_NETSCAPE_CHALLENGE_BUG = 0x00000002; public static final int SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG = 0x00000008; - public static final int SSL_OP_SSLREF2_REUSE_CERT_TYPE_BUG = 0x00000010; - public static final int SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER = 0x00000020; - public static final int SSL_OP_MSIE_SSLV2_RSA_PADDING = 0x00000040; - public static final int SSL_OP_SSLEAY_080_CLIENT_DH_BUG = 0x00000080; - public static final int SSL_OP_TLS_D5_BUG = 0x00000100; - public static final int SSL_OP_TLS_BLOCK_PADDING_BUG = 0x00000200; - - /* Disable SSL 3.0/TLS 1.0 CBC vulnerability workaround that was added - * in OpenSSL 0.9.6d. Usually (depending on the application protocol) - * the workaround is not needed. Unfortunately some broken SSL/TLS - * implementations cannot handle it at all, which is why we include - * it in SSL_OP_ALL. */ - public static final int SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS = 0x00000800; - - /* SSL_OP_ALL: various bug workarounds that should be rather harmless. - * This used to be 0x000FFFFFL before 0.9.7. */ - public static final int SSL_OP_ALL = 0x00000FFF; + public static final int SSL_OP_SSLREF2_REUSE_CERT_TYPE_BUG = 0x00000010; + public static final int SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER = 0x00000020; + public static final int SSL_OP_MSIE_SSLV2_RSA_PADDING = 0x00000040; + public static final int SSL_OP_SSLEAY_080_CLIENT_DH_BUG = 0x00000080; + public static final int SSL_OP_TLS_D5_BUG = 0x00000100; + public static final int SSL_OP_TLS_BLOCK_PADDING_BUG = 0x00000200; + + /* + * Disable SSL 3.0/TLS 1.0 CBC vulnerability workaround that was added in OpenSSL 0.9.6d. Usually (depending on the + * application protocol) the workaround is not needed. Unfortunately some broken SSL/TLS implementations cannot + * handle it at all, which is why we include it in SSL_OP_ALL. + */ + public static final int SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS = 0x00000800; + + /* + * SSL_OP_ALL: various bug workarounds that should be rather harmless. This used to be 0x000FFFFFL before 0.9.7. + */ + public static final int SSL_OP_ALL = 0x00000FFF; /* As server, disallow session resumption on renegotiation */ public static final int SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION = 0x00010000; /* Don't use compression even if supported */ - public static final int SSL_OP_NO_COMPRESSION = 0x00020000; + public static final int SSL_OP_NO_COMPRESSION = 0x00020000; /* Permit unsafe legacy renegotiation */ - public static final int SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION = 0x00040000; + public static final int SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION = 0x00040000; /* If set, always create a new key when using tmp_eddh parameters */ - public static final int SSL_OP_SINGLE_ECDH_USE = 0x00080000; + public static final int SSL_OP_SINGLE_ECDH_USE = 0x00080000; /* If set, always create a new key when using tmp_dh parameters */ - public static final int SSL_OP_SINGLE_DH_USE = 0x00100000; - /* Set to always use the tmp_rsa key when doing RSA operations, - * even when this violates protocol specs */ - public static final int SSL_OP_EPHEMERAL_RSA = 0x00200000; - /* Set on servers to choose the cipher according to the server's - * preferences */ - public static final int SSL_OP_CIPHER_SERVER_PREFERENCE = 0x00400000; - /* If set, a server will allow a client to issue an SSLv3.0 version number - * as latest version supported in the premaster secret, even when TLSv1.0 - * (version 3.1) was announced in the client hello. Normally this is - * forbidden to prevent version rollback attacks. */ - public static final int SSL_OP_TLS_ROLLBACK_BUG = 0x00800000; - - public static final int SSL_OP_NO_SSLv2 = 0x01000000; - public static final int SSL_OP_NO_SSLv3 = 0x02000000; - public static final int SSL_OP_NO_TLSv1 = 0x04000000; - public static final int SSL_OP_NO_TLSv1_2 = 0x08000000; - public static final int SSL_OP_NO_TLSv1_1 = 0x10000000; - - public static final int SSL_OP_NO_TICKET = 0x00004000; - - public static final int SSL_OP_NETSCAPE_CA_DN_BUG = 0x20000000; - public static final int SSL_OP_NETSCAPE_DEMO_CIPHER_CHANGE_BUG = 0x40000000; - - public static final int SSL_CRT_FORMAT_UNDEF = 0; - public static final int SSL_CRT_FORMAT_ASN1 = 1; - public static final int SSL_CRT_FORMAT_TEXT = 2; - public static final int SSL_CRT_FORMAT_PEM = 3; + public static final int SSL_OP_SINGLE_DH_USE = 0x00100000; + /* + * Set to always use the tmp_rsa key when doing RSA operations, even when this violates protocol specs + */ + public static final int SSL_OP_EPHEMERAL_RSA = 0x00200000; + /* + * Set on servers to choose the cipher according to the server's preferences + */ + public static final int SSL_OP_CIPHER_SERVER_PREFERENCE = 0x00400000; + /* + * If set, a server will allow a client to issue an SSLv3.0 version number as latest version supported in the + * premaster secret, even when TLSv1.0 (version 3.1) was announced in the client hello. Normally this is forbidden + * to prevent version rollback attacks. + */ + public static final int SSL_OP_TLS_ROLLBACK_BUG = 0x00800000; + + public static final int SSL_OP_NO_SSLv2 = 0x01000000; + public static final int SSL_OP_NO_SSLv3 = 0x02000000; + public static final int SSL_OP_NO_TLSv1 = 0x04000000; + public static final int SSL_OP_NO_TLSv1_2 = 0x08000000; + public static final int SSL_OP_NO_TLSv1_1 = 0x10000000; + + public static final int SSL_OP_NO_TICKET = 0x00004000; + + public static final int SSL_OP_NETSCAPE_CA_DN_BUG = 0x20000000; + public static final int SSL_OP_NETSCAPE_DEMO_CIPHER_CHANGE_BUG = 0x40000000; + + public static final int SSL_CRT_FORMAT_UNDEF = 0; + public static final int SSL_CRT_FORMAT_ASN1 = 1; + public static final int SSL_CRT_FORMAT_TEXT = 2; + public static final int SSL_CRT_FORMAT_PEM = 3; public static final int SSL_CRT_FORMAT_NETSCAPE = 4; - public static final int SSL_CRT_FORMAT_PKCS12 = 5; - public static final int SSL_CRT_FORMAT_SMIME = 6; - public static final int SSL_CRT_FORMAT_ENGINE = 7; - - public static final int SSL_MODE_CLIENT = 0; - public static final int SSL_MODE_SERVER = 1; - public static final int SSL_MODE_COMBINED = 2; - - public static final int SSL_CONF_FLAG_CMDLINE = 0x0001; - public static final int SSL_CONF_FLAG_FILE = 0x0002; - public static final int SSL_CONF_FLAG_CLIENT = 0x0004; - public static final int SSL_CONF_FLAG_SERVER = 0x0008; - public static final int SSL_CONF_FLAG_SHOW_ERRORS = 0x0010; - public static final int SSL_CONF_FLAG_CERTIFICATE = 0x0020; - - public static final int SSL_CONF_TYPE_UNKNOWN = 0x0000; - public static final int SSL_CONF_TYPE_STRING = 0x0001; - public static final int SSL_CONF_TYPE_FILE = 0x0002; - public static final int SSL_CONF_TYPE_DIR = 0x0003; + public static final int SSL_CRT_FORMAT_PKCS12 = 5; + public static final int SSL_CRT_FORMAT_SMIME = 6; + public static final int SSL_CRT_FORMAT_ENGINE = 7; + + public static final int SSL_MODE_CLIENT = 0; + public static final int SSL_MODE_SERVER = 1; + public static final int SSL_MODE_COMBINED = 2; + + public static final int SSL_CONF_FLAG_CMDLINE = 0x0001; + public static final int SSL_CONF_FLAG_FILE = 0x0002; + public static final int SSL_CONF_FLAG_CLIENT = 0x0004; + public static final int SSL_CONF_FLAG_SERVER = 0x0008; + public static final int SSL_CONF_FLAG_SHOW_ERRORS = 0x0010; + public static final int SSL_CONF_FLAG_CERTIFICATE = 0x0020; + + public static final int SSL_CONF_TYPE_UNKNOWN = 0x0000; + public static final int SSL_CONF_TYPE_STRING = 0x0001; + public static final int SSL_CONF_TYPE_FILE = 0x0002; + public static final int SSL_CONF_TYPE_DIR = 0x0003; - public static final int SSL_SHUTDOWN_TYPE_UNSET = 0; + public static final int SSL_SHUTDOWN_TYPE_UNSET = 0; public static final int SSL_SHUTDOWN_TYPE_STANDARD = 1; - public static final int SSL_SHUTDOWN_TYPE_UNCLEAN = 2; + public static final int SSL_SHUTDOWN_TYPE_UNCLEAN = 2; public static final int SSL_SHUTDOWN_TYPE_ACCURATE = 3; - public static final int SSL_INFO_SESSION_ID = 0x0001; - public static final int SSL_INFO_CIPHER = 0x0002; - public static final int SSL_INFO_CIPHER_USEKEYSIZE = 0x0003; - public static final int SSL_INFO_CIPHER_ALGKEYSIZE = 0x0004; - public static final int SSL_INFO_CIPHER_VERSION = 0x0005; - public static final int SSL_INFO_CIPHER_DESCRIPTION = 0x0006; - public static final int SSL_INFO_PROTOCOL = 0x0007; - - /* To obtain the CountryName of the Client Certificate Issuer - * use the SSL_INFO_CLIENT_I_DN + SSL_INFO_DN_COUNTRYNAME - */ - public static final int SSL_INFO_CLIENT_S_DN = 0x0010; - public static final int SSL_INFO_CLIENT_I_DN = 0x0020; - public static final int SSL_INFO_SERVER_S_DN = 0x0040; - public static final int SSL_INFO_SERVER_I_DN = 0x0080; - - public static final int SSL_INFO_DN_COUNTRYNAME = 0x0001; - public static final int SSL_INFO_DN_STATEORPROVINCENAME = 0x0002; - public static final int SSL_INFO_DN_LOCALITYNAME = 0x0003; - public static final int SSL_INFO_DN_ORGANIZATIONNAME = 0x0004; + public static final int SSL_INFO_SESSION_ID = 0x0001; + public static final int SSL_INFO_CIPHER = 0x0002; + public static final int SSL_INFO_CIPHER_USEKEYSIZE = 0x0003; + public static final int SSL_INFO_CIPHER_ALGKEYSIZE = 0x0004; + public static final int SSL_INFO_CIPHER_VERSION = 0x0005; + public static final int SSL_INFO_CIPHER_DESCRIPTION = 0x0006; + public static final int SSL_INFO_PROTOCOL = 0x0007; + + /* + * To obtain the CountryName of the Client Certificate Issuer use the SSL_INFO_CLIENT_I_DN + SSL_INFO_DN_COUNTRYNAME + */ + public static final int SSL_INFO_CLIENT_S_DN = 0x0010; + public static final int SSL_INFO_CLIENT_I_DN = 0x0020; + public static final int SSL_INFO_SERVER_S_DN = 0x0040; + public static final int SSL_INFO_SERVER_I_DN = 0x0080; + + public static final int SSL_INFO_DN_COUNTRYNAME = 0x0001; + public static final int SSL_INFO_DN_STATEORPROVINCENAME = 0x0002; + public static final int SSL_INFO_DN_LOCALITYNAME = 0x0003; + public static final int SSL_INFO_DN_ORGANIZATIONNAME = 0x0004; public static final int SSL_INFO_DN_ORGANIZATIONALUNITNAME = 0x0005; - public static final int SSL_INFO_DN_COMMONNAME = 0x0006; - public static final int SSL_INFO_DN_TITLE = 0x0007; - public static final int SSL_INFO_DN_INITIALS = 0x0008; - public static final int SSL_INFO_DN_GIVENNAME = 0x0009; - public static final int SSL_INFO_DN_SURNAME = 0x000A; - public static final int SSL_INFO_DN_DESCRIPTION = 0x000B; - public static final int SSL_INFO_DN_UNIQUEIDENTIFIER = 0x000C; - public static final int SSL_INFO_DN_EMAILADDRESS = 0x000D; - - public static final int SSL_INFO_CLIENT_M_VERSION = 0x0101; - public static final int SSL_INFO_CLIENT_M_SERIAL = 0x0102; - public static final int SSL_INFO_CLIENT_V_START = 0x0103; - public static final int SSL_INFO_CLIENT_V_END = 0x0104; - public static final int SSL_INFO_CLIENT_A_SIG = 0x0105; - public static final int SSL_INFO_CLIENT_A_KEY = 0x0106; - public static final int SSL_INFO_CLIENT_CERT = 0x0107; - public static final int SSL_INFO_CLIENT_V_REMAIN = 0x0108; - - public static final int SSL_INFO_SERVER_M_VERSION = 0x0201; - public static final int SSL_INFO_SERVER_M_SERIAL = 0x0202; - public static final int SSL_INFO_SERVER_V_START = 0x0203; - public static final int SSL_INFO_SERVER_V_END = 0x0204; - public static final int SSL_INFO_SERVER_A_SIG = 0x0205; - public static final int SSL_INFO_SERVER_A_KEY = 0x0206; - public static final int SSL_INFO_SERVER_CERT = 0x0207; - /* Return client certificate chain. - * Add certificate chain number to that flag (0 ... verify depth) + public static final int SSL_INFO_DN_COMMONNAME = 0x0006; + public static final int SSL_INFO_DN_TITLE = 0x0007; + public static final int SSL_INFO_DN_INITIALS = 0x0008; + public static final int SSL_INFO_DN_GIVENNAME = 0x0009; + public static final int SSL_INFO_DN_SURNAME = 0x000A; + public static final int SSL_INFO_DN_DESCRIPTION = 0x000B; + public static final int SSL_INFO_DN_UNIQUEIDENTIFIER = 0x000C; + public static final int SSL_INFO_DN_EMAILADDRESS = 0x000D; + + public static final int SSL_INFO_CLIENT_M_VERSION = 0x0101; + public static final int SSL_INFO_CLIENT_M_SERIAL = 0x0102; + public static final int SSL_INFO_CLIENT_V_START = 0x0103; + public static final int SSL_INFO_CLIENT_V_END = 0x0104; + public static final int SSL_INFO_CLIENT_A_SIG = 0x0105; + public static final int SSL_INFO_CLIENT_A_KEY = 0x0106; + public static final int SSL_INFO_CLIENT_CERT = 0x0107; + public static final int SSL_INFO_CLIENT_V_REMAIN = 0x0108; + + public static final int SSL_INFO_SERVER_M_VERSION = 0x0201; + public static final int SSL_INFO_SERVER_M_SERIAL = 0x0202; + public static final int SSL_INFO_SERVER_V_START = 0x0203; + public static final int SSL_INFO_SERVER_V_END = 0x0204; + public static final int SSL_INFO_SERVER_A_SIG = 0x0205; + public static final int SSL_INFO_SERVER_A_KEY = 0x0206; + public static final int SSL_INFO_SERVER_CERT = 0x0207; + /* + * Return client certificate chain. Add certificate chain number to that flag (0 ... verify depth) */ - public static final int SSL_INFO_CLIENT_CERT_CHAIN = 0x0400; + public static final int SSL_INFO_CLIENT_CERT_CHAIN = 0x0400; /* Only support OFF and SERVER for now */ public static final long SSL_SESS_CACHE_OFF = 0x0000; @@ -248,12 +254,12 @@ public static native String versionString(); /** - * Initialize OpenSSL support. - * This function needs to be called once for the - * lifetime of JVM. Library.init() has to be called before. - * @param engine Support for external a Crypto Device ("engine"), - * usually - * a hardware accelerator card for crypto operations. + * Initialize OpenSSL support. This function needs to be called once for the lifetime of JVM. Library.init() has to + * be called before. + * + * @param engine Support for external a Crypto Device ("engine"), usually a hardware accelerator card for crypto + * operations. + * * @return APR status code */ public static native int initialize(String engine); @@ -261,9 +267,11 @@ /** * Get the status of FIPS Mode. * - * @return FIPS_mode return code. It is 0 if OpenSSL is not - * in FIPS mode, 1 if OpenSSL is in FIPS Mode. + * @return FIPS_mode return code. It is 0 if OpenSSL is not in FIPS mode, 1 if OpenSSL is + * in FIPS Mode. + * * @throws Exception If tcnative was not compiled with FIPS Mode available. + * * @see OpenSSL method FIPS_mode() */ public static native int fipsModeGet() throws Exception; @@ -274,8 +282,10 @@ * @param mode 1 - enable, 0 - disable * * @return FIPS_mode_set return code - * @throws Exception If tcnative was not compiled with FIPS Mode available, - * or if {@code FIPS_mode_set()} call returned an error value. + * + * @throws Exception If tcnative was not compiled with FIPS Mode available, or if {@code FIPS_mode_set()} call + * returned an error value. + * * @see OpenSSL method FIPS_mode_set() */ public static native int fipsModeSet(int mode) throws Exception; @@ -283,15 +293,16 @@ /** * Sets global random filename. * - * @param filename Filename to use. - * If set it will be used for SSL initialization - * and all contexts where explicitly not set. + * @param filename Filename to use. If set it will be used for SSL initialization and all contexts where explicitly + * not set. */ public static native void randSet(String filename); /** * Return the handshake completed count. + * * @param ssl SSL pointer + * * @return the count */ public static native int getHandshakeCount(long ssl); @@ -303,84 +314,101 @@ public static final int SSL_SENT_SHUTDOWN = 1; public static final int SSL_RECEIVED_SHUTDOWN = 2; - public static final int SSL_ERROR_NONE = 0; - public static final int SSL_ERROR_SSL = 1; - public static final int SSL_ERROR_WANT_READ = 2; - public static final int SSL_ERROR_WANT_WRITE = 3; + public static final int SSL_ERROR_NONE = 0; + public static final int SSL_ERROR_SSL = 1; + public static final int SSL_ERROR_WANT_READ = 2; + public static final int SSL_ERROR_WANT_WRITE = 3; public static final int SSL_ERROR_WANT_X509_LOOKUP = 4; - public static final int SSL_ERROR_SYSCALL = 5; /* look at error stack/return value/errno */ - public static final int SSL_ERROR_ZERO_RETURN = 6; - public static final int SSL_ERROR_WANT_CONNECT = 7; - public static final int SSL_ERROR_WANT_ACCEPT = 8; + public static final int SSL_ERROR_SYSCALL = 5; /* look at error stack/return value/errno */ + public static final int SSL_ERROR_ZERO_RETURN = 6; + public static final int SSL_ERROR_WANT_CONNECT = 7; + public static final int SSL_ERROR_WANT_ACCEPT = 8; /** * SSL_new - * @param ctx Server or Client context to use. - * @param server if true configure SSL instance to use accept handshake routines - * if false configure SSL instance to use connect handshake routines + * + * @param ctx Server or Client context to use. + * @param server if true configure SSL instance to use accept handshake routines if false configure SSL instance to + * use connect handshake routines + * * @return pointer to SSL instance (SSL *) */ public static native long newSSL(long ctx, boolean server); /** * BIO_ctrl_pending. + * * @param bio BIO pointer (BIO *) + * * @return the pending bytes count */ public static native int pendingWrittenBytesInBIO(long bio); /** * SSL_pending. + * * @param ssl SSL pointer (SSL *) + * * @return the pending bytes count */ public static native int pendingReadableBytesInSSL(long ssl); /** * BIO_write. - * @param bio BIO pointer + * + * @param bio BIO pointer * @param wbuf Buffer pointer * @param wlen Write length + * * @return the bytes count written */ public static native int writeToBIO(long bio, long wbuf, int wlen); /** * BIO_read. - * @param bio BIO pointer + * + * @param bio BIO pointer * @param rbuf Buffer pointer * @param rlen Read length + * * @return the bytes count read */ public static native int readFromBIO(long bio, long rbuf, int rlen); /** * SSL_write. - * @param ssl the SSL instance (SSL *) + * + * @param ssl the SSL instance (SSL *) * @param wbuf Buffer pointer * @param wlen Write length + * * @return the bytes count written */ public static native int writeToSSL(long ssl, long wbuf, int wlen); /** * SSL_read - * @param ssl the SSL instance (SSL *) + * + * @param ssl the SSL instance (SSL *) * @param rbuf Buffer pointer * @param rlen Read length + * * @return the bytes count read */ public static native int readFromSSL(long ssl, long rbuf, int rlen); /** * SSL_get_shutdown + * * @param ssl the SSL instance (SSL *) + * * @return the operation status */ public static native int getShutdown(long ssl); /** * SSL_free + * * @param ssl the SSL instance (SSL *) */ public static native void freeSSL(long ssl); @@ -390,86 +418,106 @@ *

      * Warning: you must explicitly free this resource by calling freeBIO *

      - * While the SSL's internal/application data BIO will be freed when freeSSL is called on - * the provided SSL instance, you must call freeBIO on the returned network BIO. + * While the SSL's internal/application data BIO will be freed when freeSSL is called on the provided SSL instance, + * you must call freeBIO on the returned network BIO. * * @param ssl the SSL instance (SSL *) + * * @return pointer to the Network BIO (BIO *) */ public static native long makeNetworkBIO(long ssl); /** * BIO_free + * * @param bio BIO pointer */ public static native void freeBIO(long bio); /** * SSL_shutdown + * * @param ssl the SSL instance (SSL *) + * * @return the operation status */ public static native int shutdownSSL(long ssl); /** - * Get the error number representing the last error OpenSSL encountered on - * this thread. + * Get the error number representing the last error OpenSSL encountered on this thread. + * * @return the last error number */ public static native int getLastErrorNumber(); /** * SSL_get_cipher. + * * @param ssl the SSL instance (SSL *) + * * @return the cipher name */ public static native String getCipherForSSL(long ssl); /** * SSL_get_version + * * @param ssl the SSL instance (SSL *) + * * @return the SSL version in use */ public static native String getVersion(long ssl); /** * SSL_do_handshake + * * @param ssl the SSL instance (SSL *) + * * @return the handshake status */ public static native int doHandshake(long ssl); /** * SSL_renegotiate + * * @param ssl the SSL instance (SSL *) + * * @return the operation status */ public static native int renegotiate(long ssl); /** * SSL_renegotiate_pending + * * @param ssl the SSL instance (SSL *) + * * @return the operation status */ public static native int renegotiatePending(long ssl); /** * SSL_verify_client_post_handshake + * * @param ssl the SSL instance (SSL *) + * * @return the operation status */ public static native int verifyClientPostHandshake(long ssl); /** * Is post handshake authentication in progress on this connection? + * * @param ssl the SSL instance (SSL *) + * * @return the operation status */ public static native int getPostHandshakeAuthInProgress(long ssl); /** * SSL_in_init. + * * @param ssl the SSL instance (SSL *) + * * @return the status */ public static native int isInInit(long ssl); @@ -480,52 +528,59 @@ /** * SSL_get0_alpn_selected + * * @param ssl the SSL instance (SSL *) + * * @return the ALPN protocol negotiated */ public static native String getAlpnSelected(long ssl); /** * Get the peer certificate chain or {@code null} if none was sent. + * * @param ssl the SSL instance (SSL *) + * * @return the certificate chain bytes */ public static native byte[][] getPeerCertChain(long ssl); /** * Get the peer certificate or {@code null} if none was sent. + * * @param ssl the SSL instance (SSL *) + * * @return the certificate bytes */ public static native byte[] getPeerCertificate(long ssl); /** * Get the error number representing for the given {@code errorNumber}. + * * @param errorNumber The error code + * * @return an error message */ public static native String getErrorString(long errorNumber); /** * SSL_get_time + * * @param ssl the SSL instance (SSL *) + * * @return returns the time at which the session ssl was established. The time is given in seconds since the Epoch */ public static native long getTime(long ssl); /** - * Set Type of Client Certificate verification and Maximum depth of CA Certificates - * in Client Certificate verification. - *
      - * This directive sets the Certificate verification level for the Client - * Authentication. Notice that this directive can be used both in per-server - * and per-directory context. In per-server context it applies to the client - * authentication process used in the standard SSL handshake when a connection - * is established. In per-directory context it forces an SSL renegotiation with - * the reconfigured client verification level after the HTTP request was read - * but before the HTTP response is sent. - *
      + * Set Type of Client Certificate verification and Maximum depth of CA Certificates in Client Certificate + * verification.
      + * This directive sets the Certificate verification level for the Client Authentication. Notice that this directive + * can be used both in per-server and per-directory context. In per-server context it applies to the client + * authentication process used in the standard SSL handshake when a connection is established. In per-directory + * context it forces an SSL renegotiation with the reconfigured client verification level after the HTTP request was + * read but before the HTTP response is sent.
      * The following levels are available for level: + * *

            * SSL_CVERIFY_NONE           - No client Certificate is required at all
            * SSL_CVERIFY_OPTIONAL       - The client may present a valid Certificate
      @@ -533,66 +588,80 @@
            * SSL_CVERIFY_OPTIONAL_NO_CA - The client may present a valid Certificate
            *                              but it need not to be (successfully) verifiable
            * 
      + * *
      - * The depth actually is the maximum number of intermediate certificate issuers, - * i.e. the number of CA certificates which are max allowed to be followed while - * verifying the client certificate. A depth of 0 means that self-signed client - * certificates are accepted only, the default depth of 1 means the client - * certificate can be self-signed or has to be signed by a CA which is directly - * known to the server (i.e. the CA's certificate is under + * The depth actually is the maximum number of intermediate certificate issuers, i.e. the number of CA certificates + * which are max allowed to be followed while verifying the client certificate. A depth of 0 means that self-signed + * client certificates are accepted only, the default depth of 1 means the client certificate can be self-signed or + * has to be signed by a CA which is directly known to the server (i.e. the CA's certificate is under * {@code setCACertificatePath}, etc). * - * @param ssl the SSL instance (SSL *) + * @param ssl the SSL instance (SSL *) * @param level Type of Client Certificate verification. - * @param depth Maximum depth of CA Certificates in Client Certificate - * verification. + * @param depth Maximum depth of CA Certificates in Client Certificate verification. */ public static native void setVerify(long ssl, int level, int depth); /** * Set OpenSSL Option. - * @param ssl the SSL instance (SSL *) - * @param options See SSL.SSL_OP_* for option flags. + * + * @param ssl the SSL instance (SSL *) + * @param options See SSL.SSL_OP_* for option flags. */ public static native void setOptions(long ssl, int options); /** * Get OpenSSL Option. + * * @param ssl the SSL instance (SSL *) - * @return options See SSL.SSL_OP_* for option flags. + * + * @return options See SSL.SSL_OP_* for option flags. */ public static native int getOptions(long ssl); /** * Returns all cipher suites that are enabled for negotiation in an SSL handshake. + * * @param ssl the SSL instance (SSL *) + * * @return ciphers */ public static native String[] getCiphers(long ssl); /** - * Returns the cipher suites available for negotiation in SSL handshake. - *
      - * This complex directive uses a colon-separated cipher-spec string consisting - * of OpenSSL cipher specifications to configure the Cipher Suite the client - * is permitted to negotiate in the SSL handshake phase. Notice that this - * directive can be used both in per-server and per-directory context. - * In per-server context it applies to the standard SSL handshake when a - * connection is established. In per-directory context it forces an SSL - * renegotiation with the reconfigured Cipher Suite after the HTTP request - * was read but before the HTTP response is sent. - * @param ssl the SSL instance (SSL *) - * @param ciphers an SSL cipher specification + * Set the TLSv1.2 and below ciphers available for negotiation the in TLS handshake. + *

      + * This complex directive uses a colon-separated cipher-spec string consisting of OpenSSL cipher specifications to + * configure the ciphers the client is permitted to negotiate in the TLS handshake phase. + * + * @param ssl The SSL instance (SSL *) + * @param cipherList An OpenSSL cipher specification. + * + * @return true if the operation was successful + * + * @throws Exception An error occurred + */ + public static native boolean setCipherSuites(long ssl, String cipherList) throws Exception; + + /** + * Set the TLSv1.3 cipher suites available for negotiation the in TLS handshake. + *

      + * This uses a colon-separated list of TLSv1.3 cipher suite names in preference order. + * + * @param ssl The SSL instance (SSL *) + * @param cipherSuites An OpenSSL cipher suite list. + * * @return true if the operation was successful + * * @throws Exception An error occurred */ - public static native boolean setCipherSuites(long ssl, String ciphers) - throws Exception; + public static native boolean setCipherSuitesEx(long ssl, String cipherSuites) throws Exception; /** * Returns the ID of the session as byte array representation. * * @param ssl the SSL instance (SSL *) + * * @return the session as byte array representation obtained via SSL_SESSION_get_id. */ public static native byte[] getSessionId(long ssl); diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/jni/SSLConf.java tomcat10-10.1.52/java/org/apache/tomcat/jni/SSLConf.java --- tomcat10-10.1.40/java/org/apache/tomcat/jni/SSLConf.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/jni/SSLConf.java 2026-01-23 19:33:36.000000000 +0000 @@ -21,10 +21,10 @@ /** * Create a new SSL_CONF context. * - * @param pool The pool to use. - * @param flags The SSL_CONF flags to use. It can be any combination of - * the following: - *

      +     * @param pool  The pool to use.
      +     * @param flags The SSL_CONF flags to use. It can be any combination of the following:
      +     *
      +     *                  
            * {@link SSL#SSL_CONF_FLAG_CMDLINE}
            * {@link SSL#SSL_CONF_FLAG_FILE}
            * {@link SSL#SSL_CONF_FLAG_CLIENT}
      @@ -33,13 +33,13 @@
            * {@link SSL#SSL_CONF_FLAG_CERTIFICATE}
            * 
      * - * @return The Java representation of a pointer to the newly created - * SSL_CONF Context + * @return The Java representation of a pointer to the newly created SSL_CONF Context * * @throws Exception If the SSL_CONF context could not be created * * @see OpenSSL SSL_CONF_CTX_new - * @see OpenSSL SSL_CONF_CTX_set_flags + * @see OpenSSL + * SSL_CONF_CTX_set_flags */ public static native long make(long pool, int flags) throws Exception; @@ -55,13 +55,12 @@ /** * Check a command with an SSL_CONF context. * - * @param cctx SSL_CONF context to use. - * @param name command name. + * @param cctx SSL_CONF context to use. + * @param name command name. * @param value command value. * - * @return The result of the check based on the {@code SSL_CONF_cmd_value_type} - * call. Unknown types will result in an exception, as well as - * file and directory types with invalid file or directory names. + * @return The result of the check based on the {@code SSL_CONF_cmd_value_type} call. Unknown types will result in + * an exception, as well as file and directory types with invalid file or directory names. * * @throws Exception If the check fails. * @@ -70,22 +69,22 @@ public static native int check(long cctx, String name, String value) throws Exception; /** - * Assign an SSL context to an SSL_CONF context. - * All following calls to {@link #apply(long, String, String)} will be + * Assign an SSL context to an SSL_CONF context. All following calls to {@link #apply(long, String, String)} will be * applied to this SSL context. * * @param cctx SSL_CONF context to use. - * @param ctx SSL context to assign to the given SSL_CONF context. + * @param ctx SSL context to assign to the given SSL_CONF context. * - * @see OpenSSL SSL_CONF_CTX_set_ssl_ctx + * @see OpenSSL + * SSL_CONF_CTX_set_ssl_ctx */ public static native void assign(long cctx, long ctx); /** * Apply a command to an SSL_CONF context. * - * @param cctx SSL_CONF context to use. - * @param name command name. + * @param cctx SSL_CONF context to use. + * @param name command name. * @param value command value. * * @return The result of the native {@code SSL_CONF_cmd} call @@ -103,7 +102,8 @@ * * @return The result of the native {@code SSL_CONF_CTX_finish} call * - * @see OpenSSL SSL_CONF_CTX_finish + * @see OpenSSL + * SSL_CONF_CTX_finish */ public static native int finish(long cctx); diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/jni/SSLContext.java tomcat10-10.1.52/java/org/apache/tomcat/jni/SSLContext.java --- tomcat10-10.1.40/java/org/apache/tomcat/jni/SSLContext.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/jni/SSLContext.java 2026-01-23 19:33:36.000000000 +0000 @@ -22,16 +22,15 @@ public final class SSLContext { - public static final byte[] DEFAULT_SESSION_ID_CONTEXT = - new byte[] { 'd', 'e', 'f', 'a', 'u', 'l', 't' }; + public static final byte[] DEFAULT_SESSION_ID_CONTEXT = new byte[] { 'd', 'e', 'f', 'a', 'u', 'l', 't' }; /** * Create a new SSL context. * - * @param pool The pool to use. - * @param protocol The SSL protocol to use. It can be any combination of - * the following: - *
      +     * @param pool     The pool to use.
      +     * @param protocol The SSL protocol to use. It can be any combination of the following:
      +     *
      +     *                     
            * {@link SSL#SSL_PROTOCOL_SSLV2}
            * {@link SSL#SSL_PROTOCOL_SSLV3}
            * {@link SSL#SSL_PROTOCOL_TLSV1}
      @@ -40,15 +39,16 @@
            * {@link SSL#SSL_PROTOCOL_TLSV1_3}
            * {@link SSL#SSL_PROTOCOL_ALL} ( == all TLS versions, no SSL)
            * 
      - * @param mode SSL mode to use - *
      +     *
      +     * @param mode     SSL mode to use
      +     *
      +     *                     
            * SSL_MODE_CLIENT
            * SSL_MODE_SERVER
            * SSL_MODE_COMBINED
      -     * 
      + *
      * - * @return The Java representation of a pointer to the newly created SSL - * Context + * @return The Java representation of a pointer to the newly created SSL Context * * @throws Exception If the SSL Context could not be created */ @@ -56,149 +56,152 @@ /** * Free the resources used by the Context + * * @param ctx Server or Client context to free. + * * @return APR Status code. */ public static native int free(long ctx); /** * Set OpenSSL Option. - * @param ctx Server or Client context to use. - * @param options See SSL.SSL_OP_* for option flags. + * + * @param ctx Server or Client context to use. + * @param options See SSL.SSL_OP_* for option flags. */ public static native void setOptions(long ctx, int options); /** * Get OpenSSL Option. + * * @param ctx Server or Client context to use. - * @return options See SSL.SSL_OP_* for option flags. + * + * @return options See SSL.SSL_OP_* for option flags. */ public static native int getOptions(long ctx); /** * Clears OpenSSL Options. - * @param ctx Server or Client context to use. - * @param options See SSL.SSL_OP_* for option flags. + * + * @param ctx Server or Client context to use. + * @param options See SSL.SSL_OP_* for option flags. */ public static native void clearOptions(long ctx, int options); /** * Returns all cipher suites that are enabled for negotiation in an SSL handshake. + * * @param ctx Server or Client context to use. + * * @return ciphers */ public static native String[] getCiphers(long ctx); /** - * Cipher Suite available for negotiation in SSL handshake. - *
      - * This complex directive uses a colon-separated cipher-spec string consisting - * of OpenSSL cipher specifications to configure the Cipher Suite the client - * is permitted to negotiate in the SSL handshake phase. Notice that this - * directive can be used both in per-server and per-directory context. - * In per-server context it applies to the standard SSL handshake when a - * connection is established. In per-directory context it forces an SSL - * renegotiation with the reconfigured Cipher Suite after the HTTP request - * was read but before the HTTP response is sent. - * @param ctx Server or Client context to use. - * @param ciphers An OpenSSL cipher specification. + * Set the TLSv1.2 and below ciphers available for negotiation the in TLS handshake. + *

      + * This complex directive uses a colon-separated cipher-spec string consisting of OpenSSL cipher specifications to + * configure the ciphers the client is permitted to negotiate in the TLS handshake phase. + * + * @param ctx Server or Client context to use. + * @param cipherList An OpenSSL cipher specification. + * * @return true if the operation was successful + * * @throws Exception An error occurred */ - public static native boolean setCipherSuite(long ctx, String ciphers) - throws Exception; + public static native boolean setCipherSuite(long ctx, String cipherList) throws Exception; /** - * Set File of concatenated PEM-encoded CA CRLs or - * directory of PEM-encoded CA Certificates for Client Auth - *
      - * This directive sets the all-in-one file where you can assemble the - * Certificate Revocation Lists (CRL) of Certification Authorities (CA) - * whose clients you deal with. These are used for Client Authentication. - * Such a file is simply the concatenation of the various PEM-encoded CRL - * files, in order of preference. - *
      - * The files in this directory have to be PEM-encoded and are accessed through - * hash filenames. So usually you can't just place the Certificate files there: - * you also have to create symbolic links named hash-value.N. And you should - * always make sure this directory contains the appropriate symbolic links. - * Use the Makefile which comes with mod_ssl to accomplish this task. - * @param ctx Server or Client context to use. + * Set the TLSv1.3 cipher suites available for negotiation the in TLS handshake. + *

      + * This uses a colon-separated list of TLSv1.3 cipher suite names in preference order. + * + * @param ctx Server or Client context to use. + * @param cipherSuites An OpenSSL cipher suite list. + * + * @return true if the operation was successful + * + * @throws Exception An error occurred + */ + public static native boolean setCipherSuitesEx(long ctx, String cipherSuites) throws Exception; + + /** + * Set File of concatenated PEM-encoded CA CRLs or directory of PEM-encoded CA Certificates for Client Auth
      + * This directive sets the all-in-one file where you can assemble the Certificate Revocation Lists (CRL) of + * Certification Authorities (CA) whose clients you deal with. These are used for Client Authentication. Such a file + * is simply the concatenation of the various PEM-encoded CRL files, in order of preference.
      + * The files in this directory have to be PEM-encoded and are accessed through hash filenames. So usually you can't + * just place the Certificate files there: you also have to create symbolic links named hash-value.N. And you should + * always make sure this directory contains the appropriate symbolic links. Use the Makefile which comes with + * mod_ssl to accomplish this task. + * + * @param ctx Server or Client context to use. * @param file File of concatenated PEM-encoded CA CRLs for Client Auth. * @param path Directory of PEM-encoded CA Certificates for Client Auth. + * * @return true if the operation was successful + * * @throws Exception An error occurred */ - public static native boolean setCARevocation(long ctx, String file, - String path) - throws Exception; + public static native boolean setCARevocation(long ctx, String file, String path) throws Exception; /** - * Set File of PEM-encoded Server CA Certificates - *
      - * This directive sets the optional all-in-one file where you can assemble the - * certificates of Certification Authorities (CA) which form the certificate - * chain of the server certificate. This starts with the issuing CA certificate - * of the server certificate and can range up to the root CA certificate. - * Such a file is simply the concatenation of the various PEM-encoded CA - * Certificate files, usually in certificate chain order. - *
      - * But be careful: Providing the certificate chain works only if you are using - * a single (either RSA or DSA) based server certificate. If you are using a - * coupled RSA+DSA certificate pair, this will work only if actually both - * certificates use the same certificate chain. Else the browsers will be - * confused in this situation. - * @param ctx Server or Client context to use. - * @param file File of PEM-encoded Server CA Certificates. - * @param skipfirst Skip first certificate if chain file is inside - * certificate file. + * Set File of PEM-encoded Server CA Certificates
      + * This directive sets the optional all-in-one file where you can assemble the certificates of Certification + * Authorities (CA) which form the certificate chain of the server certificate. This starts with the issuing CA + * certificate of the server certificate and can range up to the root CA certificate. Such a file is simply the + * concatenation of the various PEM-encoded CA Certificate files, usually in certificate chain order.
      + * But be careful: Providing the certificate chain works only if you are using a single (either RSA or DSA) based + * server certificate. If you are using a coupled RSA+DSA certificate pair, this will work only if actually both + * certificates use the same certificate chain. Else the browsers will be confused in this situation. + * + * @param ctx Server or Client context to use. + * @param file File of PEM-encoded Server CA Certificates. + * @param skipfirst Skip first certificate if chain file is inside certificate file. + * * @return true if the operation was successful */ - public static native boolean setCertificateChainFile(long ctx, String file, - boolean skipfirst); + public static native boolean setCertificateChainFile(long ctx, String file, boolean skipfirst); /** - * Set Certificate - *
      - * Point setCertificateFile at a PEM encoded certificate. If - * the certificate is encrypted, then you will be prompted for a - * pass phrase. Note that a kill -HUP will prompt again. A test - * certificate can be generated with 'make certificate' under - * built time. Keep in mind that if you've both a RSA and a DSA - * certificate you can configure both in parallel (to also allow - * the use of DSA ciphers, etc.) - *
      - * If the key is not combined with the certificate, use key param - * to point at the key file. Keep in mind that if - * you've both a RSA and a DSA private key you can configure - * both in parallel (to also allow the use of DSA ciphers, etc.) - * @param ctx Server or Client context to use. - * @param cert Certificate file. - * @param key Private Key file to use if not in cert. - * @param password Certificate password. If null and certificate - * is encrypted, password prompt will be displayed. - * @param idx Certificate index SSL_AIDX_RSA or SSL_AIDX_DSA. + * Set Certificate
      + * Point setCertificateFile at a PEM encoded certificate. If the certificate is encrypted, then you will be prompted + * for a pass phrase. Note that a kill -HUP will prompt again. A test certificate can be generated with 'make + * certificate' under built time. Keep in mind that if you've both a RSA and a DSA certificate you can configure + * both in parallel (to also allow the use of DSA ciphers, etc.)
      + * If the key is not combined with the certificate, use key param to point at the key file. Keep in mind that if + * you've both a RSA and a DSA private key you can configure both in parallel (to also allow the use of DSA ciphers, + * etc.) + * + * @param ctx Server or Client context to use. + * @param cert Certificate file. + * @param key Private Key file to use if not in cert. + * @param password Certificate password. If null and certificate is encrypted, password prompt will be displayed. + * @param idx Certificate index SSL_AIDX_RSA or SSL_AIDX_DSA. + * * @return true if the operation was successful + * * @throws Exception An error occurred */ - public static native boolean setCertificate(long ctx, String cert, - String key, String password, - int idx) - throws Exception; + public static native boolean setCertificate(long ctx, String cert, String key, String password, int idx) + throws Exception; /** - * Set the size of the internal session cache. - * http://www.openssl.org/docs/ssl/SSL_CTX_sess_set_cache_size.html - * @param ctx Server or Client context to use. + * Set the size of the internal session cache. http://www.openssl.org/docs/ssl/SSL_CTX_sess_set_cache_size.html + * + * @param ctx Server or Client context to use. * @param size The cache size + * * @return the value set */ public static native long setSessionCacheSize(long ctx, long size); /** - * Get the size of the internal session cache. - * http://www.openssl.org/docs/ssl/SSL_CTX_sess_get_cache_size.html + * Get the size of the internal session cache. http://www.openssl.org/docs/ssl/SSL_CTX_sess_get_cache_size.html + * * @param ctx Server or Client context to use. + * * @return the size */ public static native long getSessionCacheSize(long ctx); @@ -206,8 +209,10 @@ /** * Set the timeout for the internal session cache in seconds. * http://www.openssl.org/docs/ssl/SSL_CTX_set_timeout.html - * @param ctx Server or Client context to use. + * + * @param ctx Server or Client context to use. * @param timeoutSeconds Timeout value + * * @return the value set */ public static native long setSessionCacheTimeout(long ctx, long timeoutSeconds); @@ -215,90 +220,98 @@ /** * Get the timeout for the internal session cache in seconds. * http://www.openssl.org/docs/ssl/SSL_CTX_set_timeout.html + * * @param ctx Server or Client context to use. + * * @return the timeout */ public static native long getSessionCacheTimeout(long ctx); /** * Set the mode of the internal session cache and return the previous used mode. - * @param ctx Server or Client context to use. + * + * @param ctx Server or Client context to use. * @param mode The mode to set + * * @return the value set */ public static native long setSessionCacheMode(long ctx, long mode); /** * Get the mode of the current used internal session cache. + * * @param ctx Server or Client context to use. + * * @return the value set */ public static native long getSessionCacheMode(long ctx); /* - * Session resumption statistics methods. - * http://www.openssl.org/docs/ssl/SSL_CTX_sess_number.html + * Session resumption statistics methods. http://www.openssl.org/docs/ssl/SSL_CTX_sess_number.html */ public static native long sessionAccept(long ctx); + public static native long sessionAcceptGood(long ctx); + public static native long sessionAcceptRenegotiate(long ctx); + public static native long sessionCacheFull(long ctx); + public static native long sessionCbHits(long ctx); + public static native long sessionConnect(long ctx); + public static native long sessionConnectGood(long ctx); + public static native long sessionConnectRenegotiate(long ctx); + public static native long sessionHits(long ctx); + public static native long sessionMisses(long ctx); + public static native long sessionNumber(long ctx); + public static native long sessionTimeouts(long ctx); /** * Set TLS session keys. This allows us to share keys across TFEs. - * @param ctx Server or Client context to use. + * + * @param ctx Server or Client context to use. * @param keys Some session keys */ public static native void setSessionTicketKeys(long ctx, byte[] keys); /** - * Set File and Directory of concatenated PEM-encoded CA Certificates - * for Client Auth - *
      - * This directive sets the all-in-one file where you can assemble the - * Certificates of Certification Authorities (CA) whose clients you deal with. - * These are used for Client Authentication. Such a file is simply the - * concatenation of the various PEM-encoded Certificate files, in order of - * preference. This can be used alternatively and/or additionally to - * path. - *
      - * The files in this directory have to be PEM-encoded and are accessed through - * hash filenames. So usually you can't just place the Certificate files there: - * you also have to create symbolic links named hash-value.N. And you should - * always make sure this directory contains the appropriate symbolic links. - * Use the Makefile which comes with mod_ssl to accomplish this task. - * @param ctx Server or Client context to use. - * @param file File of concatenated PEM-encoded CA Certificates for - * Client Auth. + * Set File and Directory of concatenated PEM-encoded CA Certificates for Client Auth
      + * This directive sets the all-in-one file where you can assemble the Certificates of Certification Authorities (CA) + * whose clients you deal with. These are used for Client Authentication. Such a file is simply the concatenation of + * the various PEM-encoded Certificate files, in order of preference. This can be used alternatively and/or + * additionally to path.
      + * The files in this directory have to be PEM-encoded and are accessed through hash filenames. So usually you can't + * just place the Certificate files there: you also have to create symbolic links named hash-value.N. And you should + * always make sure this directory contains the appropriate symbolic links. Use the Makefile which comes with + * mod_ssl to accomplish this task. + * + * @param ctx Server or Client context to use. + * @param file File of concatenated PEM-encoded CA Certificates for Client Auth. * @param path Directory of PEM-encoded CA Certificates for Client Auth. + * * @return true if the operation was successful + * * @throws Exception An error occurred */ - public static native boolean setCACertificate(long ctx, String file, - String path) - throws Exception; + public static native boolean setCACertificate(long ctx, String file, String path) throws Exception; /** - * Set Type of Client Certificate verification and Maximum depth of CA Certificates - * in Client Certificate verification. - *
      - * This directive sets the Certificate verification level for the Client - * Authentication. Notice that this directive can be used both in per-server - * and per-directory context. In per-server context it applies to the client - * authentication process used in the standard SSL handshake when a connection - * is established. In per-directory context it forces an SSL renegotiation with - * the reconfigured client verification level after the HTTP request was read - * but before the HTTP response is sent. - *
      + * Set Type of Client Certificate verification and Maximum depth of CA Certificates in Client Certificate + * verification.
      + * This directive sets the Certificate verification level for the Client Authentication. Notice that this directive + * can be used both in per-server and per-directory context. In per-server context it applies to the client + * authentication process used in the standard SSL handshake when a connection is established. In per-directory + * context it forces an SSL renegotiation with the reconfigured client verification level after the HTTP request was + * read but before the HTTP response is sent.
      * The following levels are available for level: + * *

            * SSL_CVERIFY_NONE           - No client Certificate is required at all
            * SSL_CVERIFY_OPTIONAL       - The client may present a valid Certificate
      @@ -306,34 +319,30 @@
            * SSL_CVERIFY_OPTIONAL_NO_CA - The client may present a valid Certificate
            *                              but it need not to be (successfully) verifiable
            * 
      + * *
      - * The depth actually is the maximum number of intermediate certificate issuers, - * i.e. the number of CA certificates which are max allowed to be followed while - * verifying the client certificate. A depth of 0 means that self-signed client - * certificates are accepted only, the default depth of 1 means the client - * certificate can be self-signed or has to be signed by a CA which is directly - * known to the server (i.e. the CA's certificate is under + * The depth actually is the maximum number of intermediate certificate issuers, i.e. the number of CA certificates + * which are max allowed to be followed while verifying the client certificate. A depth of 0 means that self-signed + * client certificates are accepted only, the default depth of 1 means the client certificate can be self-signed or + * has to be signed by a CA which is directly known to the server (i.e. the CA's certificate is under * setCACertificatePath), etc. - * @param ctx Server or Client context to use. + * + * @param ctx Server or Client context to use. * @param level Type of Client Certificate verification. - * @param depth Maximum depth of CA Certificates in Client Certificate - * verification. + * @param depth Maximum depth of CA Certificates in Client Certificate verification. */ public static native void setVerify(long ctx, int level, int depth); /** - * When tc-native encounters a SNI extension in the TLS handshake it will - * call this method to determine which OpenSSL SSLContext to use for the - * connection. - * - * @param currentCtx The OpenSSL SSLContext that the handshake started to - * use. This will be the default OpenSSL SSLContext for - * the endpoint associated with the socket. - * @param sniHostName The host name requested by the client - * - * @return The Java representation of the pointer to the OpenSSL SSLContext - * to use for the given host or zero if no SSLContext could be - * identified + * When tc-native encounters a SNI extension in the TLS handshake it will call this method to determine which + * OpenSSL SSLContext to use for the connection. + * + * @param currentCtx The OpenSSL SSLContext that the handshake started to use. This will be the default OpenSSL + * SSLContext for the endpoint associated with the socket. + * @param sniHostName The host name requested by the client + * + * @return The Java representation of the pointer to the OpenSSL SSLContext to use for the given host or zero if no + * SSLContext could be identified */ public static long sniCallBack(long currentCtx, String sniHostName) { SNICallBack sniCallBack = sniCallBacks.get(Long.valueOf(currentCtx)); @@ -347,50 +356,47 @@ } /** - * A map of default SSL Contexts to SNICallBack instances (in Tomcat these - * are instances of AprEndpoint) that will be used to determine the SSL - * Context to use bases on the SNI host name. It is structured this way - * since a Tomcat instance may have several TLS enabled endpoints that each - * have different SSL Context mappings for the same host name. + * A map of default SSL Contexts to SNICallBack instances (in Tomcat these are instances of AprEndpoint) that will + * be used to determine the SSL Context to use bases on the SNI host name. It is structured this way since a Tomcat + * instance may have several TLS enabled endpoints that each have different SSL Context mappings for the same host + * name. */ private static final Map sniCallBacks = new ConcurrentHashMap<>(); /** - * Interface implemented by components that will receive the call back to - * select an OpenSSL SSLContext based on the host name requested by the - * client. + * Interface implemented by components that will receive the call back to select an OpenSSL SSLContext based on the + * host name requested by the client. */ public interface SNICallBack { /** - * This callback is made during the TLS handshake when the client uses - * the SNI extension to request a specific TLS host. + * This callback is made during the TLS handshake when the client uses the SNI extension to request a specific + * TLS host. * - * @param sniHostName The host name requested by the client - must be in - * lower case + * @param sniHostName The host name requested by the client - must be in lower case * - * @return The Java representation of the pointer to the OpenSSL - * SSLContext to use for the given host or zero if no SSLContext - * could be identified + * @return The Java representation of the pointer to the OpenSSL SSLContext to use for the given host or zero if + * no SSLContext could be identified */ long getSslContext(String sniHostName); } /** - * Allow to hook {@link CertificateVerifier} into the handshake processing. - * This will call {@code SSL_CTX_set_cert_verify_callback} and so replace the default verification - * callback used by openssl - * @param ctx Server or Client context to use. + * Allow to hook {@link CertificateVerifier} into the handshake processing. This will call + * {@code SSL_CTX_set_cert_verify_callback} and so replace the default verification callback used by openssl + * + * @param ctx Server or Client context to use. * @param verifier the verifier to call during handshake. */ public static native void setCertVerifyCallback(long ctx, CertificateVerifier verifier); /** * Set application layer protocol for application layer protocol negotiation extension - * @param ctx Server context to use. - * @param alpnProtos protocols in priority order - * @param selectorFailureBehavior see {@link SSL#SSL_SELECTOR_FAILURE_NO_ADVERTISE} - * and {@link SSL#SSL_SELECTOR_FAILURE_CHOOSE_MY_LAST_PROTOCOL} + * + * @param ctx Server context to use. + * @param alpnProtos protocols in priority order + * @param selectorFailureBehavior see {@link SSL#SSL_SELECTOR_FAILURE_NO_ADVERTISE} and + * {@link SSL#SSL_SELECTOR_FAILURE_CHOOSE_MY_LAST_PROTOCOL} */ public static native void setAlpnProtos(long ctx, String[] alpnProtos, int selectorFailureBehavior); @@ -398,42 +404,45 @@ * Set the context within which session be reused (server side only) * http://www.openssl.org/docs/ssl/SSL_CTX_set_session_id_context.html * - * @param ctx Server context to use. - * @param sidCtx can be any kind of binary data, it is therefore possible to use e.g. the name - * of the application and/or the hostname and/or service name + * @param ctx Server context to use. + * @param sidCtx can be any kind of binary data, it is therefore possible to use e.g. the name of the application + * and/or the hostname and/or service name + * * @return {@code true} if success, {@code false} otherwise. */ public static native boolean setSessionIdContext(long ctx, byte[] sidCtx); /** - * Set CertificateRaw - *
      + * Set CertificateRaw
      * Use keystore a certificate and key to fill the BIOP - * @param ctx Server or Client context to use. - * @param cert Byte array with the certificate in DER encoding. - * @param key Byte array with the Private Key file in PEM format. + * + * @param ctx Server or Client context to use. + * @param cert Byte array with the certificate in DER encoding. + * @param key Byte array with the Private Key file in PEM format. * @param sslAidxRsa Certificate index SSL_AIDX_RSA or SSL_AIDX_DSA. + * * @return {@code true} if success, {@code false} otherwise. */ public static native boolean setCertificateRaw(long ctx, byte[] cert, byte[] key, int sslAidxRsa); /** - * Add a certificate to the certificate chain. Certs should be added in - * order starting with the issuer of the host certs and working up the - * certificate chain to the CA. - * - *
      + * Add a certificate to the certificate chain. Certs should be added in order starting with the issuer of the host + * certs and working up the certificate chain to the CA.
      * Use keystore a certificate chain to fill the BIOP - * @param ctx Server or Client context to use. + * + * @param ctx Server or Client context to use. * @param cert Byte array with the certificate in DER encoding. + * * @return {@code true} if success, {@code false} otherwise. */ public static native boolean addChainCertificateRaw(long ctx, byte[] cert); /** * Add a CA certificate we accept as issuer for peer certs - * @param ctx Server or Client context to use. + * + * @param ctx Server or Client context to use. * @param cert Byte array with the certificate in DER encoding. + * * @return {@code true} if success, {@code false} otherwise. */ public static native boolean addClientCACertificateRaw(long ctx, byte[] cert); diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/jni/Sockaddr.java tomcat10-10.1.52/java/org/apache/tomcat/jni/Sockaddr.java --- tomcat10-10.1.40/java/org/apache/tomcat/jni/Sockaddr.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/jni/Sockaddr.java 2026-01-23 19:33:36.000000000 +0000 @@ -17,10 +17,9 @@ package org.apache.tomcat.jni; /** - * Tomcat Native 1.2.33 and earlier won't initialise unless this class is - * present. This dummy class ensures initialisation gets as far as being able to - * check the version of the Tomcat Native library and reporting a version error - * if 1.2.33 or earlier is present. + * Tomcat Native 1.2.33 and earlier won't initialise unless this class is present. This dummy class ensures + * initialisation gets as far as being able to check the version of the Tomcat Native library and reporting a version + * error if 1.2.33 or earlier is present. */ public class Sockaddr { diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/Diagnostics.java tomcat10-10.1.52/java/org/apache/tomcat/util/Diagnostics.java --- tomcat10-10.1.40/java/org/apache/tomcat/util/Diagnostics.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/Diagnostics.java 2026-01-23 19:33:36.000000000 +0000 @@ -76,34 +76,25 @@ private static final Log log = LogFactory.getLog(Diagnostics.class); - private static final SimpleDateFormat timeformat = - new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS"); + private static final SimpleDateFormat timeformat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS"); /* Some platform MBeans */ - private static final ClassLoadingMXBean classLoadingMXBean = - ManagementFactory.getClassLoadingMXBean(); - private static final CompilationMXBean compilationMXBean = - ManagementFactory.getCompilationMXBean(); - private static final OperatingSystemMXBean operatingSystemMXBean = - ManagementFactory.getOperatingSystemMXBean(); - private static final RuntimeMXBean runtimeMXBean = - ManagementFactory.getRuntimeMXBean(); - private static final ThreadMXBean threadMXBean = - ManagementFactory.getThreadMXBean(); + private static final ClassLoadingMXBean classLoadingMXBean = ManagementFactory.getClassLoadingMXBean(); + private static final CompilationMXBean compilationMXBean = ManagementFactory.getCompilationMXBean(); + private static final OperatingSystemMXBean operatingSystemMXBean = ManagementFactory.getOperatingSystemMXBean(); + private static final RuntimeMXBean runtimeMXBean = ManagementFactory.getRuntimeMXBean(); + private static final ThreadMXBean threadMXBean = ManagementFactory.getThreadMXBean(); // XXX Not sure whether the following MBeans should better // be retrieved on demand, i.e. whether they can change // dynamically in the MBeanServer. private static final PlatformLoggingMXBean loggingMXBean = - ManagementFactory.getPlatformMXBean(PlatformLoggingMXBean.class); - private static final MemoryMXBean memoryMXBean = - ManagementFactory.getMemoryMXBean(); + ManagementFactory.getPlatformMXBean(PlatformLoggingMXBean.class); + private static final MemoryMXBean memoryMXBean = ManagementFactory.getMemoryMXBean(); private static final List garbageCollectorMXBeans = - ManagementFactory.getGarbageCollectorMXBeans(); - private static final List memoryManagerMXBeans = - ManagementFactory.getMemoryManagerMXBeans(); - private static final List memoryPoolMXBeans = - ManagementFactory.getMemoryPoolMXBeans(); + ManagementFactory.getGarbageCollectorMXBeans(); + private static final List memoryManagerMXBeans = ManagementFactory.getMemoryManagerMXBeans(); + private static final List memoryPoolMXBeans = ManagementFactory.getMemoryPoolMXBeans(); /** * Check whether thread contention monitoring is enabled. @@ -146,8 +137,8 @@ threadMXBean.setThreadCpuTimeEnabled(enable); boolean checkValue = threadMXBean.isThreadCpuTimeEnabled(); if (enable != checkValue) { - log.error(sm.getString("diagnostics.setPropertyFail", "threadCpuTimeEnabled", - Boolean.valueOf(enable), Boolean.valueOf(checkValue))); + log.error(sm.getString("diagnostics.setPropertyFail", "threadCpuTimeEnabled", Boolean.valueOf(enable), + Boolean.valueOf(checkValue))); } } @@ -167,8 +158,8 @@ classLoadingMXBean.setVerbose(verbose); boolean checkValue = classLoadingMXBean.isVerbose(); if (verbose != checkValue) { - log.error(sm.getString("diagnostics.setPropertyFail", "verboseClassLoading", - Boolean.valueOf(verbose), Boolean.valueOf(checkValue))); + log.error(sm.getString("diagnostics.setPropertyFail", "verboseClassLoading", Boolean.valueOf(verbose), + Boolean.valueOf(checkValue))); } } @@ -176,15 +167,14 @@ * Set logger level * * @param loggerName the name of the logger - * @param levelName the level to set + * @param levelName the level to set */ public static void setLoggerLevel(String loggerName, String levelName) { loggingMXBean.setLoggerLevel(loggerName, levelName); String checkValue = loggingMXBean.getLoggerLevel(loggerName); if (!checkValue.equals(levelName)) { String propertyName = "loggerLevel[" + loggerName + "]"; - log.error(sm.getString("diagnostics.setPropertyFail", propertyName, - levelName, checkValue)); + log.error(sm.getString("diagnostics.setPropertyFail", propertyName, levelName, checkValue)); } } @@ -197,8 +187,8 @@ memoryMXBean.setVerbose(verbose); boolean checkValue = memoryMXBean.isVerbose(); if (verbose != checkValue) { - log.error(sm.getString("diagnostics.setPropertyFail", "verboseGarbageCollection", - Boolean.valueOf(verbose), Boolean.valueOf(checkValue))); + log.error(sm.getString("diagnostics.setPropertyFail", "verboseGarbageCollection", Boolean.valueOf(verbose), + Boolean.valueOf(checkValue))); } } @@ -215,7 +205,7 @@ * @param name name of the MemoryPoolMXBean or "all" */ public static void resetPeakUsage(String name) { - for (MemoryPoolMXBean mbean: memoryPoolMXBeans) { + for (MemoryPoolMXBean mbean : memoryPoolMXBeans) { if (name.equals("all") || name.equals(mbean.getName())) { mbean.resetPeakUsage(); } @@ -225,12 +215,13 @@ /** * Set usage threshold in MemoryPoolMXBean * - * @param name name of the MemoryPoolMXBean + * @param name name of the MemoryPoolMXBean * @param threshold the threshold to set + * * @return true if setting the threshold succeeded */ public static boolean setUsageThreshold(String name, long threshold) { - for (MemoryPoolMXBean mbean: memoryPoolMXBeans) { + for (MemoryPoolMXBean mbean : memoryPoolMXBeans) { if (name.equals(mbean.getName())) { try { mbean.setUsageThreshold(threshold); @@ -247,12 +238,13 @@ /** * Set collection usage threshold in MemoryPoolMXBean * - * @param name name of the MemoryPoolMXBean + * @param name name of the MemoryPoolMXBean * @param threshold the collection threshold to set + * * @return true if setting the threshold succeeded */ public static boolean setCollectionUsageThreshold(String name, long threshold) { - for (MemoryPoolMXBean mbean: memoryPoolMXBeans) { + for (MemoryPoolMXBean mbean : memoryPoolMXBeans) { if (name.equals(mbean.getName())) { try { mbean.setCollectionUsageThreshold(threshold); @@ -270,6 +262,7 @@ * Formats the thread dump header for one thread. * * @param ti the ThreadInfo describing the thread + * * @return the formatted thread dump header */ private static String getThreadDumpHeader(ThreadInfo ti) { @@ -297,6 +290,7 @@ * Formats the thread dump for one thread. * * @param ti the ThreadInfo describing the thread + * * @return the formatted thread dump */ private static String getThreadDump(ThreadInfo ti) { @@ -318,14 +312,15 @@ if (ti.getLockName() != null) { sb.append(INDENT2 + "- waiting on (a ").append(ti.getLockName()).append(")"); if (ti.getLockOwnerName() != null) { - sb.append(" owned by ").append(ti.getLockOwnerName()).append(" Id=").append(ti.getLockOwnerId()); + sb.append(" owned by ").append(ti.getLockOwnerName()).append(" Id=") + .append(ti.getLockOwnerId()); } sb.append(CRLF); } start = false; } if (monitorDepths[i] != null) { - MonitorInfo mi = (MonitorInfo)monitorDepths[i]; + MonitorInfo mi = (MonitorInfo) monitorDepths[i]; sb.append(INDENT2 + "- locked (a ").append(mi.toString()).append(")").append(" index "); sb.append(mi.getLockedStackDepth()).append(" frame ").append(mi.getLockedStackFrame().toString()); sb.append(CRLF); @@ -339,6 +334,7 @@ * Formats the thread dump for a list of threads. * * @param tinfos the ThreadInfo array describing the thread list + * * @return the formatted thread dump */ private static String getThreadDump(ThreadInfo[] tinfos) { @@ -351,17 +347,14 @@ } /** - * Check if any threads are deadlocked. If any, print - * the thread dump for those threads. + * Check if any threads are deadlocked. If any, print the thread dump for those threads. * - * @return a deadlock message and the formatted thread dump - * of the deadlocked threads + * @return a deadlock message and the formatted thread dump of the deadlocked threads */ public static String findDeadlock() { long[] ids = threadMXBean.findDeadlockedThreads(); if (ids != null) { - ThreadInfo[] tinfos = threadMXBean.getThreadInfo(threadMXBean.findDeadlockedThreads(), - true, true); + ThreadInfo[] tinfos = threadMXBean.getThreadInfo(threadMXBean.findDeadlockedThreads(), true, true); if (tinfos != null) { return sm.getString("diagnostics.deadlockFound") + CRLF + getThreadDump(tinfos); } @@ -370,8 +363,7 @@ } /** - * Retrieves a formatted JVM thread dump. - * The default StringManager will be used. + * Retrieves a formatted JVM thread dump. The default StringManager will be used. * * @return the formatted JVM thread dump */ @@ -380,29 +372,27 @@ } /** - * Retrieves a formatted JVM thread dump. - * The given list of locales will be used - * to retrieve a StringManager. + * Retrieves a formatted JVM thread dump. The given list of locales will be used to retrieve a StringManager. * * @param requestedLocales list of locales to use + * * @return the formatted JVM thread dump */ public static String getThreadDump(Enumeration requestedLocales) { - return getThreadDump( - StringManager.getManager(PACKAGE, requestedLocales)); + return getThreadDump(StringManager.getManager(PACKAGE, requestedLocales)); } /** - * Retrieve a JVM thread dump formatted - * using the given StringManager. + * Retrieve a JVM thread dump formatted using the given StringManager. * * @param requestedSm the StringManager to use + * * @return the formatted JVM thread dump */ public static String getThreadDump(StringManager requestedSm) { StringBuilder sb = new StringBuilder(); - synchronized(timeformat) { + synchronized (timeformat) { sb.append(timeformat.format(new Date())); } sb.append(CRLF); @@ -428,8 +418,10 @@ /** * Format contents of a MemoryUsage object. - * @param name a text prefix used in formatting + * + * @param name a text prefix used in formatting * @param usage the MemoryUsage object to format + * * @return the formatted contents */ private static String formatMemoryUsage(String name, MemoryUsage usage) { @@ -445,8 +437,7 @@ } /** - * Retrieves a formatted JVM information text. - * The default StringManager will be used. + * Retrieves a formatted JVM information text. The default StringManager will be used. * * @return the formatted JVM information text */ @@ -455,11 +446,10 @@ } /** - * Retrieves a formatted JVM information text. - * The given list of locales will be used - * to retrieve a StringManager. + * Retrieves a formatted JVM information text. The given list of locales will be used to retrieve a StringManager. * * @param requestedLocales list of locales to use + * * @return the formatted JVM information text */ public static String getVMInfo(Enumeration requestedLocales) { @@ -467,16 +457,16 @@ } /** - * Retrieve a JVM information text formatted - * using the given StringManager. + * Retrieve a JVM information text formatted using the given StringManager. * * @param requestedSm the StringManager to use + * * @return the formatted JVM information text */ public static String getVMInfo(StringManager requestedSm) { StringBuilder sb = new StringBuilder(); - synchronized(timeformat) { + synchronized (timeformat) { sb.append(timeformat.format(new Date())); } sb.append(CRLF); @@ -501,19 +491,25 @@ sb.append(INDENT1 + "name: ").append(operatingSystemMXBean.getName()).append(CRLF); sb.append(INDENT1 + "version: ").append(operatingSystemMXBean.getVersion()).append(CRLF); sb.append(INDENT1 + "architecture: ").append(operatingSystemMXBean.getArch()).append(CRLF); - sb.append(INDENT1 + "availableProcessors: ").append(operatingSystemMXBean.getAvailableProcessors()).append(CRLF); + sb.append(INDENT1 + "availableProcessors: ").append(operatingSystemMXBean.getAvailableProcessors()) + .append(CRLF); sb.append(INDENT1 + "systemLoadAverage: ").append(operatingSystemMXBean.getSystemLoadAverage()).append(CRLF); sb.append(CRLF); sb.append(requestedSm.getString("diagnostics.vmInfoThreadMxBean")); sb.append(":" + CRLF); - sb.append(INDENT1 + "isCurrentThreadCpuTimeSupported: ").append(threadMXBean.isCurrentThreadCpuTimeSupported()).append(CRLF); + sb.append(INDENT1 + "isCurrentThreadCpuTimeSupported: ").append(threadMXBean.isCurrentThreadCpuTimeSupported()) + .append(CRLF); sb.append(INDENT1 + "isThreadCpuTimeSupported: ").append(threadMXBean.isThreadCpuTimeSupported()).append(CRLF); sb.append(INDENT1 + "isThreadCpuTimeEnabled: ").append(threadMXBean.isThreadCpuTimeEnabled()).append(CRLF); - sb.append(INDENT1 + "isObjectMonitorUsageSupported: ").append(threadMXBean.isObjectMonitorUsageSupported()).append(CRLF); - sb.append(INDENT1 + "isSynchronizerUsageSupported: ").append(threadMXBean.isSynchronizerUsageSupported()).append(CRLF); - sb.append(INDENT1 + "isThreadContentionMonitoringSupported: ").append(threadMXBean.isThreadContentionMonitoringSupported()).append(CRLF); - sb.append(INDENT1 + "isThreadContentionMonitoringEnabled: ").append(threadMXBean.isThreadContentionMonitoringEnabled()).append(CRLF); + sb.append(INDENT1 + "isObjectMonitorUsageSupported: ").append(threadMXBean.isObjectMonitorUsageSupported()) + .append(CRLF); + sb.append(INDENT1 + "isSynchronizerUsageSupported: ").append(threadMXBean.isSynchronizerUsageSupported()) + .append(CRLF); + sb.append(INDENT1 + "isThreadContentionMonitoringSupported: ") + .append(threadMXBean.isThreadContentionMonitoringSupported()).append(CRLF); + sb.append(INDENT1 + "isThreadContentionMonitoringEnabled: ") + .append(threadMXBean.isThreadContentionMonitoringEnabled()).append(CRLF); sb.append(CRLF); sb.append(requestedSm.getString("diagnostics.vmInfoThreadCounts")); @@ -526,7 +522,7 @@ sb.append(requestedSm.getString("diagnostics.vmInfoStartup")); sb.append(":" + CRLF); - for (String arg: runtimeMXBean.getInputArguments()) { + for (String arg : runtimeMXBean.getInputArguments()) { sb.append(INDENT1).append(arg).append(CRLF); } sb.append(CRLF); @@ -552,30 +548,31 @@ sb.append(":" + CRLF); sb.append(INDENT1 + "name: ").append(compilationMXBean.getName()).append(CRLF); sb.append(INDENT1 + "totalCompilationTime: ").append(compilationMXBean.getTotalCompilationTime()).append(CRLF); - sb.append(INDENT1 + "isCompilationTimeMonitoringSupported: ").append(compilationMXBean.isCompilationTimeMonitoringSupported()).append(CRLF); + sb.append(INDENT1 + "isCompilationTimeMonitoringSupported: ") + .append(compilationMXBean.isCompilationTimeMonitoringSupported()).append(CRLF); sb.append(CRLF); - for (MemoryManagerMXBean mbean: memoryManagerMXBeans) { + for (MemoryManagerMXBean mbean : memoryManagerMXBeans) { sb.append(requestedSm.getString("diagnostics.vmInfoMemoryManagers", mbean.getName())); sb.append(":" + CRLF); sb.append(INDENT1 + "isValid: ").append(mbean.isValid()).append(CRLF); sb.append(INDENT1 + "mbean.getMemoryPoolNames: " + CRLF); String[] names = mbean.getMemoryPoolNames(); Arrays.sort(names); - for (String name: names) { + for (String name : names) { sb.append(INDENT2).append(name).append(CRLF); } sb.append(CRLF); } - for (GarbageCollectorMXBean mbean: garbageCollectorMXBeans) { + for (GarbageCollectorMXBean mbean : garbageCollectorMXBeans) { sb.append(requestedSm.getString("diagnostics.vmInfoGarbageCollectors", mbean.getName())); sb.append(":" + CRLF); sb.append(INDENT1 + "isValid: ").append(mbean.isValid()).append(CRLF); sb.append(INDENT1 + "mbean.getMemoryPoolNames: " + CRLF); String[] names = mbean.getMemoryPoolNames(); Arrays.sort(names); - for (String name: names) { + for (String name : names) { sb.append(INDENT2).append(name).append(CRLF); } sb.append(INDENT1 + "getCollectionCount: ").append(mbean.getCollectionCount()).append(CRLF); @@ -586,12 +583,13 @@ sb.append(requestedSm.getString("diagnostics.vmInfoMemory")); sb.append(":" + CRLF); sb.append(INDENT1 + "isVerbose: ").append(memoryMXBean.isVerbose()).append(CRLF); - sb.append(INDENT1 + "getObjectPendingFinalizationCount: ").append(memoryMXBean.getObjectPendingFinalizationCount()).append(CRLF); + sb.append(INDENT1 + "getObjectPendingFinalizationCount: ") + .append(memoryMXBean.getObjectPendingFinalizationCount()).append(CRLF); sb.append(formatMemoryUsage("heap", memoryMXBean.getHeapMemoryUsage())); sb.append(formatMemoryUsage("non-heap", memoryMXBean.getNonHeapMemoryUsage())); sb.append(CRLF); - for (MemoryPoolMXBean mbean: memoryPoolMXBeans) { + for (MemoryPoolMXBean mbean : memoryPoolMXBeans) { sb.append(requestedSm.getString("diagnostics.vmInfoMemoryPools", mbean.getName())); sb.append(":" + CRLF); sb.append(INDENT1 + "isValid: ").append(mbean.isValid()).append(CRLF); @@ -599,7 +597,7 @@ sb.append(INDENT1 + "mbean.getMemoryManagerNames: " + CRLF); String[] names = mbean.getMemoryManagerNames(); Arrays.sort(names); - for (String name: names) { + for (String name : names) { sb.append(INDENT2).append(name).append(CRLF); } sb.append(INDENT1 + "isUsageThresholdSupported: ").append(mbean.isUsageThresholdSupported()).append(CRLF); @@ -608,9 +606,11 @@ } catch (UnsupportedOperationException ex) { // IGNORE } - sb.append(INDENT1 + "isCollectionUsageThresholdSupported: ").append(mbean.isCollectionUsageThresholdSupported()).append(CRLF); + sb.append(INDENT1 + "isCollectionUsageThresholdSupported: ") + .append(mbean.isCollectionUsageThresholdSupported()).append(CRLF); try { - sb.append(INDENT1 + "isCollectionUsageThresholdExceeded: ").append(mbean.isCollectionUsageThresholdExceeded()).append(CRLF); + sb.append(INDENT1 + "isCollectionUsageThresholdExceeded: ") + .append(mbean.isCollectionUsageThresholdExceeded()).append(CRLF); } catch (UnsupportedOperationException ex) { // IGNORE } @@ -625,12 +625,14 @@ // IGNORE } try { - sb.append(INDENT1 + "getCollectionUsageThreshold: ").append(mbean.getCollectionUsageThreshold()).append(CRLF); + sb.append(INDENT1 + "getCollectionUsageThreshold: ").append(mbean.getCollectionUsageThreshold()) + .append(CRLF); } catch (UnsupportedOperationException ex) { // IGNORE } try { - sb.append(INDENT1 + "getCollectionUsageThresholdCount: ").append(mbean.getCollectionUsageThresholdCount()).append(CRLF); + sb.append(INDENT1 + "getCollectionUsageThresholdCount: ") + .append(mbean.getCollectionUsageThresholdCount()).append(CRLF); } catch (UnsupportedOperationException ex) { // IGNORE } @@ -646,7 +648,7 @@ Map props = runtimeMXBean.getSystemProperties(); ArrayList keys = new ArrayList<>(props.keySet()); Collections.sort(keys); - for (String prop: keys) { + for (String prop : keys) { sb.append(INDENT1).append(prop).append(": ").append(props.get(prop)).append(CRLF); } sb.append(CRLF); @@ -655,7 +657,7 @@ sb.append(":" + CRLF); List loggers = loggingMXBean.getLoggerNames(); Collections.sort(loggers); - for (String logger: loggers) { + for (String logger : loggers) { sb.append(INDENT1).append(logger).append(": level=").append(loggingMXBean.getLoggerLevel(logger)); sb.append(", parent=").append(loggingMXBean.getParentLoggerName(logger)).append(CRLF); } diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/ExceptionUtils.java tomcat10-10.1.52/java/org/apache/tomcat/util/ExceptionUtils.java --- tomcat10-10.1.40/java/org/apache/tomcat/util/ExceptionUtils.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/ExceptionUtils.java 2026-01-23 19:33:36.000000000 +0000 @@ -25,8 +25,8 @@ public class ExceptionUtils { /** - * Checks whether the supplied Throwable is one that needs to be - * rethrown and swallows all others. + * Checks whether the supplied Throwable is one that needs to be rethrown and swallows all others. + * * @param t the Throwable to check */ public static void handleThrowable(Throwable t) { @@ -44,11 +44,11 @@ } /** - * Checks whether the supplied Throwable is an instance of - * InvocationTargetException and returns the throwable that is - * wrapped by it, if there is any. + * Checks whether the supplied Throwable is an instance of InvocationTargetException and returns the + * throwable that is wrapped by it, if there is any. * * @param t the Throwable to check + * * @return t or t.getCause() */ public static Throwable unwrapInvocationTargetException(Throwable t) { @@ -60,10 +60,9 @@ /** - * NO-OP method provided to enable simple preloading of this class. Since - * the class is used extensively in error handling, it is prudent to - * preload it to avoid any failure to load this class masking the true - * problem during error handling. + * NO-OP method provided to enable simple preloading of this class. Since the class is used extensively in error + * handling, it is prudent to preload it to avoid any failure to load this class masking the true problem during + * error handling. */ public static void preload() { // NO-OP diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/IntrospectionUtils.java tomcat10-10.1.52/java/org/apache/tomcat/util/IntrospectionUtils.java --- tomcat10-10.1.40/java/org/apache/tomcat/util/IntrospectionUtils.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/IntrospectionUtils.java 2026-01-23 19:33:36.000000000 +0000 @@ -38,29 +38,28 @@ private static final StringManager sm = StringManager.getManager(IntrospectionUtils.class); /** - * Find a method with the right name If found, call the method ( if param is - * int or boolean we'll convert value to the right type before) - that means - * you can have setDebug(1). - * @param o The object to set a property on - * @param name The property name + * Find a method with the right name If found, call the method ( if param is int or boolean we'll convert value to + * the right type before) - that means you can have setDebug(1). + * + * @param o The object to set a property on + * @param name The property name * @param value The property value + * * @return true if operation was successful */ public static boolean setProperty(Object o, String name, String value) { return setProperty(o, name, value, true, null); } - public static boolean setProperty(Object o, String name, String value, - boolean invokeSetProperty) { + public static boolean setProperty(Object o, String name, String value, boolean invokeSetProperty) { return setProperty(o, name, value, invokeSetProperty, null); } @SuppressWarnings("null") // setPropertyMethodVoid is not null when used - public static boolean setProperty(Object o, String name, String value, - boolean invokeSetProperty, StringBuilder actualMethod) { + public static boolean setProperty(Object o, String name, String value, boolean invokeSetProperty, + StringBuilder actualMethod) { if (log.isTraceEnabled()) { - log.trace("IntrospectionUtils: setProperty(" + - o.getClass() + " " + name + "=" + value + ")"); + log.trace("IntrospectionUtils: setProperty(" + o.getClass() + " " + name + "=" + value + ")"); } if (actualMethod == null && XReflectionIntrospectionUtils.isEnabled()) { @@ -77,8 +76,8 @@ // First, the ideal case - a setFoo( String ) method for (Method item : methods) { Class[] paramT = item.getParameterTypes(); - if (setter.equals(item.getName()) && paramT.length == 1 - && "java.lang.String".equals(paramT[0].getName())) { + if (setter.equals(item.getName()) && paramT.length == 1 && + "java.lang.String".equals(paramT[0].getName())) { item.invoke(o, value); if (actualMethod != null) { actualMethod.append(item.getName()).append("(\"").append(escape(value)).append("\")"); @@ -90,16 +89,14 @@ // Try a setFoo ( int ) or ( boolean ) for (Method method : methods) { boolean ok = true; - if (setter.equals(method.getName()) - && method.getParameterTypes().length == 1) { + if (setter.equals(method.getName()) && method.getParameterTypes().length == 1) { // match - find the type and invoke it Class paramType = method.getParameterTypes()[0]; Object[] params = new Object[1]; // Try a setFoo ( int ) - if ("java.lang.Integer".equals(paramType.getName()) - || "int".equals(paramType.getName())) { + if ("java.lang.Integer".equals(paramType.getName()) || "int".equals(paramType.getName())) { try { params[0] = Integer.valueOf(value); } catch (NumberFormatException ex) { @@ -107,14 +104,15 @@ } if (actualMethod != null) { if ("java.lang.Integer".equals(paramType.getName())) { - actualMethod.append(method.getName()).append("(Integer.valueOf(\"").append(value).append("\"))"); + actualMethod.append(method.getName()).append("(Integer.valueOf(\"").append(value) + .append("\"))"); } else { - actualMethod.append(method.getName()).append("(Integer.parseInt(\"").append(value).append("\"))"); + actualMethod.append(method.getName()).append("(Integer.parseInt(\"").append(value) + .append("\"))"); } } // Try a setFoo ( long ) - } else if ("java.lang.Long".equals(paramType.getName()) - || "long".equals(paramType.getName())) { + } else if ("java.lang.Long".equals(paramType.getName()) || "long".equals(paramType.getName())) { try { params[0] = Long.valueOf(value); } catch (NumberFormatException ex) { @@ -122,25 +120,28 @@ } if (actualMethod != null) { if ("java.lang.Long".equals(paramType.getName())) { - actualMethod.append(method.getName()).append("(Long.valueOf(\"").append(value).append("\"))"); + actualMethod.append(method.getName()).append("(Long.valueOf(\"").append(value) + .append("\"))"); } else { - actualMethod.append(method.getName()).append("(Long.parseLong(\"").append(value).append("\"))"); + actualMethod.append(method.getName()).append("(Long.parseLong(\"").append(value) + .append("\"))"); } } // Try a setFoo ( boolean ) - } else if ("java.lang.Boolean".equals(paramType.getName()) - || "boolean".equals(paramType.getName())) { + } else if ("java.lang.Boolean".equals(paramType.getName()) || + "boolean".equals(paramType.getName())) { params[0] = Boolean.valueOf(value); if (actualMethod != null) { if ("java.lang.Boolean".equals(paramType.getName())) { - actualMethod.append(method.getName()).append("(Boolean.valueOf(\"").append(value).append("\"))"); + actualMethod.append(method.getName()).append("(Boolean.valueOf(\"").append(value) + .append("\"))"); } else { - actualMethod.append(method.getName()).append("(Boolean.parseBoolean(\"").append(value).append("\"))"); + actualMethod.append(method.getName()).append("(Boolean.parseBoolean(\"").append(value) + .append("\"))"); } } // Try a setFoo ( InetAddress ) - } else if ("java.net.InetAddress".equals(paramType - .getName())) { + } else if ("java.net.InetAddress".equals(paramType.getName())) { try { params[0] = InetAddress.getByName(value); } catch (UnknownHostException exc) { @@ -150,13 +151,13 @@ ok = false; } if (actualMethod != null) { - actualMethod.append(method.getName()).append("(InetAddress.getByName(\"").append(value).append("\"))"); + actualMethod.append(method.getName()).append("(InetAddress.getByName(\"").append(value) + .append("\"))"); } // Unknown type } else { if (log.isTraceEnabled()) { - log.trace("IntrospectionUtils: Unknown type " + - paramType.getName()); + log.trace("IntrospectionUtils: Unknown type " + paramType.getName()); } } @@ -178,25 +179,24 @@ } // Ok, no setXXX found, try a setProperty("name", "value") - if (invokeSetProperty && (setPropertyMethodBool != null || - setPropertyMethodVoid != null)) { + if (invokeSetProperty && (setPropertyMethodBool != null || setPropertyMethodVoid != null)) { if (actualMethod != null) { - actualMethod.append("setProperty(\"").append(name).append("\", \"").append(escape(value)).append("\")"); + actualMethod.append("setProperty(\"").append(name).append("\", \"").append(escape(value)) + .append("\")"); } Object[] params = new Object[2]; params[0] = name; params[1] = value; if (setPropertyMethodBool != null) { try { - return ((Boolean) setPropertyMethodBool.invoke(o, - params)).booleanValue(); - }catch (IllegalArgumentException biae) { - //the boolean method had the wrong - //parameter types. let's try the other - if (setPropertyMethodVoid!=null) { + return ((Boolean) setPropertyMethodBool.invoke(o, params)).booleanValue(); + } catch (IllegalArgumentException biae) { + // the boolean method had the wrong + // parameter types. let's try the other + if (setPropertyMethodVoid != null) { setPropertyMethodVoid.invoke(o, params); return true; - }else { + } else { throw biae; } } @@ -216,8 +216,8 @@ } /** - * @param s - * the input string + * @param s the input string + * * @return escaped string, per Java rule */ public static String escape(String s) { @@ -291,36 +291,29 @@ } /** - * Replaces ${NAME} in the value with the value of the property 'NAME'. - * Replaces ${NAME:DEFAULT} with the value of the property 'NAME:DEFAULT', - * if the property 'NAME:DEFAULT' is not set, - * the expression is replaced with the value of the property 'NAME', - * if the property 'NAME' is not set, - * the expression is replaced with 'DEFAULT'. - * If the property is not set and there is no default the value will be - * returned unmodified. + * Replaces ${NAME} in the value with the value of the property 'NAME'. Replaces ${NAME:DEFAULT} with the value of + * the property 'NAME:DEFAULT', if the property 'NAME:DEFAULT' is not set, the expression is replaced with the value + * of the property 'NAME', if the property 'NAME' is not set, the expression is replaced with 'DEFAULT'. If the + * property is not set and there is no default the value will be returned unmodified. * - * @param value The value - * @param staticProp Replacement properties + * @param value The value + * @param staticProp Replacement properties * @param dynamicProp Replacement properties - * @param classLoader Class loader associated with the code requesting the - * property + * @param classLoader Class loader associated with the code requesting the property * * @return the replacement value */ - public static String replaceProperties(String value, - Hashtable staticProp, PropertySource[] dynamicProp, - ClassLoader classLoader) { - return replaceProperties(value, staticProp, dynamicProp, classLoader, 0); + public static String replaceProperties(String value, Hashtable staticProp, + PropertySource[] dynamicProp, ClassLoader classLoader) { + return replaceProperties(value, staticProp, dynamicProp, classLoader, 0); } - private static String replaceProperties(String value, - Hashtable staticProp, PropertySource[] dynamicProp, - ClassLoader classLoader, int iterationCount) { + private static String replaceProperties(String value, Hashtable staticProp, + PropertySource[] dynamicProp, ClassLoader classLoader, int iterationCount) { if (value == null || !value.contains("${")) { return value; } - if (iterationCount >=20) { + if (iterationCount >= 20) { log.warn(sm.getString("introspectionUtils.tooManyIterations", value)); return value; } @@ -378,11 +371,11 @@ if (log.isTraceEnabled()) { log.trace("IntrospectionUtils.replaceProperties iter on: " + newval); } - return replaceProperties(newval, staticProp, dynamicProp, classLoader, iterationCount+1); + return replaceProperties(newval, staticProp, dynamicProp, classLoader, iterationCount + 1); } - private static String getProperty(String name, Hashtable staticProp, - PropertySource[] dynamicProp, ClassLoader classLoader) { + private static String getProperty(String name, Hashtable staticProp, PropertySource[] dynamicProp, + ClassLoader classLoader) { String v = null; if (staticProp != null) { v = (String) staticProp.get(name); @@ -404,7 +397,9 @@ /** * Reverse of Introspector.decapitalize. + * * @param name The name + * * @return the capitalized string */ public static String capitalize(String name) { @@ -434,8 +429,7 @@ return methods; } - public static Method findMethod(Class c, String name, - Class[] params) { + public static Method findMethod(Class c, String name, Class[] params) { Method[] methods = findMethods(c); for (Method method : methods) { if (method.getName().equals(name)) { @@ -465,14 +459,13 @@ return null; } - public static Object callMethod1(Object target, String methodN, - Object param1, String typeParam1, ClassLoader cl) throws Exception { + public static Object callMethod1(Object target, String methodN, Object param1, String typeParam1, ClassLoader cl) + throws Exception { if (target == null || methodN == null || param1 == null) { throw new IllegalArgumentException(sm.getString("introspectionUtils.nullParameter")); } if (log.isTraceEnabled()) { - log.trace("IntrospectionUtils: callMethod1 " + - target.getClass().getName() + " " + + log.trace("IntrospectionUtils: callMethod1 " + target.getClass().getName() + " " + param1.getClass().getName() + " " + typeParam1); } @@ -484,7 +477,8 @@ } Method m = findMethod(target.getClass(), methodN, params); if (m == null) { - throw new NoSuchMethodException(sm.getString("introspectionUtils.noMethod", methodN, target, target.getClass())); + throw new NoSuchMethodException( + sm.getString("introspectionUtils.noMethod", methodN, target, target.getClass())); } try { return m.invoke(target, param1); @@ -494,8 +488,8 @@ } } - public static Object callMethodN(Object target, String methodN, - Object[] params, Class[] typeParams) throws Exception { + public static Object callMethodN(Object target, String methodN, Object[] params, Class[] typeParams) + throws Exception { Method m = findMethod(target.getClass(), methodN, typeParams); if (m == null) { if (log.isDebugEnabled()) { @@ -529,57 +523,50 @@ Object result = null; if ("java.lang.String".equals(paramType.getName())) { result = object; - } else if ("java.lang.Integer".equals(paramType.getName()) - || "int".equals(paramType.getName())) { + } else if ("java.lang.Integer".equals(paramType.getName()) || "int".equals(paramType.getName())) { try { result = Integer.valueOf(object); } catch (NumberFormatException ex) { } // Try a setFoo ( boolean ) - } else if ("java.lang.Boolean".equals(paramType.getName()) - || "boolean".equals(paramType.getName())) { + } else if ("java.lang.Boolean".equals(paramType.getName()) || "boolean".equals(paramType.getName())) { result = Boolean.valueOf(object); // Try a setFoo ( InetAddress ) - } else if ("java.net.InetAddress".equals(paramType - .getName())) { + } else if ("java.net.InetAddress".equals(paramType.getName())) { try { result = InetAddress.getByName(object); } catch (UnknownHostException exc) { if (log.isDebugEnabled()) { - log.debug(sm.getString("introspectionUtils.hostResolutionFail", object)); + log.debug(sm.getString("introspectionUtils.hostResolutionFail", object), exc); } } // Unknown type } else { if (log.isTraceEnabled()) { - log.trace("IntrospectionUtils: Unknown type " + - paramType.getName()); + log.trace("IntrospectionUtils: Unknown type " + paramType.getName()); } } if (result == null) { - throw new IllegalArgumentException(sm.getString("introspectionUtils.conversionError", object, paramType.getName())); + throw new IllegalArgumentException( + sm.getString("introspectionUtils.conversionError", object, paramType.getName())); } return result; } /** - * Checks to see if the specified class is an instance of or assignable from - * the specified type. The class clazz, all its superclasses, - * interfaces and those superinterfaces are tested for a match against - * the type name type. - * This is similar to instanceof or {@link Class#isAssignableFrom} - * except that the target type will not be resolved into a Class - * object, which provides some security and memory benefits. + * Checks to see if the specified class is an instance of or assignable from the specified type. The class + * clazz, all its superclasses, interfaces and those superinterfaces are tested for a match against the + * type name type. This is similar to instanceof or {@link Class#isAssignableFrom} except + * that the target type will not be resolved into a Class object, which provides some security and memory benefits. * * @param clazz The class to test for a match. - * @param type The name of the type that clazz must be. + * @param type The name of the type that clazz must be. * - * @return true if the clazz tested is an - * instance of the specified type, - * false otherwise. + * @return true if the clazz tested is an instance of the specified type, + * false otherwise. */ public static boolean isInstance(Class clazz, String type) { if (type.equals(clazz.getName())) { @@ -613,19 +600,16 @@ public interface SecurePropertySource extends PropertySource { /** - * Obtain a property value, checking that code associated with the - * provided class loader has permission to access the property. If the - * {@code classLoader} is {@code null} or if {@code classLoader} does - * not implement {@link PermissionCheck} then the property value will be - * looked up without a call to + * Obtain a property value, checking that code associated with the provided class loader has permission to + * access the property. If the {@code classLoader} is {@code null} or if {@code classLoader} does not implement + * {@link PermissionCheck} then the property value will be looked up without a call to * {@link PermissionCheck#check(java.security.Permission)} * - * @param key The key of the requested property - * @param classLoader The class loader associated with the code that - * trigger the property lookup - * @return The property value or {@code null} if it could not be found - * or if {@link PermissionCheck#check(java.security.Permission)} - * fails + * @param key The key of the requested property + * @param classLoader The class loader associated with the code that trigger the property lookup + * + * @return The property value or {@code null} if it could not be found or if + * {@link PermissionCheck#check(java.security.Permission)} fails */ String getProperty(String key, ClassLoader classLoader); } diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/MultiThrowable.java tomcat10-10.1.52/java/org/apache/tomcat/util/MultiThrowable.java --- tomcat10-10.1.40/java/org/apache/tomcat/util/MultiThrowable.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/MultiThrowable.java 2026-01-23 19:33:36.000000000 +0000 @@ -21,9 +21,8 @@ import java.util.List; /** - * Wraps a list of throwables as a single throwable. This is intended to be used - * when multiple actions are taken where each may throw an exception but all - * actions are taken before any errors are reported. + * Wraps a list of throwables as a single throwable. This is intended to be used when multiple actions are taken where + * each may throw an exception but all actions are taken before any errors are reported. *

      * This class is NOT threadsafe. */ @@ -52,9 +51,8 @@ /** - * @return {@code null} if there are no wrapped throwables, the Throwable if - * there is a single wrapped throwable or the current instance of - * there are multiple wrapped throwables + * @return {@code null} if there are no wrapped throwables, the Throwable if there is a single wrapped throwable or + * the current instance of there are multiple wrapped throwables */ public Throwable getThrowable() { if (size() == 0) { @@ -76,10 +74,9 @@ /** - * Overrides the default implementation to provide a concatenation of the - * messages associated with each of the wrapped throwables. Note that the - * format of the returned String is not guaranteed to be fixed and may - * change in a future release. + * Overrides the default implementation to provide a concatenation of the messages associated with each of the + * wrapped throwables. Note that the format of the returned String is not guaranteed to be fixed and may change in a + * future release. */ @Override public String toString() { diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/XReflectionIntrospectionUtils.java tomcat10-10.1.52/java/org/apache/tomcat/util/XReflectionIntrospectionUtils.java --- tomcat10-10.1.40/java/org/apache/tomcat/util/XReflectionIntrospectionUtils.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/XReflectionIntrospectionUtils.java 2026-01-23 19:33:36.000000000 +0000 @@ -25,8 +25,8 @@ /** * Always throws {@link UnsupportedOperationException} * - * @param o Unused - * @param name Unused + * @param o Unused + * @param name Unused * * @return Never returns normally */ diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/bcel/Const.java tomcat10-10.1.52/java/org/apache/tomcat/util/bcel/Const.java --- tomcat10-10.1.40/java/org/apache/tomcat/util/bcel/Const.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/bcel/Const.java 2026-01-23 19:33:36.000000000 +0000 @@ -269,6 +269,22 @@ public static final short MAJOR_24 = 68; /** + * Minor version number of class files for Java 25: {@value}. + * + * @see #MAJOR_25 + * @since 6.11.0 + */ + public static final short MINOR_25 = 0; + + /** + * Major version number of class files for Java 25: {@value}. + * + * @see #MINOR_25 + * @since 6.11.0 + */ + public static final short MAJOR_25 = 69; + + /** * Get the CONSTANT_NAMES entry at the given index. * * @param index index into {@code CONSTANT_NAMES}. diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/bcel/classfile/Utility.java tomcat10-10.1.52/java/org/apache/tomcat/util/bcel/classfile/Utility.java --- tomcat10-10.1.40/java/org/apache/tomcat/util/bcel/classfile/Utility.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/bcel/classfile/Utility.java 2026-01-23 19:33:36.000000000 +0000 @@ -28,10 +28,7 @@ final class Utility { /** - * Shorten long class name str, i.e., chop off the prefix, - * if the - * class name starts with this string and the flag chopit is true. - * Slashes / are converted to dots .. + * Shorten long class names, java/lang/String becomes String. * * @param str The long class name * @return Compacted class name diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/buf/AbstractChunk.java tomcat10-10.1.52/java/org/apache/tomcat/util/buf/AbstractChunk.java --- tomcat10-10.1.40/java/org/apache/tomcat/util/buf/AbstractChunk.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/buf/AbstractChunk.java 2026-01-23 19:33:36.000000000 +0000 @@ -85,6 +85,7 @@ /** * Set the start position of the data in the buffer. + * * @param start the new start position */ public void setStart(int start) { @@ -105,6 +106,7 @@ /** * Set the end position of the data in the buffer. + * * @param end the new end position */ public void setEnd(int end) { @@ -114,6 +116,7 @@ /** * @return start + * * @deprecated Unused. This method will be removed in Tomcat 12. */ @Deprecated @@ -123,7 +126,9 @@ /** * Set start. + * * @param off the new start + * * @deprecated Unused. This method will be removed in Tomcat 12. */ @Deprecated @@ -155,15 +160,15 @@ /** - * Return the index of the first occurrence of the subsequence of - * the given String, or -1 if it is not found. + * Return the index of the first occurrence of the subsequence of the given String, or -1 if it is not found. * - * @param src the String to look for + * @param src the String to look for * @param srcStart the subsequence start in the String - * @param srcLen the subsequence length in the String + * @param srcLen the subsequence length in the String * @param myOffset the index on which to start the search in the buffer - * @return the position of the first character of the first occurrence - * of the subsequence in the buffer, or -1 if not found + * + * @return the position of the first character of the first occurrence of the subsequence in the buffer, or -1 if + * not found */ public int indexOf(String src, int srcStart, int srcLen, int myOffset) { char first = src.charAt(srcStart); @@ -171,7 +176,8 @@ // Look for first char int srcEnd = srcStart + srcLen; - mainLoop: for (int i = myOffset + start; i <= (end - srcLen); i++) { + mainLoop: + for (int i = myOffset + start; i <= (end - srcLen); i++) { if (getBufferElement(i) != first) { continue; } @@ -225,6 +231,7 @@ /** * @param index the element location in the buffer + * * @return the element */ protected abstract int getBufferElement(int index); diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/buf/Ascii.java tomcat10-10.1.52/java/org/apache/tomcat/util/buf/Ascii.java --- tomcat10-10.1.40/java/org/apache/tomcat/util/buf/Ascii.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/buf/Ascii.java 2026-01-23 19:33:36.000000000 +0000 @@ -18,9 +18,6 @@ /** * This class implements some basic ASCII character handling functions. - * - * @author dac@eng.sun.com - * @author James Todd [gonzo@eng.sun.com] */ public final class Ascii { /* diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/buf/ByteChunk.java tomcat10-10.1.52/java/org/apache/tomcat/util/buf/ByteChunk.java --- tomcat10-10.1.40/java/org/apache/tomcat/util/buf/ByteChunk.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/buf/ByteChunk.java 2026-01-23 19:33:36.000000000 +0000 @@ -41,22 +41,13 @@ * chars and Strings until the strings are needed. In addition, the charset is determined later, from headers or user * code. *

      - * In a server it is very important to be able to operate on - * the original byte[] without converting everything to chars. - * Some protocols are ASCII only, and some allow different - * non-UNICODE encodings. The encoding is not known beforehand, - * and can even change during the execution of the protocol. - * ( for example a multipart message may have parts with different - * encoding ) + * In a server it is very important to be able to operate on the original byte[] without converting everything to chars. + * Some protocols are ASCII only, and some allow different non-UNICODE encodings. The encoding is not known beforehand, + * and can even change during the execution of the protocol. ( for example a multipart message may have parts with + * different encoding ) *

      - * For HTTP, it is not very clear how the encoding of RequestURI - * and mime values can be determined, but it is a great advantage - * to be able to parse the request without converting to string. - * - * @author dac@sun.com - * @author James Todd [gonzo@sun.com] - * @author Costin Manolache - * @author Remy Maucherat + * For HTTP, it is not very clear how the encoding of RequestURI and mime values can be determined, but it is a great + * advantage to be able to parse the request without converting to string. */ public final class ByteChunk extends AbstractChunk { @@ -566,7 +557,8 @@ // entire byte array. This is expensive if only a small subset of the // bytes will be used. The code below is from Apache Harmony. CharBuffer cb; - if (malformedInputAction == CodingErrorAction.REPLACE && unmappableCharacterAction == CodingErrorAction.REPLACE) { + if (malformedInputAction == CodingErrorAction.REPLACE && + unmappableCharacterAction == CodingErrorAction.REPLACE) { cb = charset.decode(ByteBuffer.wrap(buff, start, end - start)); } else { cb = charset.newDecoder().onMalformedInput(malformedInputAction) @@ -701,9 +693,10 @@ *

      * NOTE: This only works for characters in the range 0-127. * - * @param c2 the array to compare to + * @param c2 the array to compare to * @param off2 offset * @param len2 length + * * @return true if the comparison succeeded, false otherwise */ public boolean equals(char[] c2, int off2, int len2) { diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/buf/CharChunk.java tomcat10-10.1.52/java/org/apache/tomcat/util/buf/CharChunk.java --- tomcat10-10.1.40/java/org/apache/tomcat/util/buf/CharChunk.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/buf/CharChunk.java 2026-01-23 19:33:36.000000000 +0000 @@ -21,11 +21,6 @@ /** * Utilities to manipulate char chunks. While String is the easiest way to manipulate chars ( search, substrings, etc), * it is known to not be the most efficient solution - Strings are designed as immutable and secure objects. - * - * @author dac@sun.com - * @author James Todd [gonzo@sun.com] - * @author Costin Manolache - * @author Remy Maucherat */ public final class CharChunk extends AbstractChunk implements CharSequence { diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/buf/HexUtils.java tomcat10-10.1.52/java/org/apache/tomcat/util/buf/HexUtils.java --- tomcat10-10.1.40/java/org/apache/tomcat/util/buf/HexUtils.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/buf/HexUtils.java 2026-01-23 19:33:36.000000000 +0000 @@ -21,8 +21,6 @@ /** * Tables useful when converting byte arrays to and from strings of hexadecimal digits. Code from Ajp11, from Apache's * JServ. - * - * @author Craig R. McClanahan */ public final class HexUtils { @@ -33,9 +31,9 @@ /** * Table for HEX to DEC byte translation. */ - private static final int[] DEC = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, -1, -1, -1, -1, -1, -1, 10, 11, 12, 13, - 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, 10, 11, 12, 13, 14, 15, }; + private static final int[] DEC = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, -1, -1, -1, -1, -1, -1, 10, 11, 12, 13, 14, 15, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 10, + 11, 12, 13, 14, 15, }; /** diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/buf/MessageBytes.java tomcat10-10.1.52/java/org/apache/tomcat/util/buf/MessageBytes.java --- tomcat10-10.1.40/java/org/apache/tomcat/util/buf/MessageBytes.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/buf/MessageBytes.java 2026-01-23 19:33:36.000000000 +0000 @@ -31,10 +31,6 @@ *

      * The object can represent a byte[], a char[], or a (sub) String. All operations can be made in case-sensitive mode or * not. - * - * @author dac@eng.sun.com - * @author James Todd [gonzo@eng.sun.com] - * @author Costin Manolache */ public final class MessageBytes implements Cloneable, Serializable { diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/buf/StringCache.java tomcat10-10.1.52/java/org/apache/tomcat/util/buf/StringCache.java --- tomcat10-10.1.40/java/org/apache/tomcat/util/buf/StringCache.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/buf/StringCache.java 2026-01-23 19:33:36.000000000 +0000 @@ -31,8 +31,6 @@ /** * This class implements a String cache for ByteChunk and CharChunk. - * - * @author Remy Maucherat */ public class StringCache { @@ -481,8 +479,8 @@ * * @return the corresponding value * - * @deprecated Unused. Will be removed in Tomcat 11. - * Use {@link #find(ByteChunk, CodingErrorAction, CodingErrorAction)} + * @deprecated Unused. Will be removed in Tomcat 11. Use + * {@link #find(ByteChunk, CodingErrorAction, CodingErrorAction)} */ @Deprecated protected static final String find(ByteChunk name) { @@ -500,7 +498,7 @@ * @return the corresponding value */ protected static String find(ByteChunk name, CodingErrorAction malformedInputAction, - CodingErrorAction unmappableCharacterAction) { + CodingErrorAction unmappableCharacterAction) { int pos = findClosest(name, bcCache, bcCache.length); if ((pos < 0) || (compare(name, bcCache[pos].name) != 0) || !(name.getCharset().equals(bcCache[pos].charset)) || !malformedInputAction.equals(bcCache[pos].malformedInputAction) || diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/buf/StringUtils.java tomcat10-10.1.52/java/org/apache/tomcat/util/buf/StringUtils.java --- tomcat10-10.1.40/java/org/apache/tomcat/util/buf/StringUtils.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/buf/StringUtils.java 2026-01-23 19:33:36.000000000 +0000 @@ -101,11 +101,11 @@ } /** - * Splits a comma-separated string into an array of String values. - * Whitespace around the commas is removed. - * Null or empty values will return a zero-element array. + * Splits a comma-separated string into an array of String values. Whitespace around the commas is removed. Null or + * empty values will return a zero-element array. * * @param s The string to split by commas. + * * @return An array of String values. */ public static String[] splitCommaSeparated(String s) { diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/buf/UDecoder.java tomcat10-10.1.52/java/org/apache/tomcat/util/buf/UDecoder.java --- tomcat10-10.1.40/java/org/apache/tomcat/util/buf/UDecoder.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/buf/UDecoder.java 2026-01-23 19:33:36.000000000 +0000 @@ -28,8 +28,6 @@ /** * All URL decoding happens here. This way we can reuse, review, optimize without adding complexity to the buffers. The * conversion will modify the original buffer. - * - * @author Costin Manolache */ public final class UDecoder { @@ -101,10 +99,8 @@ * URLDecode, will modify the source. Assumes source bytes are encoded using a superset of US-ASCII as per RFC 7230. * * @param mb The URL encoded bytes - * @param encodedSolidusHandling How should the %2f sequence handled by the decoder? For query strings this - * parameter will be ignored and the %2f sequence will be decoded - * @param encodedReverseSolidusHandling How should the %5c sequence handled by the decoder? For query strings this - * parameter will be ignored and the %5c sequence will be decoded + * @param encodedSolidusHandling How should the %2f sequence handled by the decoder? + * @param encodedReverseSolidusHandling How should the %5c sequence handled by the decoder? * * @throws IOException Invalid %xx URL encoding */ diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/buf/UEncoder.java tomcat10-10.1.52/java/org/apache/tomcat/util/buf/UEncoder.java --- tomcat10-10.1.40/java/org/apache/tomcat/util/buf/UEncoder.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/buf/UEncoder.java 2026-01-23 19:33:36.000000000 +0000 @@ -24,8 +24,6 @@ * Efficient implementation of a UTF-8 encoder. This class is not thread safe - you need one encoder per thread. The * encoder will save and recycle the internal objects, avoiding garbage. You can add extra characters that you want * preserved, for example while encoding a URL you can add "/". - * - * @author Costin Manolache */ public final class UEncoder { diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/codec/binary/Base64.java tomcat10-10.1.52/java/org/apache/tomcat/util/codec/binary/Base64.java --- tomcat10-10.1.40/java/org/apache/tomcat/util/codec/binary/Base64.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/codec/binary/Base64.java 2026-01-23 19:33:36.000000000 +0000 @@ -18,7 +18,6 @@ /** * Provides Base64 encoding and decoding as defined by RFC 2045. - * *

      * This class implements section 6.8. Base64 Content-Transfer-Encoding from RFC 2045 Multipurpose * Internet Mail Extensions (MIME) Part One: Format of Internet Message Bodies by Freed and Borenstein. @@ -36,15 +35,15 @@ * The URL-safe parameter is only applied to encode operations. Decoding seamlessly handles both modes. *

      *

      - * Since this class operates directly on byte streams, and not character streams, it is hard-coded to only - * encode/decode character encodings which are compatible with the lower 127 ASCII chart (ISO-8859-1, Windows-1252, - * UTF-8, etc). + * Since this class operates directly on byte streams, and not character streams, it is hard-coded to only encode/decode + * character encodings which are compatible with the lower 127 ASCII chart (ISO-8859-1, Windows-1252, UTF-8, etc). *

      *

      * This class is thread-safe. *

      * * @see RFC 2045 + * * @since 1.0 * * @deprecated Unused. This class will be removed in Tomcat 11 onwards. @@ -53,8 +52,7 @@ public class Base64 extends BaseNCodec { /** - * BASE64 characters are 6 bits in length. - * They are formed by taking a block of 3 octets to form a 24-bit string, + * BASE64 characters are 6 bits in length. They are formed by taking a block of 3 octets to form a 24-bit string, * which is converted into 4 BASE64 characters. */ private static final int BITS_PER_ENCODED_BYTE = 6; @@ -69,30 +67,23 @@ * https://svn.apache.org/repos/asf/webservices/commons/trunk/modules/util/ *

      */ - private static final byte[] STANDARD_ENCODE_TABLE = { - 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', - 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', - 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', - 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', - '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/' - }; + private static final byte[] STANDARD_ENCODE_TABLE = { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', + 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', + 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '0', '1', + '2', '3', '4', '5', '6', '7', '8', '9', '+', '/' }; /** - * This is a copy of the STANDARD_ENCODE_TABLE above, but with + and / - * changed to - and _ to make the encoded Base64 results more URL-SAFE. - * This table is only used when the Base64's mode is set to URL-SAFE. - */ - private static final byte[] URL_SAFE_ENCODE_TABLE = { - 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', - 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', - 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', - 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', - '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '-', '_' - }; + * This is a copy of the STANDARD_ENCODE_TABLE above, but with + and / changed to - and _ to make the encoded Base64 + * results more URL-SAFE. This table is only used when the Base64's mode is set to URL-SAFE. + */ + private static final byte[] URL_SAFE_ENCODE_TABLE = { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', + 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', + 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '0', '1', + '2', '3', '4', '5', '6', '7', '8', '9', '-', '_' }; /** - * This array is a lookup table that translates Unicode characters drawn from the "Base64 Alphabet" (as specified - * in Table 1 of RFC 2045) into their 6-bit positive integer equivalents. Characters that are not in the Base64 + * This array is a lookup table that translates Unicode characters drawn from the "Base64 Alphabet" (as specified in + * Table 1 of RFC 2045) into their 6-bit positive integer equivalents. Characters that are not in the Base64 * alphabet but fall within the bounds of the array are translated to -1. *

      * Note: '+' and '-' both decode to 62. '/' and '_' both decode to 63. This means decoder seamlessly handles both @@ -103,6 +94,7 @@ * https://svn.apache.org/repos/asf/webservices/commons/trunk/modules/util/ *

      */ + // @formatter:off private static final byte[] STANDARD_DECODE_TABLE = { // 0 1 2 3 4 5 6 7 8 9 A B C D E F -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 00-0f @@ -125,7 +117,8 @@ 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, 63, // 50-5f P-Z _ -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, // 60-6f a-o 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51 // 70-7a p-z - }; + }; + // @formatter:on /* * Base64 uses 6-bit fields. @@ -141,8 +134,7 @@ // The private member fields below are used with the new streaming approach, which requires // some state be preserved between calls of encode() and decode(). - public static byte[] decodeBase64( - final byte[] base64Data, final int off, final int len) { + public static byte[] decodeBase64(final byte[] base64Data, final int off, final int len) { return new Base64().decode(base64Data, off, len); } @@ -152,9 +144,10 @@ * Note: this method seamlessly handles data encoded in URL-safe or normal mode. *

      * - * @param base64String - * String containing Base64 data + * @param base64String String containing Base64 data + * * @return Array containing decoded data. + * * @since 1.4 */ public static byte[] decodeBase64(final String base64String) { @@ -169,13 +162,13 @@ /** * Encodes binary data using the base64 algorithm, optionally chunking the output into 76 character blocks. * - * @param binaryData - * Array containing binary data to encode. - * @param isChunked - * if {@code true} this encoder will chunk the base64 output into 76 character blocks + * @param binaryData Array containing binary data to encode. + * @param isChunked if {@code true} this encoder will chunk the base64 output into 76 character blocks + * * @return Base64-encoded data. - * @throws IllegalArgumentException - * Thrown when the input array needs an output array bigger than {@link Integer#MAX_VALUE} + * + * @throws IllegalArgumentException Thrown when the input array needs an output array bigger than + * {@link Integer#MAX_VALUE} */ public static byte[] encodeBase64(final byte[] binaryData, final boolean isChunked) { return encodeBase64(binaryData, isChunked, false); @@ -184,16 +177,16 @@ /** * Encodes binary data using the base64 algorithm, optionally chunking the output into 76 character blocks. * - * @param binaryData - * Array containing binary data to encode. - * @param isChunked - * if {@code true} this encoder will chunk the base64 output into 76 character blocks - * @param urlSafe - * if {@code true} this encoder will emit - and _ instead of the usual + and / characters. - * Note: no padding is added when encoding using the URL-safe alphabet. + * @param binaryData Array containing binary data to encode. + * @param isChunked if {@code true} this encoder will chunk the base64 output into 76 character blocks + * @param urlSafe if {@code true} this encoder will emit - and _ instead of the usual + and / characters. + * Note: no padding is added when encoding using the URL-safe alphabet. + * * @return Base64-encoded data. - * @throws IllegalArgumentException - * Thrown when the input array needs an output array bigger than {@link Integer#MAX_VALUE} + * + * @throws IllegalArgumentException Thrown when the input array needs an output array bigger than + * {@link Integer#MAX_VALUE} + * * @since 1.4 */ public static byte[] encodeBase64(final byte[] binaryData, final boolean isChunked, final boolean urlSafe) { @@ -203,22 +196,20 @@ /** * Encodes binary data using the base64 algorithm, optionally chunking the output into 76 character blocks. * - * @param binaryData - * Array containing binary data to encode. - * @param isChunked - * if {@code true} this encoder will chunk the base64 output into 76 character blocks - * @param urlSafe - * if {@code true} this encoder will emit - and _ instead of the usual + and / characters. - * Note: no padding is added when encoding using the URL-safe alphabet. - * @param maxResultSize - * The maximum result size to accept. + * @param binaryData Array containing binary data to encode. + * @param isChunked if {@code true} this encoder will chunk the base64 output into 76 character blocks + * @param urlSafe if {@code true} this encoder will emit - and _ instead of the usual + and / characters. + * Note: no padding is added when encoding using the URL-safe alphabet. + * @param maxResultSize The maximum result size to accept. + * * @return Base64-encoded data. - * @throws IllegalArgumentException - * Thrown when the input array needs an output array bigger than maxResultSize + * + * @throws IllegalArgumentException Thrown when the input array needs an output array bigger than maxResultSize + * * @since 1.4 */ - public static byte[] encodeBase64(final byte[] binaryData, final boolean isChunked, - final boolean urlSafe, final int maxResultSize) { + public static byte[] encodeBase64(final byte[] binaryData, final boolean isChunked, final boolean urlSafe, + final int maxResultSize) { if (binaryData == null || binaryData.length == 0) { return binaryData; } @@ -228,23 +219,22 @@ final Base64 b64 = isChunked ? new Base64(urlSafe) : new Base64(0, CHUNK_SEPARATOR, urlSafe); final long len = b64.getEncodedLength(binaryData); if (len > maxResultSize) { - throw new IllegalArgumentException(sm.getString( - "base64.inputTooLarge", Long.valueOf(len), Integer.valueOf(maxResultSize))); + throw new IllegalArgumentException( + sm.getString("base64.inputTooLarge", Long.valueOf(len), Integer.valueOf(maxResultSize))); } return b64.encode(binaryData); } /** - * Encodes binary data using the base64 algorithm but does not chunk the output. + * Encodes binary data using the base64 algorithm but does not chunk the output. NOTE: We changed the behavior of + * this method from multi-line chunking (commons-codec-1.4) to single-line non-chunking (commons-codec-1.5). * - * NOTE: We changed the behavior of this method from multi-line chunking (commons-codec-1.4) to - * single-line non-chunking (commons-codec-1.5). + * @param binaryData binary data to encode * - * @param binaryData - * binary data to encode * @return String containing Base64 characters. - * @since 1.4 (NOTE: 1.4 chunked the output, whereas 1.5 does not). + * + * @since 1.4 (NOTE: 1.4 chunked the output, whereas 1.5 does not). */ public static String encodeBase64String(final byte[] binaryData) { return StringUtils.newStringUsAscii(encodeBase64(binaryData, false)); @@ -252,11 +242,12 @@ /** * Encodes binary data using a URL-safe variation of the base64 algorithm but does not chunk the output. The - * url-safe variation emits - and _ instead of + and / characters. - * Note: no padding is added. - * @param binaryData - * binary data to encode + * url-safe variation emits - and _ instead of + and / characters. Note: no padding is added. + * + * @param binaryData binary data to encode + * * @return String containing Base64 characters + * * @since 1.4 */ public static String encodeBase64URLSafeString(final byte[] binaryData) { @@ -264,24 +255,22 @@ } /** - * Validates whether decoding the final trailing character is possible in the context - * of the set of possible base 64 values. + * Validates whether decoding the final trailing character is possible in the context of the set of possible base 64 + * values. *

      - * The character is valid if the lower bits within the provided mask are zero. This - * is used to test the final trailing base-64 digit is zero in the bits that will be discarded. + * The character is valid if the lower bits within the provided mask are zero. This is used to test the final + * trailing base-64 digit is zero in the bits that will be discarded. *

      * * @param emptyBitsMask The mask of the lower bits that should be empty - * @param context the context to be used + * @param context the context to be used * * @throws IllegalArgumentException if the bits being checked contain any non-zero value */ private static void validateCharacter(final int emptyBitsMask, final Context context) { if ((context.ibitWorkArea & emptyBitsMask) != 0) { - throw new IllegalArgumentException( - "Last encoded character (before the paddings if any) is a valid " + - "base 64 alphabet but not a possible value. " + - "Expected the discarded bits to be zero."); + throw new IllegalArgumentException("Last encoded character (before the paddings if any) is a valid " + + "base 64 alphabet but not a possible value. " + "Expected the discarded bits to be zero."); } } @@ -327,7 +316,6 @@ *

      * When encoding the line length is 0 (no chunking), and the encoding table is STANDARD_ENCODE_TABLE. *

      - * *

      * When decoding all variants are supported. *

      @@ -341,14 +329,12 @@ *

      * When encoding the line length is 76, the line separator is CRLF, and the encoding table is STANDARD_ENCODE_TABLE. *

      - * *

      * When decoding all variants are supported. *

      * - * @param urlSafe - * if {@code true}, URL-safe encoding is used. In most cases this should be set to - * {@code false}. + * @param urlSafe if {@code true}, URL-safe encoding is used. In most cases this should be set to {@code false}. + * * @since 1.4 */ public Base64(final boolean urlSafe) { @@ -368,10 +354,10 @@ * When decoding all variants are supported. *

      * - * @param lineLength - * Each line of encoded data will be at most of the given length (rounded down to the nearest multiple of - * 4). If lineLength <= 0, then the output will not be divided into lines (chunks). Ignored when - * decoding. + * @param lineLength Each line of encoded data will be at most of the given length (rounded down to the nearest + * multiple of 4). If lineLength <= 0, then the output will not be divided into lines + * (chunks). Ignored when decoding. + * * @since 1.4 */ public Base64(final int lineLength) { @@ -391,14 +377,13 @@ * When decoding all variants are supported. *

      * - * @param lineLength - * Each line of encoded data will be at most of the given length (rounded down to the nearest multiple of - * 4). If lineLength <= 0, then the output will not be divided into lines (chunks). Ignored when - * decoding. - * @param lineSeparator - * Each line of encoded data will end with this sequence of bytes. - * @throws IllegalArgumentException - * Thrown when the provided lineSeparator included some base64 characters. + * @param lineLength Each line of encoded data will be at most of the given length (rounded down to the nearest + * multiple of 4). If lineLength <= 0, then the output will not be divided into lines + * (chunks). Ignored when decoding. + * @param lineSeparator Each line of encoded data will end with this sequence of bytes. + * + * @throws IllegalArgumentException Thrown when the provided lineSeparator included some base64 characters. + * * @since 1.4 */ public Base64(final int lineLength, final byte[] lineSeparator) { @@ -418,23 +403,20 @@ * When decoding all variants are supported. *

      * - * @param lineLength - * Each line of encoded data will be at most of the given length (rounded down to the nearest multiple of - * 4). If lineLength <= 0, then the output will not be divided into lines (chunks). Ignored when - * decoding. - * @param lineSeparator - * Each line of encoded data will end with this sequence of bytes. - * @param urlSafe - * Instead of emitting '+' and '/' we emit '-' and '_' respectively. urlSafe is only applied to encode - * operations. Decoding seamlessly handles both modes. - * Note: no padding is added when using the URL-safe alphabet. - * @throws IllegalArgumentException - * Thrown when the {@code lineSeparator} contains Base64 characters. + * @param lineLength Each line of encoded data will be at most of the given length (rounded down to the nearest + * multiple of 4). If lineLength <= 0, then the output will not be divided into lines + * (chunks). Ignored when decoding. + * @param lineSeparator Each line of encoded data will end with this sequence of bytes. + * @param urlSafe Instead of emitting '+' and '/' we emit '-' and '_' respectively. urlSafe is only applied to + * encode operations. Decoding seamlessly handles both modes. Note: no padding is added + * when using the URL-safe alphabet. + * + * @throws IllegalArgumentException Thrown when the {@code lineSeparator} contains Base64 characters. + * * @since 1.4 */ public Base64(final int lineLength, final byte[] lineSeparator, final boolean urlSafe) { - super(BYTES_PER_UNENCODED_BLOCK, BYTES_PER_ENCODED_BLOCK, - lineLength, + super(BYTES_PER_UNENCODED_BLOCK, BYTES_PER_ENCODED_BLOCK, lineLength, lineSeparator == null ? 0 : lineSeparator.length); // Needs to be set early to avoid NPE during call to containsAlphabetOrPad() below this.decodeTable = urlSafe ? URL_SAFE_DECODE_TABLE : STANDARD_DECODE_TABLE; @@ -445,7 +427,7 @@ final String sep = StringUtils.newStringUtf8(lineSeparator); throw new IllegalArgumentException(sm.getString("base64.lineSeparator", sep)); } - if (lineLength > 0){ // null line-sep forces no chunking rather than throwing IAE + if (lineLength > 0) { // null line-sep forces no chunking rather than throwing IAE this.encodeSize = BYTES_PER_ENCODED_BLOCK + lineSeparator.length; this.lineSeparator = lineSeparator.clone(); } else { @@ -478,14 +460,10 @@ * https://svn.apache.org/repos/asf/webservices/commons/trunk/modules/util/ *

      * - * @param input - * byte[] array of ASCII data to base64 decode. - * @param inPos - * Position to start reading data from. - * @param inAvail - * Amount of bytes available from input for decoding. - * @param context - * the context to be used + * @param input byte[] array of ASCII data to base64 decode. + * @param inPos Position to start reading data from. + * @param inAvail Amount of bytes available from input for decoding. + * @param context the context to be used */ @Override void decode(final byte[] input, int inPos, final int inAvail, final Context context) { @@ -506,7 +484,7 @@ if (b >= 0 && b < decodeTable.length) { final int result = decodeTable[b]; if (result >= 0) { - context.modulus = (context.modulus+1) % BYTES_PER_ENCODED_BLOCK; + context.modulus = (context.modulus + 1) % BYTES_PER_ENCODED_BLOCK; context.ibitWorkArea = (context.ibitWorkArea << BITS_PER_ENCODED_BYTE) + result; if (context.modulus == 0) { buffer[context.pos++] = (byte) (context.ibitWorkArea >> 16 & MASK_8BITS); @@ -526,22 +504,22 @@ // We have some spare bits remaining // Output all whole multiples of 8 bits and ignore the rest switch (context.modulus) { -// case 0 : // impossible, as excluded above -// case 1 : // 6 bits - invalid - use default below - case 2 : // 12 bits = 8 + 4 + // case 0 : // impossible, as excluded above + // case 1 : // 6 bits - invalid - use default below + case 2: // 12 bits = 8 + 4 validateCharacter(MASK_4BITS, context); context.ibitWorkArea = context.ibitWorkArea >> 4; // dump the extra 4 bits buffer[context.pos++] = (byte) (context.ibitWorkArea & MASK_8BITS); break; - case 3 : // 18 bits = 8 + 8 + 2 + case 3: // 18 bits = 8 + 8 + 2 validateCharacter(MASK_2BITS, context); context.ibitWorkArea = context.ibitWorkArea >> 2; // dump 2 bits buffer[context.pos++] = (byte) (context.ibitWorkArea >> 8 & MASK_8BITS); buffer[context.pos++] = (byte) (context.ibitWorkArea & MASK_8BITS); break; default: - throw new IllegalStateException(sm.getString( - "base64.impossibleModulus", Integer.valueOf(context.modulus))); + throw new IllegalStateException( + sm.getString("base64.impossibleModulus", Integer.valueOf(context.modulus))); } } } @@ -552,20 +530,18 @@ * the data to encode, and once with inAvail set to "-1" to alert encoder that EOF has been reached, to flush last * remaining bytes (if not multiple of 3). *

      - *

      Note: no padding is added when encoding using the URL-safe alphabet.

      + *

      + * Note: no padding is added when encoding using the URL-safe alphabet. + *

      *

      * Thanks to "commons" project in ws.apache.org for the bitwise operations, and general approach. * https://svn.apache.org/repos/asf/webservices/commons/trunk/modules/util/ *

      * - * @param in - * byte[] array of binary data to base64 encode. - * @param inPos - * Position to start reading data from. - * @param inAvail - * Amount of bytes available from input for encoding. - * @param context - * the context to be used + * @param in byte[] array of binary data to base64 encode. + * @param inPos Position to start reading data from. + * @param inAvail Amount of bytes available from input for encoding. + * @param context the context to be used */ @Override void encode(final byte[] in, int inPos, final int inAvail, final Context context) { @@ -582,9 +558,9 @@ final byte[] buffer = ensureBufferSize(encodeSize, context); final int savedPos = context.pos; switch (context.modulus) { // 0-2 - case 0 : // nothing to do here + case 0: // nothing to do here break; - case 1 : // 8 bits = 6 + 2 + case 1: // 8 bits = 6 + 2 // top 6 bits: buffer[context.pos++] = encodeTable[context.ibitWorkArea >> 2 & MASK_6BITS]; // remaining 2: @@ -596,7 +572,7 @@ } break; - case 2 : // 16 bits = 6 + 6 + 4 + case 2: // 16 bits = 6 + 6 + 4 buffer[context.pos++] = encodeTable[context.ibitWorkArea >> 10 & MASK_6BITS]; buffer[context.pos++] = encodeTable[context.ibitWorkArea >> 4 & MASK_6BITS]; buffer[context.pos++] = encodeTable[context.ibitWorkArea << 2 & MASK_6BITS]; @@ -606,8 +582,8 @@ } break; default: - throw new IllegalStateException(sm.getString( - "base64.impossibleModulus", Integer.valueOf(context.modulus))); + throw new IllegalStateException( + sm.getString("base64.impossibleModulus", Integer.valueOf(context.modulus))); } context.currentLinePos += context.pos - savedPos; // keep track of current line position // if currentPos == 0 we are at the start of a line, so don't add CRLF @@ -618,12 +594,12 @@ } else { for (int i = 0; i < inAvail; i++) { final byte[] buffer = ensureBufferSize(encodeSize, context); - context.modulus = (context.modulus+1) % BYTES_PER_UNENCODED_BLOCK; + context.modulus = (context.modulus + 1) % BYTES_PER_UNENCODED_BLOCK; int b = in[inPos++]; if (b < 0) { b += 256; } - context.ibitWorkArea = (context.ibitWorkArea << 8) + b; // BITS_PER_BYTE + context.ibitWorkArea = (context.ibitWorkArea << 8) + b; // BITS_PER_BYTE if (0 == context.modulus) { // 3 bytes = 24 bits = 4 * 6 bits to extract buffer[context.pos++] = encodeTable[context.ibitWorkArea >> 18 & MASK_6BITS]; buffer[context.pos++] = encodeTable[context.ibitWorkArea >> 12 & MASK_6BITS]; @@ -643,8 +619,8 @@ /** * Returns whether or not the {@code octet} is in the Base64 alphabet. * - * @param octet - * The value to test + * @param octet The value to test + * * @return {@code true} if the value is defined in the Base64 alphabet {@code false} otherwise. */ @Override @@ -656,6 +632,7 @@ * Returns our current encode mode. True if we're URL-SAFE, false otherwise. * * @return true if we're in URL-SAFE mode, false otherwise. + * * @since 1.4 */ public boolean isUrlSafe() { diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/codec/binary/BaseNCodec.java tomcat10-10.1.52/java/org/apache/tomcat/util/codec/binary/BaseNCodec.java --- tomcat10-10.1.40/java/org/apache/tomcat/util/codec/binary/BaseNCodec.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/codec/binary/BaseNCodec.java 2026-01-23 19:33:36.000000000 +0000 @@ -23,7 +23,6 @@ /** * Abstract superclass for Base-N encoders and decoders. - * *

      * This class is thread-safe. *

      @@ -36,17 +35,16 @@ protected static final StringManager sm = StringManager.getManager(BaseNCodec.class); /** - * Holds thread context so classes can be thread-safe. - * - * This class is not itself thread-safe; each thread must allocate its own copy. + * Holds thread context so classes can be thread-safe. This class is not itself thread-safe; each thread must + * allocate its own copy. * * @since 1.7 */ static class Context { /** - * Placeholder for the bytes we're dealing with for our based logic. - * Bitwise operations store and extract the encoding or decoding from this variable. + * Placeholder for the bytes we're dealing with for our based logic. Bitwise operations store and extract the + * encoding or decoding from this variable. */ int ibitWorkArea; @@ -72,8 +70,8 @@ boolean eof; /** - * Variable tracks how many characters have been written to the current line. Only used when encoding. We use - * it to make sure each encoded line never goes beyond lineLength (if lineLength > 0). + * Variable tracks how many characters have been written to the current line. Only used when encoding. We use it + * to make sure each encoded line never goes beyond lineLength (if lineLength > 0). */ int currentLinePos; @@ -91,9 +89,10 @@ @SuppressWarnings("boxing") // OK to ignore boxing here @Override public String toString() { - return String.format("%s[buffer=%s, currentLinePos=%s, eof=%s, ibitWorkArea=%s, " + - "modulus=%s, pos=%s, readPos=%s]", this.getClass().getSimpleName(), HexUtils.toHexString(buffer), - currentLinePos, eof, ibitWorkArea, modulus, pos, readPos); + return String.format( + "%s[buffer=%s, currentLinePos=%s, eof=%s, ibitWorkArea=%s, " + "modulus=%s, pos=%s, readPos=%s]", + this.getClass().getSimpleName(), HexUtils.toHexString(buffer), currentLinePos, eof, ibitWorkArea, + modulus, pos, readPos); } } @@ -105,8 +104,7 @@ static final int EOF = -1; /** - * MIME chunk size per RFC 2045 section 6.8. - * + * MIME chunk size per RFC 2045 section 6.8. *

      * The {@value} character limit does not count the trailing CRLF, but counts all other characters, including any * equal signs. @@ -119,20 +117,18 @@ private static final int DEFAULT_BUFFER_RESIZE_FACTOR = 2; /** - * Defines the default buffer size - currently {@value} - * - must be large enough for at least one encoded block+separator + * Defines the default buffer size - currently {@value} - must be large enough for at least one encoded + * block+separator */ private static final int DEFAULT_BUFFER_SIZE = 128; /** * The maximum size buffer to allocate. - * - *

      This is set to the same size used in the JDK {@link java.util.ArrayList}:

      - *
      - * Some VMs reserve some header words in an array. - * Attempts to allocate larger arrays may result in - * OutOfMemoryError: Requested array size exceeds VM limit. - *
      + *

      + * This is set to the same size used in the JDK {@link java.util.ArrayList}: + *

      + *
      Some VMs reserve some header words in an array. Attempts to allocate larger arrays may result in + * OutOfMemoryError: Requested array size exceeds VM limit.
      */ private static final int MAX_BUFFER_SIZE = Integer.MAX_VALUE - 8; @@ -149,15 +145,16 @@ * * @see RFC 2045 section 2.1 */ - static final byte[] CHUNK_SEPARATOR = {'\r', '\n'}; + static final byte[] CHUNK_SEPARATOR = { '\r', '\n' }; /** - * Create a positive capacity at least as large the minimum required capacity. - * If the minimum capacity is negative then this throws an OutOfMemoryError as no array - * can be allocated. + * Create a positive capacity at least as large the minimum required capacity. If the minimum capacity is negative + * then this throws an OutOfMemoryError as no array can be allocated. * * @param minCapacity the minimum capacity + * * @return the capacity + * * @throws OutOfMemoryError if the {@code minCapacity} is negative */ private static int createPositiveCapacity(final int minCapacity) { @@ -178,9 +175,12 @@ /** * Increases our buffer by the {@link #DEFAULT_BUFFER_RESIZE_FACTOR}. - * @param context the context to be used + * + * @param context the context to be used * @param minCapacity the minimum required capacity + * * @return the resized byte[] buffer + * * @throws OutOfMemoryError if the {@code minCapacity} is negative */ private static byte[] resizeBuffer(final Context context, final int minCapacity) { @@ -209,8 +209,7 @@ private final int encodedBlockSize; /** - * Chunksize for encoding. Not used when decoding. - * A value of zero or less implies no chunking of the encoded data. + * Chunksize for encoding. Not used when decoding. A value of zero or less implies no chunking of the encoded data. * Rounded down to the nearest multiple of encodedBlockSize. */ protected final int lineLength; @@ -221,31 +220,31 @@ private final int chunkSeparatorLength; /** - * Note {@code lineLength} is rounded down to the nearest multiple of the encoded block size. - * If {@code chunkSeparatorLength} is zero, then chunking is disabled. + * Note {@code lineLength} is rounded down to the nearest multiple of the encoded block size. If + * {@code chunkSeparatorLength} is zero, then chunking is disabled. * - * @param unencodedBlockSize the size of an unencoded block (e.g. Base64 = 3) - * @param encodedBlockSize the size of an encoded block (e.g. Base64 = 4) - * @param lineLength if > 0, use chunking with a length {@code lineLength} + * @param unencodedBlockSize the size of an unencoded block (e.g. Base64 = 3) + * @param encodedBlockSize the size of an encoded block (e.g. Base64 = 4) + * @param lineLength if > 0, use chunking with a length {@code lineLength} * @param chunkSeparatorLength the chunk separator length, if relevant */ - protected BaseNCodec(final int unencodedBlockSize, final int encodedBlockSize, - final int lineLength, final int chunkSeparatorLength) { + protected BaseNCodec(final int unencodedBlockSize, final int encodedBlockSize, final int lineLength, + final int chunkSeparatorLength) { this(unencodedBlockSize, encodedBlockSize, lineLength, chunkSeparatorLength, PAD_DEFAULT); } /** - * Note {@code lineLength} is rounded down to the nearest multiple of the encoded block size. - * If {@code chunkSeparatorLength} is zero, then chunking is disabled. + * Note {@code lineLength} is rounded down to the nearest multiple of the encoded block size. If + * {@code chunkSeparatorLength} is zero, then chunking is disabled. * - * @param unencodedBlockSize the size of an unencoded block (e.g. Base64 = 3) - * @param encodedBlockSize the size of an encoded block (e.g. Base64 = 4) - * @param lineLength if > 0, use chunking with a length {@code lineLength} + * @param unencodedBlockSize the size of an unencoded block (e.g. Base64 = 3) + * @param encodedBlockSize the size of an encoded block (e.g. Base64 = 4) + * @param lineLength if > 0, use chunking with a length {@code lineLength} * @param chunkSeparatorLength the chunk separator length, if relevant - * @param pad byte used as padding byte. + * @param pad byte used as padding byte. */ - protected BaseNCodec(final int unencodedBlockSize, final int encodedBlockSize, - final int lineLength, final int chunkSeparatorLength, final byte pad) { + protected BaseNCodec(final int unencodedBlockSize, final int encodedBlockSize, final int lineLength, + final int chunkSeparatorLength, final byte pad) { this.unencodedBlockSize = unencodedBlockSize; this.encodedBlockSize = encodedBlockSize; final boolean useChunking = lineLength > 0 && chunkSeparatorLength > 0; @@ -258,19 +257,19 @@ * Returns the amount of buffered data available for reading. * * @param context the context to be used + * * @return The amount of buffered data available for reading. */ - int available(final Context context) { // package protected for access from I/O streams + int available(final Context context) { // package protected for access from I/O streams return hasData(context) ? context.pos - context.readPos : 0; } /** - * Tests a given byte array to see if it contains any characters within the alphabet or PAD. + * Tests a given byte array to see if it contains any characters within the alphabet or PAD. Intended for use in + * checking line-ending arrays * - * Intended for use in checking line-ending arrays + * @param arrayOctet byte array to test * - * @param arrayOctet - * byte array to test * @return {@code true} if any byte is a valid character in the alphabet or PAD; {@code false} otherwise */ protected boolean containsAlphabetOrPad(final byte[] arrayOctet) { @@ -288,8 +287,8 @@ /** * Decodes a byte[] containing characters in the Base-N alphabet. * - * @param pArray - * A byte array containing Base-N character data + * @param pArray A byte array containing Base-N character data + * * @return a byte array containing binary data */ public byte[] decode(final byte[] pArray) { @@ -314,8 +313,8 @@ /** * Decodes a String containing characters in the Base-N alphabet. * - * @param pArray - * A String containing Base-N character data + * @param pArray A String containing Base-N character data + * * @return a byte array containing binary data */ public byte[] decode(final String pArray) { @@ -325,8 +324,8 @@ /** * Encodes a byte[] containing binary data, into a byte[] containing characters in the alphabet. * - * @param pArray - * a byte array containing binary data + * @param pArray a byte array containing binary data + * * @return A byte array containing only the base N alphabetic character data */ public byte[] encode(final byte[] pArray) { @@ -337,16 +336,14 @@ } /** - * Encodes a byte[] containing binary data, into a byte[] containing - * characters in the alphabet. + * Encodes a byte[] containing binary data, into a byte[] containing characters in the alphabet. + * + * @param pArray a byte array containing binary data + * @param offset initial offset of the subarray. + * @param length length of the subarray. * - * @param pArray - * a byte array containing binary data - * @param offset - * initial offset of the subarray. - * @param length - * length of the subarray. * @return A byte array containing only the base N alphabetic character data + * * @since 1.11 */ public byte[] encode(final byte[] pArray, final int offset, final int length) { @@ -365,32 +362,35 @@ abstract void encode(byte[] pArray, int i, int length, Context context); /** - * Encodes a byte[] containing binary data, into a String containing characters in the appropriate alphabet. - * Uses UTF8 encoding. + * Encodes a byte[] containing binary data, into a String containing characters in the appropriate alphabet. Uses + * UTF8 encoding. * * @param pArray a byte array containing binary data + * * @return String containing only character data in the appropriate alphabet. + * * @since 1.5 - */ - public String encodeAsString(final byte[] pArray){ + */ + public String encodeAsString(final byte[] pArray) { return StringUtils.newStringUtf8(encode(pArray)); } /** * Ensure that the buffer has room for {@code size} bytes * - * @param size minimum spare space required + * @param size minimum spare space required * @param context the context to be used + * * @return the buffer */ - protected byte[] ensureBufferSize(final int size, final Context context){ + protected byte[] ensureBufferSize(final int size, final Context context) { if (context.buffer == null) { context.buffer = new byte[Math.max(size, getDefaultBufferSize())]; context.pos = 0; context.readPos = 0; // Overflow-conscious: - // x + y > z == x + y - z > 0 + // x + y > z == x + y - z > 0 } else if (context.pos + size - context.buffer.length > 0) { return resizeBuffer(context, context.pos + size); } @@ -411,16 +411,16 @@ * * @param pArray byte[] array which will later be encoded * - * @return amount of space needed to encode the supplied array. - * Returns a long since a max-len array will require > Integer.MAX_VALUE + * @return amount of space needed to encode the supplied array. Returns a long since a max-len array will require + * > Integer.MAX_VALUE */ public long getEncodedLength(final byte[] pArray) { // Calculate non-chunked size - rounded up to allow for padding // cast to long is needed to avoid possibility of overflow - long len = (pArray.length + unencodedBlockSize-1) / unencodedBlockSize * (long) encodedBlockSize; + long len = (pArray.length + unencodedBlockSize - 1) / unencodedBlockSize * (long) encodedBlockSize; if (lineLength > 0) { // We're using chunking // Round up to nearest multiple - len += (len + lineLength-1) / lineLength * chunkSeparatorLength; + len += (len + lineLength - 1) / lineLength * chunkSeparatorLength; } return len; } @@ -429,15 +429,15 @@ * Returns true if this object has buffered data for reading. * * @param context the context to be used + * * @return true if there is data still available for reading. */ - boolean hasData(final Context context) { // package protected for access from I/O streams + boolean hasData(final Context context) { // package protected for access from I/O streams return context.pos > context.readPos; } /** - * Returns whether or not the {@code octet} is in the current alphabet. - * Does not allow whitespace or pad. + * Returns whether or not the {@code octet} is in the current alphabet. Does not allow whitespace or pad. * * @param value The value to test * @@ -452,14 +452,11 @@ * Package private for access from I/O streams. *

      * - * @param b - * byte[] array to extract the buffered data into. - * @param bPos - * position in byte[] array to start extraction at. - * @param bAvail - * amount of bytes we're allowed to extract. We may extract fewer (if fewer are available). - * @param context - * the context to be used + * @param b byte[] array to extract the buffered data into. + * @param bPos position in byte[] array to start extraction at. + * @param bAvail amount of bytes we're allowed to extract. We may extract fewer (if fewer are available). + * @param context the context to be used + * * @return The number of bytes successfully extracted into the provided byte[] array. */ int readResults(final byte[] b, final int bPos, final int bAvail, final Context context) { diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/codec/binary/StringUtils.java tomcat10-10.1.52/java/org/apache/tomcat/util/codec/binary/StringUtils.java --- tomcat10-10.1.40/java/org/apache/tomcat/util/codec/binary/StringUtils.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/codec/binary/StringUtils.java 2026-01-23 19:33:36.000000000 +0000 @@ -23,11 +23,13 @@ * Converts String to and from bytes using the encodings required by the Java specification. These encodings are * specified in * Standard charsets. - * - *

      This class is immutable and thread-safe.

      + *

      + * This class is immutable and thread-safe. + *

      * * @see Charset * @see StandardCharsets + * * @since 1.4 * * @deprecated Unused. This class will be removed in Tomcat 11 onwards. @@ -38,10 +40,9 @@ /** * Calls {@link String#getBytes(Charset)} * - * @param string - * The string to encode (if null, return null). - * @param charset - * The {@link Charset} to encode the {@code String} + * @param string The string to encode (if null, return null). + * @param charset The {@link Charset} to encode the {@code String} + * * @return the encoded bytes */ private static byte[] getBytes(final String string, final Charset charset) { @@ -52,13 +53,15 @@ * Encodes the given string into a sequence of bytes using the UTF-8 charset, storing the result into a new byte * array. * - * @param string - * the String to encode, may be {@code null} + * @param string the String to encode, may be {@code null} + * * @return encoded bytes, or {@code null} if the input string was {@code null} - * @throws NullPointerException - * Thrown if {@link StandardCharsets#UTF_8} is not initialized, which should never happen - * since it is required by the Java platform specification. + * + * @throws NullPointerException Thrown if {@link StandardCharsets#UTF_8} is not initialized, which should never + * happen since it is required by the Java platform specification. + * * @since As of 1.7, throws {@link NullPointerException} instead of UnsupportedEncodingException + * * @see Charset */ public static byte[] getBytesUtf8(final String string) { @@ -68,14 +71,13 @@ /** * Constructs a new {@code String} by decoding the specified array of bytes using the given charset. * - * @param bytes - * The bytes to be decoded into characters - * @param charset - * The {@link Charset} to encode the {@code String}; not {@code null} - * @return A new {@code String} decoded from the specified array of bytes using the given charset, - * or {@code null} if the input byte array was {@code null}. - * @throws NullPointerException - * Thrown if charset is {@code null} + * @param bytes The bytes to be decoded into characters + * @param charset The {@link Charset} to encode the {@code String}; not {@code null} + * + * @return A new {@code String} decoded from the specified array of bytes using the given charset, or {@code null} + * if the input byte array was {@code null}. + * + * @throws NullPointerException Thrown if charset is {@code null} */ private static String newString(final byte[] bytes, final Charset charset) { return bytes == null ? null : new String(bytes, charset); @@ -84,13 +86,14 @@ /** * Constructs a new {@code String} by decoding the specified array of bytes using the US-ASCII charset. * - * @param bytes - * The bytes to be decoded into characters - * @return A new {@code String} decoded from the specified array of bytes using the US-ASCII charset, - * or {@code null} if the input byte array was {@code null}. - * @throws NullPointerException - * Thrown if {@link StandardCharsets#US_ASCII} is not initialized, which should never happen - * since it is required by the Java platform specification. + * @param bytes The bytes to be decoded into characters + * + * @return A new {@code String} decoded from the specified array of bytes using the US-ASCII charset, or + * {@code null} if the input byte array was {@code null}. + * + * @throws NullPointerException Thrown if {@link StandardCharsets#US_ASCII} is not initialized, which should never + * happen since it is required by the Java platform specification. + * * @since As of 1.7, throws {@link NullPointerException} instead of UnsupportedEncodingException */ public static String newStringUsAscii(final byte[] bytes) { @@ -100,13 +103,14 @@ /** * Constructs a new {@code String} by decoding the specified array of bytes using the UTF-8 charset. * - * @param bytes - * The bytes to be decoded into characters - * @return A new {@code String} decoded from the specified array of bytes using the UTF-8 charset, - * or {@code null} if the input byte array was {@code null}. - * @throws NullPointerException - * Thrown if {@link StandardCharsets#UTF_8} is not initialized, which should never happen since it is - * required by the Java platform specification. + * @param bytes The bytes to be decoded into characters + * + * @return A new {@code String} decoded from the specified array of bytes using the UTF-8 charset, or {@code null} + * if the input byte array was {@code null}. + * + * @throws NullPointerException Thrown if {@link StandardCharsets#UTF_8} is not initialized, which should never + * happen since it is required by the Java platform specification. + * * @since As of 1.7, throws {@link NullPointerException} instead of UnsupportedEncodingException */ public static String newStringUtf8(final byte[] bytes) { diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/codec/binary/package-info.java tomcat10-10.1.52/java/org/apache/tomcat/util/codec/binary/package-info.java --- tomcat10-10.1.40/java/org/apache/tomcat/util/codec/binary/package-info.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/codec/binary/package-info.java 2026-01-23 19:33:36.000000000 +0000 @@ -16,8 +16,6 @@ */ /** - * Base64 String encoding and decoding. - * - * Unused. This package will be removed in Tomcat 11 onwards. + * Base64 String encoding and decoding. Unused. This package will be removed in Tomcat 11 onwards. */ package org.apache.tomcat.util.codec.binary; diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/collections/CaseInsensitiveKeyMap.java tomcat10-10.1.52/java/org/apache/tomcat/util/collections/CaseInsensitiveKeyMap.java --- tomcat10-10.1.40/java/org/apache/tomcat/util/collections/CaseInsensitiveKeyMap.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/collections/CaseInsensitiveKeyMap.java 2026-01-23 19:33:36.000000000 +0000 @@ -27,11 +27,9 @@ import org.apache.tomcat.util.res.StringManager; /** - * A Map implementation that uses case-insensitive (using {@link - * Locale#ENGLISH}) strings as keys. + * A Map implementation that uses case-insensitive (using {@link Locale#ENGLISH}) strings as keys. *

      - * Keys must be instances of {@link String}. Note that this means that - * null keys are not permitted. + * Keys must be instances of {@link String}. Note that this means that null keys are not permitted. *

      * This implementation is not thread-safe. * @@ -39,8 +37,7 @@ */ public class CaseInsensitiveKeyMap extends AbstractMap { - private static final StringManager sm = - StringManager.getManager(CaseInsensitiveKeyMap.class); + private static final StringManager sm = StringManager.getManager(CaseInsensitiveKeyMap.class); private final Map map = new HashMap<>(); @@ -64,12 +61,11 @@ /** * {@inheritDoc} *

      - * Use this method with caution. If the input Map contains duplicate - * keys when the keys are compared in a case-insensitive manner then some - * values will be lost when inserting via this method. + * Use this method with caution. If the input Map contains duplicate keys when the keys are compared in a + * case-insensitive manner then some values will be lost when inserting via this method. */ @Override - public void putAll(Map m) { + public void putAll(Map m) { super.putAll(m); } @@ -87,7 +83,7 @@ @Override - public Set> entrySet() { + public Set> entrySet() { return new EntrySet<>(map.entrySet()); } @@ -126,8 +122,8 @@ } @Override - public Entry next() { - Entry entry = iterator.next(); + public Entry next() { + Entry entry = iterator.next(); return new EntryImpl<>(entry.getKey().getKey(), entry.getValue()); } diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/collections/ConcurrentCache.java tomcat10-10.1.52/java/org/apache/tomcat/util/collections/ConcurrentCache.java --- tomcat10-10.1.40/java/org/apache/tomcat/util/collections/ConcurrentCache.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/collections/ConcurrentCache.java 2026-01-23 19:33:36.000000000 +0000 @@ -20,7 +20,7 @@ import java.util.WeakHashMap; import java.util.concurrent.ConcurrentHashMap; -public final class ConcurrentCache { +public final class ConcurrentCache { private final int size; diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/collections/ConcurrentLruCache.java tomcat10-10.1.52/java/org/apache/tomcat/util/collections/ConcurrentLruCache.java --- tomcat10-10.1.40/java/org/apache/tomcat/util/collections/ConcurrentLruCache.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/collections/ConcurrentLruCache.java 2026-01-23 19:33:36.000000000 +0000 @@ -76,7 +76,7 @@ if (oldMap != null) { map.putAll(oldMap); } - } else { + } else { map = null; } } @@ -94,7 +94,7 @@ } - private static class LimitedLinkedHashMap extends LinkedHashMap { + private static class LimitedLinkedHashMap extends LinkedHashMap { private static final long serialVersionUID = 1L; private final int limit; diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/collections/ManagedConcurrentWeakHashMap.java tomcat10-10.1.52/java/org/apache/tomcat/util/collections/ManagedConcurrentWeakHashMap.java --- tomcat10-10.1.40/java/org/apache/tomcat/util/collections/ManagedConcurrentWeakHashMap.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/collections/ManagedConcurrentWeakHashMap.java 2026-01-23 19:33:36.000000000 +0000 @@ -30,23 +30,20 @@ import java.util.concurrent.ConcurrentMap; /** - * Concurrent hash map that holds its keys via weak references. Unlike - * WeakHashMap this class does not handle dead keys during common - * access operations, but expects you to call its {@link #maintain()} method + * Concurrent hash map that holds its keys via weak references. Unlike WeakHashMap this class does not + * handle dead keys during common access operations, but expects you to call its {@link #maintain()} method * periodically. Both keys and values are expected to be not-null. * * @param The type of keys used with the Map instance * @param The type of values used with the Map instance */ -public class ManagedConcurrentWeakHashMap extends AbstractMap implements - ConcurrentMap { +public class ManagedConcurrentWeakHashMap extends AbstractMap implements ConcurrentMap { - private final ConcurrentMap map = new ConcurrentHashMap<>(); + private final ConcurrentMap map = new ConcurrentHashMap<>(); private final ReferenceQueue queue = new ReferenceQueue<>(); /** - * Method, that has to be invoked periodically to clean dead keys from the - * map. + * Method, that has to be invoked periodically to clean dead keys from the map. */ public void maintain() { Key key; @@ -108,16 +105,14 @@ } /** - * Creates Key instance to be used to store values in the map. It is - * registered with the ReferenceQueue. + * Creates Key instance to be used to store values in the map. It is registered with the ReferenceQueue. */ private Key createStoreKey(Object key) { return new Key(key, queue); } /** - * Creates Key instance to be used only to lookup values in the map. It is - * not registered with the ReferenceQueue. + * Creates Key instance to be used only to lookup values in the map. It is not registered with the ReferenceQueue. */ private Key createLookupKey(Object key) { return new Key(key, null); @@ -213,7 +208,7 @@ } @Override - public Set> entrySet() { + public Set> entrySet() { return new AbstractSet<>() { @Override public boolean isEmpty() { @@ -226,10 +221,9 @@ } @Override - public Iterator> iterator() { + public Iterator> iterator() { return new Iterator<>() { - private final Iterator> it = map - .entrySet().iterator(); + private final Iterator> it = map.entrySet().iterator(); @Override public boolean hasNext() { @@ -237,9 +231,9 @@ } @Override - public Map.Entry next() { + public Map.Entry next() { return new Map.Entry<>() { - private final Map.Entry en = it.next(); + private final Map.Entry en = it.next(); @SuppressWarnings("unchecked") @Override diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/collections/SynchronizedQueue.java tomcat10-10.1.52/java/org/apache/tomcat/util/collections/SynchronizedQueue.java --- tomcat10-10.1.40/java/org/apache/tomcat/util/collections/SynchronizedQueue.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/collections/SynchronizedQueue.java 2026-01-23 19:33:36.000000000 +0000 @@ -17,11 +17,9 @@ package org.apache.tomcat.util.collections; /** - * This is intended as a (mostly) GC-free alternative to - * {@link java.util.concurrent.ConcurrentLinkedQueue} when the requirement is to - * create an unbounded queue with no requirement to shrink the queue. The aim is - * to provide the bare minimum of required functionality as quickly as possible - * with minimum garbage. + * This is intended as a (mostly) GC-free alternative to {@link java.util.concurrent.ConcurrentLinkedQueue} when the + * requirement is to create an unbounded queue with no requirement to shrink the queue. The aim is to provide the bare + * minimum of required functionality as quickly as possible with minimum garbage. * * @param The type of object managed by this queue */ diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/collections/SynchronizedStack.java tomcat10-10.1.52/java/org/apache/tomcat/util/collections/SynchronizedStack.java --- tomcat10-10.1.40/java/org/apache/tomcat/util/collections/SynchronizedStack.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/collections/SynchronizedStack.java 2026-01-23 19:33:36.000000000 +0000 @@ -17,11 +17,9 @@ package org.apache.tomcat.util.collections; /** - * This is intended as a (mostly) GC-free alternative to - * {@link java.util.Stack} when the requirement is to create a pool of re-usable - * objects with no requirement to shrink the pool. The aim is to provide the - * bare minimum of required functionality as quickly as possible with minimum - * garbage. + * This is intended as a (mostly) GC-free alternative to {@link java.util.Stack} when the requirement is to create a + * pool of re-usable objects with no requirement to shrink the pool. The aim is to provide the bare minimum of required + * functionality as quickly as possible with minimum garbage. * * @param The type of object managed by this stack */ diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/compat/Jre20Compat.java tomcat10-10.1.52/java/org/apache/tomcat/util/compat/Jre20Compat.java --- tomcat10-10.1.40/java/org/apache/tomcat/util/compat/Jre20Compat.java 1970-01-01 00:00:00.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/compat/Jre20Compat.java 2026-01-23 19:33:36.000000000 +0000 @@ -0,0 +1,66 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.tomcat.util.compat; + +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; + +import org.apache.juli.logging.Log; +import org.apache.juli.logging.LogFactory; +import org.apache.tomcat.util.res.StringManager; + +public class Jre20Compat extends Jre19Compat { + + private static final Log log = LogFactory.getLog(Jre20Compat.class); + private static final StringManager sm = StringManager.getManager(Jre20Compat.class); + + private static final boolean supported; + private static final Method setNamedGroupsMethod; + + + static { + Class c1 = null; + Method m1 = null; + + try { + c1 = Class.forName("javax.net.ssl.SSLParameters"); + m1 = c1.getMethod("setNamedGroups", String[].class); + } catch (NoSuchMethodException e) { + // Must be pre-Java 20 + log.debug(sm.getString("jre20Compat.javaPre20"), e); + } catch (ReflectiveOperationException e) { + // Should never happen + log.error(sm.getString("jre20Compat.unexpected"), e); + } + supported = (m1 != null); + setNamedGroupsMethod = m1; + } + + static boolean isSupported() { + return supported; + } + + @Override + public void setNamedGroupsMethod(Object sslParameters, String[] names) { + try { + setNamedGroupsMethod.invoke(sslParameters, (Object) names); + } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) { + throw new UnsupportedOperationException(e); + } + } + +} diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/compat/Jre21Compat.java tomcat10-10.1.52/java/org/apache/tomcat/util/compat/Jre21Compat.java --- tomcat10-10.1.40/java/org/apache/tomcat/util/compat/Jre21Compat.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/compat/Jre21Compat.java 2026-01-23 19:33:36.000000000 +0000 @@ -27,7 +27,7 @@ import org.apache.juli.logging.LogFactory; import org.apache.tomcat.util.res.StringManager; -public class Jre21Compat extends Jre19Compat { +public class Jre21Compat extends Jre20Compat { private static final Log log = LogFactory.getLog(Jre21Compat.class); private static final StringManager sm = StringManager.getManager(Jre21Compat.class); diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/compat/Jre22Compat.java tomcat10-10.1.52/java/org/apache/tomcat/util/compat/Jre22Compat.java --- tomcat10-10.1.40/java/org/apache/tomcat/util/compat/Jre22Compat.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/compat/Jre22Compat.java 2026-01-23 19:33:36.000000000 +0000 @@ -37,7 +37,9 @@ c1 = Class.forName("java.text.ListFormat"); } catch (ClassNotFoundException e) { // Must be pre-Java 22 - log.debug(sm.getString("jre22Compat.javaPre22"), e); + if (log.isDebugEnabled()) { + log.debug(sm.getString("jre22Compat.javaPre22"), e); + } } supported = (c1 != null); } diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/compat/JreCompat.java tomcat10-10.1.52/java/org/apache/tomcat/util/compat/JreCompat.java --- tomcat10-10.1.40/java/org/apache/tomcat/util/compat/JreCompat.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/compat/JreCompat.java 2026-01-23 19:33:36.000000000 +0000 @@ -48,6 +48,7 @@ private static final boolean jre12Available; private static final boolean jre16Available; private static final boolean jre19Available; + private static final boolean jre20Available; private static final boolean jre21Available; private static final boolean jre22Available; @@ -75,6 +76,7 @@ instance = new Jre22Compat(); jre22Available = true; jre21Available = true; + jre20Available = true; jre19Available = true; jre16Available = true; jre12Available = true; @@ -82,6 +84,15 @@ instance = new Jre21Compat(); jre22Available = false; jre21Available = true; + jre20Available = true; + jre19Available = true; + jre16Available = true; + jre12Available = true; + } else if (Jre20Compat.isSupported()) { + instance = new Jre20Compat(); + jre22Available = false; + jre21Available = false; + jre20Available = true; jre19Available = true; jre16Available = true; jre12Available = true; @@ -89,6 +100,7 @@ instance = new Jre19Compat(); jre22Available = false; jre21Available = false; + jre20Available = false; jre19Available = true; jre16Available = true; jre12Available = true; @@ -96,6 +108,7 @@ instance = new Jre16Compat(); jre22Available = false; jre21Available = false; + jre20Available = false; jre19Available = false; jre16Available = true; jre12Available = true; @@ -103,6 +116,7 @@ instance = new Jre12Compat(); jre22Available = false; jre21Available = false; + jre20Available = false; jre19Available = false; jre16Available = false; jre12Available = true; @@ -110,6 +124,7 @@ instance = new JreCompat(); jre22Available = false; jre21Available = false; + jre20Available = false; jre19Available = false; jre16Available = false; jre12Available = false; @@ -142,6 +157,11 @@ } + public static boolean isJre20Available() { + return jre20Available; + } + + public static boolean isJre21Available() { return jre21Available; } @@ -402,4 +422,14 @@ } } } + + /** + * TLS groups configuration from JSSE API in Java 20. + * @param sslParameters the parameters object + * @param names the names of the groups to enable + */ + public void setNamedGroupsMethod(Object sslParameters, String[] names) { + throw new UnsupportedOperationException(sm.getString("jreCompat.noNamedGroups")); + } + } diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/concurrent/KeyedReentrantReadWriteLock.java tomcat10-10.1.52/java/org/apache/tomcat/util/concurrent/KeyedReentrantReadWriteLock.java --- tomcat10-10.1.40/java/org/apache/tomcat/util/concurrent/KeyedReentrantReadWriteLock.java 1970-01-01 00:00:00.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/concurrent/KeyedReentrantReadWriteLock.java 2026-01-23 19:33:36.000000000 +0000 @@ -0,0 +1,179 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.tomcat.util.concurrent; + +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.concurrent.locks.Condition; +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReadWriteLock; +import java.util.concurrent.locks.ReentrantReadWriteLock; +import java.util.function.Function; + +import org.apache.tomcat.util.res.StringManager; + +/** + * Provides a reentrant read/write lock for a given key. Any locks obtained from an instance of this class using the + * same key will use the same underlying reentrant read/write lock as long as at least one lock for that key remains in + * use. Once no locks are in use for the given key, the lock is eligible for GC and the next lock obtained using that + * key will use a new underlying reentrant read/write lock. + *

      + * The class is used when Tomcat needs to manage concurrent access to components identified by a key (e.g. sessions). + *

      + * The map of keys to locks is maintained so that locks are created as required and removed when no longer used. + *

      + * The locks provided by this class only implement {@code Lock#lock()} and {@code Lock#unlock()}. All other methods will + * throw {@code UnsupportedOperationException}. + */ +public class KeyedReentrantReadWriteLock { + + private final Map locksMap = new HashMap<>(); + + + /** + * Obtain the reentrant read/write lock for the given key. + * + * @param key The key for which the lock should be obtained + * + * @return A reentrant read/write lock for the given key + */ + public ReadWriteLock getLock(String key) { + return new ReadWriteLockImpl(locksMap, key); + } + + + /* + * Reentrant read/write lock implementation that is passed back to the caller. It provides the lock wrappers that + * track usage. + */ + private static class ReadWriteLockImpl implements ReadWriteLock { + + private final Map locksMap; + private final String key; + private volatile Lock readLock; + private volatile Lock writeLock; + + ReadWriteLockImpl(Map locksMap, String key) { + this.locksMap = locksMap; + this.key = key; + } + + @Override + public Lock readLock() { + if (readLock == null) { + readLock = new LockImpl(locksMap, key, ReentrantReadWriteLock::readLock); + } + return readLock; + } + + @Override + public Lock writeLock() { + if (writeLock == null) { + writeLock = new LockImpl(locksMap, key, ReentrantReadWriteLock::writeLock); + } + return writeLock; + } + } + + + /* + * Lock wrapper implementation that provides both read locks and write locks from the underlying lock and tracks + * their usage. Most of the methods throw UnsupportedOperationException as Tomcat does not (currently) require + * implementations of those methods. + */ + private static class LockImpl implements Lock { + + private static final StringManager sm = StringManager.getManager(LockImpl.class); + + private final Map locksMap; + private final String key; + private final Function function; + + LockImpl(Map locksMap, String key, Function function) { + this.locksMap = locksMap; + this.key = key; + this.function = function; + } + + @Override + public void lock() { + CountedLock countedLock = null; + synchronized (locksMap) { + // Lookup / create the counted lock for the given key + countedLock = locksMap.compute(key, (k, v) -> v == null ? new CountedLock() : v); + // Increment usage count inside the sync block to ensure other threads are aware key is in use. + countedLock.count.incrementAndGet(); + } + // Lock outside of the sync block in case the call to lock() blocks. + function.apply(countedLock.reentrantLock).lock(); + } + + @Override + public void unlock() { + CountedLock countedLock = null; + // Unlocking so a lock should exist in the map for the given key. + synchronized (locksMap) { + countedLock = locksMap.get(key); + } + if (countedLock == null) { + throw new IllegalStateException(sm.getString("lockImpl.unlockWithoutLock")); + } + // No need to unlock inside sync block, so don't. + function.apply(countedLock.reentrantLock).unlock(); + synchronized (locksMap) { + /* + * Decrement usage count and check for zero inside the sync block to ensure usage tracking is consistent + * across multiple threads. + */ + if (countedLock.count.decrementAndGet() == 0) { + locksMap.remove(key); + } + } + } + + @Override + public void lockInterruptibly() throws InterruptedException { + throw new UnsupportedOperationException(); + } + + @Override + public boolean tryLock() { + throw new UnsupportedOperationException(); + } + + @Override + public boolean tryLock(long time, TimeUnit unit) throws InterruptedException { + throw new UnsupportedOperationException(); + } + + @Override + public Condition newCondition() { + throw new UnsupportedOperationException(); + } + } + + + /* + * Holds the underlying reentrant read/write lock and the counter that tracks usage. + */ + private static class CountedLock { + AtomicInteger count = new AtomicInteger(); + ReentrantReadWriteLock reentrantLock = new ReentrantReadWriteLock(); + } +} diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/concurrent/LocalStrings.properties tomcat10-10.1.52/java/org/apache/tomcat/util/concurrent/LocalStrings.properties --- tomcat10-10.1.40/java/org/apache/tomcat/util/concurrent/LocalStrings.properties 1970-01-01 00:00:00.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/concurrent/LocalStrings.properties 2026-01-23 19:33:36.000000000 +0000 @@ -0,0 +1,19 @@ +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# Do not edit this file directly. +# To edit translations see: https://tomcat.apache.org/getinvolved.html#Translations + +lockImpl.unlockWithoutLock=An attempt was made to release a lock without first obtaining the lock diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/concurrent/LocalStrings_fr.properties tomcat10-10.1.52/java/org/apache/tomcat/util/concurrent/LocalStrings_fr.properties --- tomcat10-10.1.40/java/org/apache/tomcat/util/concurrent/LocalStrings_fr.properties 1970-01-01 00:00:00.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/concurrent/LocalStrings_fr.properties 2026-01-23 19:33:36.000000000 +0000 @@ -0,0 +1,19 @@ +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# Do not edit this file directly. +# To edit translations see: https://tomcat.apache.org/getinvolved.html#Translations + +lockImpl.unlockWithoutLock=Une tentative pour rendre le verrou a été faite sans avoir d'abord obtenu le verrou diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/concurrent/LocalStrings_ja.properties tomcat10-10.1.52/java/org/apache/tomcat/util/concurrent/LocalStrings_ja.properties --- tomcat10-10.1.40/java/org/apache/tomcat/util/concurrent/LocalStrings_ja.properties 1970-01-01 00:00:00.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/concurrent/LocalStrings_ja.properties 2026-01-23 19:33:36.000000000 +0000 @@ -0,0 +1,19 @@ +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# Do not edit this file directly. +# To edit translations see: https://tomcat.apache.org/getinvolved.html#Translations + +lockImpl.unlockWithoutLock=ロックを取得せずにロックを解除しようとしました diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/descriptor/Constants.java tomcat10-10.1.52/java/org/apache/tomcat/util/descriptor/Constants.java --- tomcat10-10.1.40/java/org/apache/tomcat/util/descriptor/Constants.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/descriptor/Constants.java 2026-01-23 19:33:36.000000000 +0000 @@ -18,8 +18,7 @@ public class Constants { - public static final String PACKAGE_NAME = - Constants.class.getPackage().getName(); + public static final String PACKAGE_NAME = Constants.class.getPackage().getName(); public static final boolean IS_SECURITY_ENABLED = (System.getSecurityManager() != null); } diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/descriptor/DigesterFactory.java tomcat10-10.1.52/java/org/apache/tomcat/util/descriptor/DigesterFactory.java --- tomcat10-10.1.40/java/org/apache/tomcat/util/descriptor/DigesterFactory.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/descriptor/DigesterFactory.java 2026-01-23 19:33:36.000000000 +0000 @@ -31,13 +31,11 @@ import org.xml.sax.ext.EntityResolver2; /** - * Wrapper class around the Digester that hide Digester's initialization - * details. + * Wrapper class around the Digester that hide Digester's initialization details. */ public class DigesterFactory { - private static final StringManager sm = - StringManager.getManager(Constants.PACKAGE_NAME); + private static final StringManager sm = StringManager.getManager(Constants.PACKAGE_NAME); private static final Class CLASS_SERVLET_CONTEXT; private static final Class CLASS_JSP_CONTEXT; @@ -55,20 +53,18 @@ /** - * Mapping of well-known public IDs used by the Servlet API to the matching - * local resource. + * Mapping of well-known public IDs used by the Servlet API to the matching local resource. */ public static final Map SERVLET_API_PUBLIC_IDS; /** - * Mapping of well-known system IDs used by the Servlet API to the matching - * local resource. + * Mapping of well-known system IDs used by the Servlet API to the matching local resource. */ public static final Map SERVLET_API_SYSTEM_IDS; static { - Map publicIds = new HashMap<>(); - Map systemIds = new HashMap<>(); + Map publicIds = new HashMap<>(); + Map systemIds = new HashMap<>(); // W3C add(publicIds, XmlIdentifiers.XSD_10_PUBLIC, locationFor("XMLSchema.dtd")); @@ -149,7 +145,7 @@ SERVLET_API_SYSTEM_IDS = Collections.unmodifiableMap(systemIds); } - private static void addSelf(Map ids, String id) { + private static void addSelf(Map ids, String id) { String location = locationFor(id); if (location != null) { ids.put(id, location); @@ -186,22 +182,21 @@ /** * Create a Digester parser. - * @param xmlValidation turn on/off xml validation + * + * @param xmlValidation turn on/off xml validation * @param xmlNamespaceAware turn on/off namespace validation - * @param rule an instance of RuleSet used for parsing the xml. - * @param blockExternal turn on/off the blocking of external resources + * @param rule an instance of RuleSet used for parsing the xml. + * @param blockExternal turn on/off the blocking of external resources + * * @return a new digester */ - public static Digester newDigester(boolean xmlValidation, - boolean xmlNamespaceAware, - RuleSet rule, - boolean blockExternal) { + public static Digester newDigester(boolean xmlValidation, boolean xmlNamespaceAware, RuleSet rule, + boolean blockExternal) { Digester digester = new Digester(); digester.setNamespaceAware(xmlNamespaceAware); digester.setValidating(xmlValidation); digester.setUseContextClassLoader(true); - EntityResolver2 resolver = new LocalResolver(SERVLET_API_PUBLIC_IDS, - SERVLET_API_SYSTEM_IDS, blockExternal); + EntityResolver2 resolver = new LocalResolver(SERVLET_API_PUBLIC_IDS, SERVLET_API_SYSTEM_IDS, blockExternal); digester.setEntityResolver(resolver); if (rule != null) { digester.addRuleSet(rule); diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/descriptor/LocalResolver.java tomcat10-10.1.52/java/org/apache/tomcat/util/descriptor/LocalResolver.java --- tomcat10-10.1.40/java/org/apache/tomcat/util/descriptor/LocalResolver.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/descriptor/LocalResolver.java 2026-01-23 19:33:36.000000000 +0000 @@ -34,14 +34,10 @@ */ public class LocalResolver implements EntityResolver2 { - private static final StringManager sm = - StringManager.getManager(Constants.PACKAGE_NAME); + private static final StringManager sm = StringManager.getManager(Constants.PACKAGE_NAME); - private static final String[] JAVA_EE_NAMESPACES = { - XmlIdentifiers.JAVAEE_1_4_NS, - XmlIdentifiers.JAVAEE_5_NS, - XmlIdentifiers.JAVAEE_7_NS, - XmlIdentifiers.JAKARTAEE_9_NS}; + private static final String[] JAVA_EE_NAMESPACES = { XmlIdentifiers.JAVAEE_1_4_NS, XmlIdentifiers.JAVAEE_5_NS, + XmlIdentifiers.JAVAEE_7_NS, XmlIdentifiers.JAKARTAEE_9_NS }; private final Map publicIds; @@ -49,19 +45,14 @@ private final boolean blockExternal; /** - * Constructor providing mappings of public and system identifiers to local - * resources. Each map contains a mapping from a well-known identifier to a - * URL for a local resource path. + * Constructor providing mappings of public and system identifiers to local resources. Each map contains a mapping + * from a well-known identifier to a URL for a local resource path. * - * @param publicIds mapping of well-known public identifiers to local - * resources - * @param systemIds mapping of well-known system identifiers to local - * resources - * @param blockExternal are external resources blocked that are not - * well-known + * @param publicIds mapping of well-known public identifiers to local resources + * @param systemIds mapping of well-known system identifiers to local resources + * @param blockExternal are external resources blocked that are not well-known */ - public LocalResolver(Map publicIds, - Map systemIds, boolean blockExternal) { + public LocalResolver(Map publicIds, Map systemIds, boolean blockExternal) { this.publicIds = publicIds; this.systemIds = systemIds; this.blockExternal = blockExternal; @@ -69,15 +60,14 @@ @Override - public InputSource resolveEntity(String publicId, String systemId) - throws SAXException, IOException { + public InputSource resolveEntity(String publicId, String systemId) throws SAXException, IOException { return resolveEntity(null, publicId, null, systemId); } @Override - public InputSource resolveEntity(String name, String publicId, - String base, String systemId) throws SAXException, IOException { + public InputSource resolveEntity(String name, String publicId, String base, String systemId) + throws SAXException, IOException { // First try resolving using the publicId String resolved = publicIds.get(publicId); @@ -89,8 +79,7 @@ // If there is no systemId, can't try anything else if (systemId == null) { - throw new FileNotFoundException(sm.getString("localResolver.unresolvedEntity", - name, publicId, null, base)); + throw new FileNotFoundException(sm.getString("localResolver.unresolvedEntity", name, publicId, null, base)); } // Try resolving with the supplied systemId @@ -149,14 +138,12 @@ } } - throw new FileNotFoundException(sm.getString("localResolver.unresolvedEntity", - name, publicId, systemId, base)); + throw new FileNotFoundException(sm.getString("localResolver.unresolvedEntity", name, publicId, systemId, base)); } @Override - public InputSource getExternalSubset(String name, String baseURI) - throws SAXException, IOException { + public InputSource getExternalSubset(String name, String baseURI) throws SAXException, IOException { return null; } } diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/descriptor/XmlErrorHandler.java tomcat10-10.1.52/java/org/apache/tomcat/util/descriptor/XmlErrorHandler.java --- tomcat10-10.1.40/java/org/apache/tomcat/util/descriptor/XmlErrorHandler.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/descriptor/XmlErrorHandler.java 2026-01-23 19:33:36.000000000 +0000 @@ -27,8 +27,7 @@ public class XmlErrorHandler implements ErrorHandler { - private static final StringManager sm = - StringManager.getManager(Constants.PACKAGE_NAME); + private static final StringManager sm = StringManager.getManager(Constants.PACKAGE_NAME); private final List errors = new ArrayList<>(); @@ -64,12 +63,10 @@ public void logFindings(Log log, String source) { for (SAXParseException e : getWarnings()) { - log.warn(sm.getString( - "xmlErrorHandler.warning", e.getMessage(), source)); + log.warn(sm.getString("xmlErrorHandler.warning", e.getMessage(), source)); } for (SAXParseException e : getErrors()) { - log.warn(sm.getString( - "xmlErrorHandler.error", e.getMessage(), source)); + log.warn(sm.getString("xmlErrorHandler.error", e.getMessage(), source)); } } } diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/descriptor/XmlIdentifiers.java tomcat10-10.1.52/java/org/apache/tomcat/util/descriptor/XmlIdentifiers.java --- tomcat10-10.1.40/java/org/apache/tomcat/util/descriptor/XmlIdentifiers.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/descriptor/XmlIdentifiers.java 2026-01-23 19:33:36.000000000 +0000 @@ -17,43 +17,32 @@ package org.apache.tomcat.util.descriptor; /** - * Defines constants for well-known Public and System identifiers documented by - * the Servlet and JSP specifications. + * Defines constants for well-known Public and System identifiers documented by the Servlet and JSP specifications. */ public final class XmlIdentifiers { // from W3C public static final String XML_2001_XSD = "http://www.w3.org/2001/xml.xsd"; public static final String DATATYPES_PUBLIC = "datatypes"; - public static final String XSD_10_PUBLIC = - "-//W3C//DTD XMLSCHEMA 200102//EN"; + public static final String XSD_10_PUBLIC = "-//W3C//DTD XMLSCHEMA 200102//EN"; // from J2EE 1.2 - public static final String WEB_22_PUBLIC = - "-//Sun Microsystems, Inc.//DTD Web Application 2.2//EN"; - public static final String WEB_22_SYSTEM = - "http://java.sun.com/dtd/web-app_2_2.dtd"; - public static final String TLD_11_PUBLIC = - "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.1//EN"; - public static final String TLD_11_SYSTEM = - "http://java.sun.com/dtd/web-jsptaglibrary_1_1.dtd"; + public static final String WEB_22_PUBLIC = "-//Sun Microsystems, Inc.//DTD Web Application 2.2//EN"; + public static final String WEB_22_SYSTEM = "http://java.sun.com/dtd/web-app_2_2.dtd"; + public static final String TLD_11_PUBLIC = "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.1//EN"; + public static final String TLD_11_SYSTEM = "http://java.sun.com/dtd/web-jsptaglibrary_1_1.dtd"; // from J2EE 1.3 - public static final String WEB_23_PUBLIC = - "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"; - public static final String WEB_23_SYSTEM = - "http://java.sun.com/dtd/web-app_2_3.dtd"; - public static final String TLD_12_PUBLIC = - "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.2//EN"; - public static final String TLD_12_SYSTEM = - "http://java.sun.com/dtd/web-jsptaglibrary_1_2.dtd"; + public static final String WEB_23_PUBLIC = "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"; + public static final String WEB_23_SYSTEM = "http://java.sun.com/dtd/web-app_2_3.dtd"; + public static final String TLD_12_PUBLIC = "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.2//EN"; + public static final String TLD_12_SYSTEM = "http://java.sun.com/dtd/web-jsptaglibrary_1_2.dtd"; // from J2EE 1.4 public static final String JAVAEE_1_4_NS = "http://java.sun.com/xml/ns/j2ee"; public static final String WEB_24_XSD = JAVAEE_1_4_NS + "/web-app_2_4.xsd"; public static final String TLD_20_XSD = JAVAEE_1_4_NS + "/web-jsptaglibrary_2_0.xsd"; - public static final String WEBSERVICES_11_XSD = - "http://www.ibm.com/webservices/xsd/j2ee_web_services_1_1.xsd"; + public static final String WEBSERVICES_11_XSD = "http://www.ibm.com/webservices/xsd/j2ee_web_services_1_1.xsd"; // from JavaEE 5 public static final String JAVAEE_5_NS = "http://java.sun.com/xml/ns/javaee"; diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/descriptor/tagplugin/TagPluginParser.java tomcat10-10.1.52/java/org/apache/tomcat/util/descriptor/tagplugin/TagPluginParser.java --- tomcat10-10.1.40/java/org/apache/tomcat/util/descriptor/tagplugin/TagPluginParser.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/descriptor/tagplugin/TagPluginParser.java 2026-01-23 19:33:36.000000000 +0000 @@ -40,11 +40,10 @@ private final Log log = LogFactory.getLog(TagPluginParser.class); // must not be static private static final String PREFIX = "tag-plugins/tag-plugin"; private final Digester digester; - private final Map plugins = new HashMap<>(); + private final Map plugins = new HashMap<>(); public TagPluginParser(ServletContext context, boolean blockExternal) { - digester = DigesterFactory.newDigester( - false, false, new TagPluginRuleSet(), blockExternal); + digester = DigesterFactory.newDigester(false, false, new TagPluginRuleSet(), blockExternal); digester.setClassLoader(context.getClassLoader()); } @@ -74,7 +73,7 @@ plugins.put(tagClass, pluginClass); } - public Map getPlugins() { + public Map getPlugins() { return plugins; } diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/descriptor/tld/ImplicitTldRuleSet.java tomcat10-10.1.52/java/org/apache/tomcat/util/descriptor/tld/ImplicitTldRuleSet.java --- tomcat10-10.1.40/java/org/apache/tomcat/util/descriptor/tld/ImplicitTldRuleSet.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/descriptor/tld/ImplicitTldRuleSet.java 2026-01-23 19:33:36.000000000 +0000 @@ -23,8 +23,7 @@ import org.xml.sax.Attributes; /** - * RulesSet for digesting implicit.tld files. - * Only version information used and short names are allowed. + * RulesSet for digesting implicit.tld files. Only version information used and short names are allowed. */ public class ImplicitTldRuleSet implements RuleSet { diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/descriptor/tld/TagFileXml.java tomcat10-10.1.52/java/org/apache/tomcat/util/descriptor/tld/TagFileXml.java --- tomcat10-10.1.40/java/org/apache/tomcat/util/descriptor/tld/TagFileXml.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/descriptor/tld/TagFileXml.java 2026-01-23 19:33:36.000000000 +0000 @@ -17,9 +17,8 @@ package org.apache.tomcat.util.descriptor.tld; /** - * Bare-bone model of a tag file loaded from a TLD. - * This does not contain the tag-specific attributes that requiring parsing - * the actual tag file to derive. + * Bare-bone model of a tag file loaded from a TLD. This does not contain the tag-specific attributes that requiring + * parsing the actual tag file to derive. */ public class TagFileXml { private String name; diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/descriptor/tld/TagXml.java tomcat10-10.1.52/java/org/apache/tomcat/util/descriptor/tld/TagXml.java --- tomcat10-10.1.40/java/org/apache/tomcat/util/descriptor/tld/TagXml.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/descriptor/tld/TagXml.java 2026-01-23 19:33:36.000000000 +0000 @@ -24,10 +24,8 @@ import jakarta.servlet.jsp.tagext.TagVariableInfo; /** - * Model of a tag define in a tag library descriptor. - * This represents the information as parsed from the XML but differs from - * TagInfo in that it does not provide a link back to the tag library that - * defined it. + * Model of a tag define in a tag library descriptor. This represents the information as parsed from the XML but differs + * from TagInfo in that it does not provide a link back to the tag library that defined it. */ public class TagXml { private String name; diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/descriptor/tld/TaglibXml.java tomcat10-10.1.52/java/org/apache/tomcat/util/descriptor/tld/TaglibXml.java --- tomcat10-10.1.40/java/org/apache/tomcat/util/descriptor/tld/TaglibXml.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/descriptor/tld/TaglibXml.java 2026-01-23 19:33:36.000000000 +0000 @@ -24,11 +24,9 @@ /** * Common representation of a Tag Library Descriptor (TLD) XML file. *

      - * This stores the raw result of parsing an TLD XML file, flattening different - * version of the descriptors to a common format. This is different to a - * TagLibraryInfo instance that would be passed to a tag validator in that it - * does not contain the uri and prefix values used by a JSP to reference this - * tag library. + * This stores the raw result of parsing an TLD XML file, flattening different version of the descriptors to a common + * format. This is different to a TagLibraryInfo instance that would be passed to a tag validator in that it does not + * contain the uri and prefix values used by a JSP to reference this tag library. */ public class TaglibXml { private String tlibVersion; diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/descriptor/tld/TldParser.java tomcat10-10.1.52/java/org/apache/tomcat/util/descriptor/tld/TldParser.java --- tomcat10-10.1.40/java/org/apache/tomcat/util/descriptor/tld/TldParser.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/descriptor/tld/TldParser.java 2026-01-23 19:33:36.000000000 +0000 @@ -39,15 +39,12 @@ private final Log log = LogFactory.getLog(TldParser.class); // must not be static private final Digester digester; - public TldParser(boolean namespaceAware, boolean validation, - boolean blockExternal) { + public TldParser(boolean namespaceAware, boolean validation, boolean blockExternal) { this(namespaceAware, validation, new TldRuleSet(), blockExternal); } - public TldParser(boolean namespaceAware, boolean validation, RuleSet ruleSet, - boolean blockExternal) { - digester = DigesterFactory.newDigester( - validation, namespaceAware, ruleSet, blockExternal); + public TldParser(boolean namespaceAware, boolean validation, RuleSet ruleSet, boolean blockExternal) { + digester = DigesterFactory.newDigester(validation, namespaceAware, ruleSet, blockExternal); } public TaglibXml parse(TldResourcePath path) throws IOException, SAXException { diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/descriptor/tld/TldResourcePath.java tomcat10-10.1.52/java/org/apache/tomcat/util/descriptor/tld/TldResourcePath.java --- tomcat10-10.1.40/java/org/apache/tomcat/util/descriptor/tld/TldResourcePath.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/descriptor/tld/TldResourcePath.java 2026-01-23 19:33:36.000000000 +0000 @@ -28,17 +28,15 @@ /** * A TLD Resource Path as defined in JSP 7.3.2. *

      - * This encapsulates references to Tag Library Descriptors that can be located - * in different places: + * This encapsulates references to Tag Library Descriptors that can be located in different places: *

        *
      • As resources within an application
      • *
      • As entries in JAR files included in the application
      • *
      • As resources provided by the container
      • *
      - * When configuring a mapping from a well-known URI to a TLD, a user is allowed - * to specify just the name of a JAR file that implicitly contains a TLD in - * META-INF/taglib.tld. Such a mapping must be explicitly converted - * to a URL and entryName when using this implementation. + * When configuring a mapping from a well-known URI to a TLD, a user is allowed to specify just the name of a JAR file + * that implicitly contains a TLD in META-INF/taglib.tld. Such a mapping must be explicitly converted to a + * URL and entryName when using this implementation. */ public class TldResourcePath { private final URL url; @@ -78,19 +76,18 @@ } /** - * Returns the path within the web application, if any, that the resource - * returned by {@link #getUrl()} was obtained from. + * Returns the path within the web application, if any, that the resource returned by {@link #getUrl()} was obtained + * from. * - * @return the web application path or @null if the resource is not - * located within a web application + * @return the web application path or @null if the resource is not located within a web application */ public String getWebappPath() { return webappPath; } /** - * Returns the name of the JAR entry that contains the TLD. - * May be null to indicate the URL refers directly to the TLD itself. + * Returns the name of the JAR entry that contains the TLD. May be null to indicate the URL refers directly to the + * TLD itself. * * @return the name of the JAR entry that contains the TLD */ @@ -99,9 +96,8 @@ } /** - * Return the external form of the URL representing this TLD. - * This can be used as a canonical location for the TLD itself, for example, - * as the systemId to use when parsing its XML. + * Return the external form of the URL representing this TLD. This can be used as a canonical location for the TLD + * itself, for example, as the systemId to use when parsing its XML. * * @return the external form of the URL representing this TLD */ @@ -117,6 +113,7 @@ * Opens a stream to access the TLD. * * @return a stream containing the TLD content + * * @throws IOException if there was a problem opening the stream */ public InputStream openStream() throws IOException { @@ -156,8 +153,7 @@ TldResourcePath other = (TldResourcePath) o; - return url.equals(other.url) && - Objects.equals(webappPath, other.webappPath) && + return url.equals(other.url) && Objects.equals(webappPath, other.webappPath) && Objects.equals(entryName, other.entryName); } diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/descriptor/tld/TldRuleSet.java tomcat10-10.1.52/java/org/apache/tomcat/util/descriptor/tld/TldRuleSet.java --- tomcat10-10.1.40/java/org/apache/tomcat/util/descriptor/tld/TldRuleSet.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/descriptor/tld/TldRuleSet.java 2026-01-23 19:33:36.000000000 +0000 @@ -90,29 +90,23 @@ digester.addRule(TAG_PREFIX + "/variable", new ScriptVariableRule()); digester.addCallMethod(TAG_PREFIX + "/variable/name-given", "setNameGiven", 0); - digester.addCallMethod(TAG_PREFIX + "/variable/name-from-attribute", - "setNameFromAttribute", 0); + digester.addCallMethod(TAG_PREFIX + "/variable/name-from-attribute", "setNameFromAttribute", 0); digester.addCallMethod(TAG_PREFIX + "/variable/variable-class", "setClassName", 0); - digester.addRule(TAG_PREFIX + "/variable/declare", - new GenericBooleanRule(Variable.class, "setDeclare")); + digester.addRule(TAG_PREFIX + "/variable/declare", new GenericBooleanRule(Variable.class, "setDeclare")); digester.addCallMethod(TAG_PREFIX + "/variable/scope", "setScope", 0); digester.addRule(TAG_PREFIX + "/attribute", new TagAttributeRule()); digester.addCallMethod(TAG_PREFIX + "/attribute/description", "setDescription", 0); digester.addCallMethod(TAG_PREFIX + "/attribute/name", "setName", 0); - digester.addRule(TAG_PREFIX + "/attribute/required", - new GenericBooleanRule(Attribute.class, "setRequired")); + digester.addRule(TAG_PREFIX + "/attribute/required", new GenericBooleanRule(Attribute.class, "setRequired")); digester.addRule(TAG_PREFIX + "/attribute/rtexprvalue", new GenericBooleanRule(Attribute.class, "setRequestTime")); digester.addCallMethod(TAG_PREFIX + "/attribute/type", "setType", 0); digester.addCallMethod(TAG_PREFIX + "/attribute/deferred-value", "setDeferredValue"); - digester.addCallMethod(TAG_PREFIX + "/attribute/deferred-value/type", - "setExpectedTypeName", 0); + digester.addCallMethod(TAG_PREFIX + "/attribute/deferred-value/type", "setExpectedTypeName", 0); digester.addCallMethod(TAG_PREFIX + "/attribute/deferred-method", "setDeferredMethod"); - digester.addCallMethod(TAG_PREFIX + "/attribute/deferred-method/method-signature", - "setMethodSignature", 0); - digester.addRule(TAG_PREFIX + "/attribute/fragment", - new GenericBooleanRule(Attribute.class, "setFragment")); + digester.addCallMethod(TAG_PREFIX + "/attribute/deferred-method/method-signature", "setMethodSignature", 0); + digester.addRule(TAG_PREFIX + "/attribute/fragment", new GenericBooleanRule(Attribute.class, "setFragment")); digester.addRule(TAG_PREFIX + "/dynamic-attributes", new GenericBooleanRule(TagXml.class, "setDynamicAttributes")); @@ -154,8 +148,10 @@ StringBuilder code = digester.getGeneratedCode(); if (code != null) { code.append(System.lineSeparator()); - code.append(TldRuleSet.class.getName()).append(".Attribute ").append(digester.toVariableName(attribute)).append(" = new "); - code.append(TldRuleSet.class.getName()).append(".Attribute").append('(').append(Boolean.toString(allowShortNames)); + code.append(TldRuleSet.class.getName()).append(".Attribute ").append(digester.toVariableName(attribute)) + .append(" = new "); + code.append(TldRuleSet.class.getName()).append(".Attribute").append('(') + .append(Boolean.toString(allowShortNames)); code.append(");").append(System.lineSeparator()); } } @@ -293,17 +289,8 @@ type = "java.lang.String"; } - return new TagAttributeInfo( - name, - required, - type, - requestTime, - fragment, - description, - deferredValue, - deferredMethod, - expectedTypeName, - methodSignature); + return new TagAttributeInfo(name, required, type, requestTime, fragment, description, deferredValue, + deferredMethod, expectedTypeName, methodSignature); } } @@ -316,8 +303,10 @@ StringBuilder code = digester.getGeneratedCode(); if (code != null) { code.append(System.lineSeparator()); - code.append(TldRuleSet.class.getName()).append(".Variable ").append(digester.toVariableName(variable)).append(" = new "); - code.append(TldRuleSet.class.getName()).append(".Variable").append("();").append(System.lineSeparator()); + code.append(TldRuleSet.class.getName()).append(".Variable ").append(digester.toVariableName(variable)) + .append(" = new "); + code.append(TldRuleSet.class.getName()).append(".Variable").append("();") + .append(System.lineSeparator()); } } @@ -391,7 +380,7 @@ @Override public void body(String namespace, String name, String text) throws Exception { - if(null != text) { + if (null != text) { text = text.trim(); } boolean value = "true".equalsIgnoreCase(text) || "yes".equalsIgnoreCase(text); diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/descriptor/tld/ValidatorXml.java tomcat10-10.1.52/java/org/apache/tomcat/util/descriptor/tld/ValidatorXml.java --- tomcat10-10.1.40/java/org/apache/tomcat/util/descriptor/tld/ValidatorXml.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/descriptor/tld/ValidatorXml.java 2026-01-23 19:33:36.000000000 +0000 @@ -24,7 +24,7 @@ */ public class ValidatorXml { private String validatorClass; - private final Map initParams = new HashMap<>(); + private final Map initParams = new HashMap<>(); public String getValidatorClass() { return validatorClass; @@ -38,7 +38,7 @@ initParams.put(name, value); } - public Map getInitParams() { + public Map getInitParams() { return initParams; } } diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/descriptor/web/ApplicationParameter.java tomcat10-10.1.52/java/org/apache/tomcat/util/descriptor/web/ApplicationParameter.java --- tomcat10-10.1.40/java/org/apache/tomcat/util/descriptor/web/ApplicationParameter.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/descriptor/web/ApplicationParameter.java 2026-01-23 19:33:36.000000000 +0000 @@ -20,13 +20,9 @@ /** - * Representation of a context initialization parameter that is configured - * in the server configuration file, rather than the application deployment - * descriptor. This is convenient for establishing default values (which - * may be configured to allow application overrides or not) without having - * to modify the application deployment descriptor itself. - * - * @author Craig R. McClanahan + * Representation of a context initialization parameter that is configured in the server configuration file, rather than + * the application deployment descriptor. This is convenient for establishing default values (which may be configured to + * allow application overrides or not) without having to modify the application deployment descriptor itself. */ public class ApplicationParameter implements Serializable { @@ -64,8 +60,7 @@ /** - * Does this application parameter allow overrides by the application - * deployment descriptor? + * Does this application parameter allow overrides by the application deployment descriptor? */ private boolean override = true; diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/descriptor/web/Constants.java tomcat10-10.1.52/java/org/apache/tomcat/util/descriptor/web/Constants.java --- tomcat10-10.1.40/java/org/apache/tomcat/util/descriptor/web/Constants.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/descriptor/web/Constants.java 2026-01-23 19:33:36.000000000 +0000 @@ -18,8 +18,7 @@ public class Constants { - public static final String PACKAGE_NAME = - Constants.class.getPackage().getName(); + public static final String PACKAGE_NAME = Constants.class.getPackage().getName(); public static final String WEB_XML_LOCATION = "/WEB-INF/web.xml"; diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/descriptor/web/ContextEjb.java tomcat10-10.1.52/java/org/apache/tomcat/util/descriptor/web/ContextEjb.java --- tomcat10-10.1.40/java/org/apache/tomcat/util/descriptor/web/ContextEjb.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/descriptor/web/ContextEjb.java 2026-01-23 19:33:36.000000000 +0000 @@ -17,14 +17,9 @@ package org.apache.tomcat.util.descriptor.web; - /** - * Representation of an EJB resource reference for a web application, as - * represented in a <ejb-ref> element in the - * deployment descriptor. - * - * @author Craig R. McClanahan - * @author Peter Rossbach (pero@apache.org) + * Representation of an EJB resource reference for a web application, as represented in a <ejb-ref> + * element in the deployment descriptor. */ public class ContextEjb extends ResourceBase { diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/descriptor/web/ContextEnvironment.java tomcat10-10.1.52/java/org/apache/tomcat/util/descriptor/web/ContextEnvironment.java --- tomcat10-10.1.40/java/org/apache/tomcat/util/descriptor/web/ContextEnvironment.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/descriptor/web/ContextEnvironment.java 2026-01-23 19:33:36.000000000 +0000 @@ -17,12 +17,9 @@ package org.apache.tomcat.util.descriptor.web; - /** - * Representation of an application environment entry, as represented in - * an <env-entry> element in the deployment descriptor. - * - * @author Craig R. McClanahan + * Representation of an application environment entry, as represented in an <env-entry> element in + * the deployment descriptor. */ public class ContextEnvironment extends ResourceBase { @@ -33,8 +30,7 @@ /** - * Does this environment entry allow overrides by the application - * deployment descriptor? + * Does this environment entry allow overrides by the application deployment descriptor? */ private boolean override = true; diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/descriptor/web/ContextHandler.java tomcat10-10.1.52/java/org/apache/tomcat/util/descriptor/web/ContextHandler.java --- tomcat10-10.1.40/java/org/apache/tomcat/util/descriptor/web/ContextHandler.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/descriptor/web/ContextHandler.java 2026-01-23 19:33:36.000000000 +0000 @@ -24,11 +24,8 @@ /** - * Representation of a handler reference for a web service, as - * represented in a <handler> element in the - * deployment descriptor. - * - * @author Fabien Carrion + * Representation of a handler reference for a web service, as represented in a <handler> element in + * the deployment descriptor. */ public class ContextHandler extends ResourceBase { @@ -51,15 +48,14 @@ } /** - * A list of QName specifying the SOAP Headers the handler will work on. - * -namespace and localpart values must be found inside the WSDL. + * A list of QName specifying the SOAP Headers the handler will work on. -namespace and localpart values must be + * found inside the WSDL. *

      * A service-qname is composed by a namespaceURI and a localpart. *

      - * soapHeader[0] : namespaceURI - * soapHeader[1] : localpart + * soapHeader[0] : namespaceURI soapHeader[1] : localpart */ - private final Map soapHeaders = new HashMap<>(); + private final Map soapHeaders = new HashMap<>(); public Iterator getLocalparts() { return soapHeaders.keySet().iterator(); @@ -75,7 +71,8 @@ /** * Set a configured property. - * @param name The property name + * + * @param name The property name * @param value The property value */ public void setProperty(String name, String value) { @@ -157,8 +154,7 @@ public int hashCode() { final int prime = 31; int result = super.hashCode(); - result = prime * result + - ((handlerclass == null) ? 0 : handlerclass.hashCode()); + result = prime * result + ((handlerclass == null) ? 0 : handlerclass.hashCode()); result = prime * result + portNames.hashCode(); result = prime * result + soapHeaders.hashCode(); result = prime * result + soapRoles.hashCode(); diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/descriptor/web/ContextLocalEjb.java tomcat10-10.1.52/java/org/apache/tomcat/util/descriptor/web/ContextLocalEjb.java --- tomcat10-10.1.40/java/org/apache/tomcat/util/descriptor/web/ContextLocalEjb.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/descriptor/web/ContextLocalEjb.java 2026-01-23 19:33:36.000000000 +0000 @@ -17,14 +17,9 @@ package org.apache.tomcat.util.descriptor.web; - /** - * Representation of a local EJB resource reference for a web application, as - * represented in a <ejb-local-ref> element in the - * deployment descriptor. - * - * @author Craig R. McClanahan - * @author Peter Rossbach (pero@apache.org) + * Representation of a local EJB resource reference for a web application, as represented in a + * <ejb-local-ref> element in the deployment descriptor. */ public class ContextLocalEjb extends ResourceBase { diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/descriptor/web/ContextResource.java tomcat10-10.1.52/java/org/apache/tomcat/util/descriptor/web/ContextResource.java --- tomcat10-10.1.40/java/org/apache/tomcat/util/descriptor/web/ContextResource.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/descriptor/web/ContextResource.java 2026-01-23 19:33:36.000000000 +0000 @@ -17,14 +17,9 @@ package org.apache.tomcat.util.descriptor.web; - /** - * Representation of a resource reference for a web application, as - * represented in a <resource-ref> element in the - * deployment descriptor. - * - * @author Craig R. McClanahan - * @author Peter Rossbach (pero@apache.org) + * Representation of a resource reference for a web application, as represented in a <resource-ref> + * element in the deployment descriptor. */ public class ContextResource extends ResourceBase { @@ -34,8 +29,7 @@ /** - * The authorization requirement for this resource - * (Application or Container). + * The authorization requirement for this resource (Application or Container). */ private String auth = null; @@ -48,8 +42,7 @@ } /** - * The sharing scope of this resource factory (Shareable - * or Unshareable). + * The sharing scope of this resource factory (Shareable or Unshareable). */ private String scope = "Shareable"; @@ -63,9 +56,8 @@ /** - * Is this resource known to be a singleton resource. The default value is - * true since this is what users expect although the Jakarta EE spec implies - * that the default should be false. + * Is this resource known to be a singleton resource. The default value is true since this is what users expect + * although the Jakarta EE spec implies that the default should be false. */ private boolean singleton = true; @@ -79,10 +71,8 @@ /** - * The name of the zero argument method to be called when the resource is - * no longer required to clean-up resources. This method must only speed up - * the clean-up of resources that would otherwise happen via garbage - * collection. + * The name of the zero argument method to be called when the resource is no longer required to clean-up resources. + * This method must only speed up the clean-up of resources that would otherwise happen via garbage collection. */ private String closeMethod = null; private boolean closeMethodConfigured = false; @@ -139,8 +129,7 @@ final int prime = 31; int result = super.hashCode(); result = prime * result + ((auth == null) ? 0 : auth.hashCode()); - result = prime * result + - ((closeMethod == null) ? 0 : closeMethod.hashCode()); + result = prime * result + ((closeMethod == null) ? 0 : closeMethod.hashCode()); result = prime * result + ((scope == null) ? 0 : scope.hashCode()); result = prime * result + (singleton ? 1231 : 1237); return result; diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/descriptor/web/ContextResourceEnvRef.java tomcat10-10.1.52/java/org/apache/tomcat/util/descriptor/web/ContextResourceEnvRef.java --- tomcat10-10.1.40/java/org/apache/tomcat/util/descriptor/web/ContextResourceEnvRef.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/descriptor/web/ContextResourceEnvRef.java 2026-01-23 19:33:36.000000000 +0000 @@ -17,13 +17,9 @@ package org.apache.tomcat.util.descriptor.web; - /** - * Representation of an application resource reference, as represented in - * an <res-env-ref> element in the deployment descriptor. - * - * @author Craig R. McClanahan - * @author Peter Rossbach (pero@apache.org) + * Representation of an application resource reference, as represented in an <res-env-ref> element in + * the deployment descriptor. */ public class ContextResourceEnvRef extends ResourceBase { @@ -32,8 +28,7 @@ // ------------------------------------------------------------- Properties /** - * Does this environment entry allow overrides by the application - * deployment descriptor? + * Does this environment entry allow overrides by the application deployment descriptor? */ private boolean override = true; diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/descriptor/web/ContextResourceLink.java tomcat10-10.1.52/java/org/apache/tomcat/util/descriptor/web/ContextResourceLink.java --- tomcat10-10.1.40/java/org/apache/tomcat/util/descriptor/web/ContextResourceLink.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/descriptor/web/ContextResourceLink.java 2026-01-23 19:33:36.000000000 +0000 @@ -17,14 +17,9 @@ package org.apache.tomcat.util.descriptor.web; - /** - * Representation of a resource link for a web application, as - * represented in a <ResourceLink> element in the - * server configuration file. - * - * @author Remy Maucherat - * @author Peter Rossbach (Peter Rossbach (pero@apache.org)) + * Representation of a resource link for a web application, as represented in a <ResourceLink> + * element in the server configuration file. */ public class ContextResourceLink extends ResourceBase { @@ -32,7 +27,7 @@ // ------------------------------------------------------------- Properties - /** + /** * The global name of this resource. */ private String global = null; diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/descriptor/web/ContextService.java tomcat10-10.1.52/java/org/apache/tomcat/util/descriptor/web/ContextService.java --- tomcat10-10.1.40/java/org/apache/tomcat/util/descriptor/web/ContextService.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/descriptor/web/ContextService.java 2026-01-23 19:33:36.000000000 +0000 @@ -23,11 +23,8 @@ /** - * Representation of a web service reference for a web application, as - * represented in a <service-ref> element in the - * deployment descriptor. - * - * @author Fabien Carrion + * Representation of a web service reference for a web application, as represented in a <service-ref> + * element in the deployment descriptor. */ public class ContextService extends ResourceBase { @@ -76,8 +73,7 @@ } /** - * The fully qualified class name of the JAX-WS Service interface that the - * client depends on. + * The fully qualified class name of the JAX-WS Service interface that the client depends on. */ private String serviceInterface = null; @@ -90,8 +86,7 @@ } /** - * Contains the location (relative to the root of - * the module) of the web service WSDL description. + * Contains the location (relative to the root of the module) of the web service WSDL description. */ private String wsdlfile = null; @@ -104,8 +99,8 @@ } /** - * A file specifying the correlation of the WSDL definition - * to the interfaces (Service Endpoint Interface, Service Interface). + * A file specifying the correlation of the WSDL definition to the interfaces (Service Endpoint Interface, Service + * Interface). */ private String jaxrpcmappingfile = null; @@ -118,15 +113,13 @@ } /** - * Declares the specific WSDL service element that is being referred to. - * It is not specified if no wsdl-file is declared or if WSDL contains only - * 1 service element. + * Declares the specific WSDL service element that is being referred to. It is not specified if no wsdl-file is + * declared or if WSDL contains only 1 service element. *

      - * A service-qname is composed by a namespaceURI and a localpart. - * It must be defined if more than 1 service is declared in the WSDL. + * A service-qname is composed by a namespaceURI and a localpart. It must be defined if more than 1 service is + * declared in the WSDL. *

      - * serviceqname[0] : namespaceURI - * serviceqname[1] : localpart + * serviceqname[0] : namespaceURI serviceqname[1] : localpart */ private String[] serviceqname = new String[2]; @@ -163,9 +156,9 @@ } /** - * Declares a client dependency on the container to resolving a Service Endpoint Interface - * to a WSDL port. It optionally associates the Service Endpoint Interface with a - * particular port-component. + * Declares a client dependency on the container to resolving a Service Endpoint Interface to a WSDL port. It + * optionally associates the Service Endpoint Interface with a particular port-component. + * * @return the endpoint names */ public Iterator getServiceendpoints() { @@ -184,10 +177,9 @@ } /** - * A list of Handlers to use for this service-ref. - * The instantiation of the handler have to be done. + * A list of Handlers to use for this service-ref. The instantiation of the handler have to be done. */ - private final Map handlers = new HashMap<>(); + private final Map handlers = new HashMap<>(); public Iterator getHandlers() { return handlers.keySet().iterator(); @@ -267,20 +259,14 @@ public int hashCode() { final int prime = 31; int result = super.hashCode(); - result = prime * result + - ((displayname == null) ? 0 : displayname.hashCode()); + result = prime * result + ((displayname == null) ? 0 : displayname.hashCode()); result = prime * result + handlers.hashCode(); - result = prime * result + - ((jaxrpcmappingfile == null) ? 0 : jaxrpcmappingfile.hashCode()); - result = prime * result + - ((largeIcon == null) ? 0 : largeIcon.hashCode()); - result = prime * result + - ((serviceInterface == null) ? 0 : serviceInterface.hashCode()); + result = prime * result + ((jaxrpcmappingfile == null) ? 0 : jaxrpcmappingfile.hashCode()); + result = prime * result + ((largeIcon == null) ? 0 : largeIcon.hashCode()); + result = prime * result + ((serviceInterface == null) ? 0 : serviceInterface.hashCode()); result = prime * result + Arrays.hashCode(serviceqname); - result = prime * result + - ((smallIcon == null) ? 0 : smallIcon.hashCode()); - result = prime * result + - ((wsdlfile == null) ? 0 : wsdlfile.hashCode()); + result = prime * result + ((smallIcon == null) ? 0 : smallIcon.hashCode()); + result = prime * result + ((wsdlfile == null) ? 0 : wsdlfile.hashCode()); return result; } diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/descriptor/web/ContextTransaction.java tomcat10-10.1.52/java/org/apache/tomcat/util/descriptor/web/ContextTransaction.java --- tomcat10-10.1.40/java/org/apache/tomcat/util/descriptor/web/ContextTransaction.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/descriptor/web/ContextTransaction.java 2026-01-23 19:33:36.000000000 +0000 @@ -23,10 +23,8 @@ /** - * Representation of an application resource reference, as represented in - * an <res-env-ref> element in the deployment descriptor. - * - * @author Craig R. McClanahan + * Representation of an application resource reference, as represented in an <res-env-ref> element in + * the deployment descriptor. */ public class ContextTransaction implements Serializable { @@ -38,10 +36,11 @@ /** * Holder for our configured properties. */ - private final Map properties = new HashMap<>(); + private final Map properties = new HashMap<>(); /** * @param name The property name + * * @return a configured property. */ public Object getProperty(String name) { @@ -50,7 +49,8 @@ /** * Set a configured property. - * @param name The property name + * + * @param name The property name * @param value The property value */ public void setProperty(String name, Object value) { @@ -59,6 +59,7 @@ /** * Remove a configured property. + * * @param name The property name */ public void removeProperty(String name) { @@ -67,6 +68,7 @@ /** * List properties. + * * @return the property names iterator */ public Iterator listProperties() { diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/descriptor/web/ErrorPage.java tomcat10-10.1.52/java/org/apache/tomcat/util/descriptor/web/ErrorPage.java --- tomcat10-10.1.40/java/org/apache/tomcat/util/descriptor/web/ErrorPage.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/descriptor/web/ErrorPage.java 2026-01-23 19:33:36.000000000 +0000 @@ -22,11 +22,8 @@ import org.apache.tomcat.util.buf.UDecoder; /** - * Representation of an error page element for a web application, - * as represented in a <error-page> element in the - * deployment descriptor. - * - * @author Craig R. McClanahan + * Representation of an error page element for a web application, as represented in a <error-page> + * element in the deployment descriptor. */ public class ErrorPage extends XmlEncodingBase implements Serializable { @@ -36,8 +33,8 @@ // ----------------------------------------------------- Instance Variables /** - * The error (status) code for which this error page is active. Note that - * status code 0 is used for the default error page. + * The error (status) code for which this error page is active. Note that status code 0 is used for the default + * error page. */ private int errorCode = 0; diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/descriptor/web/FilterDef.java tomcat10-10.1.52/java/org/apache/tomcat/util/descriptor/web/FilterDef.java --- tomcat10-10.1.40/java/org/apache/tomcat/util/descriptor/web/FilterDef.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/descriptor/web/FilterDef.java 2026-01-23 19:33:36.000000000 +0000 @@ -26,17 +26,14 @@ /** - * Representation of a filter definition for a web application, as represented - * in a <filter> element in the deployment descriptor. - * - * @author Craig R. McClanahan + * Representation of a filter definition for a web application, as represented in a <filter> element + * in the deployment descriptor. */ public class FilterDef implements Serializable { private static final long serialVersionUID = 1L; - private static final StringManager sm = - StringManager.getManager(Constants.PACKAGE_NAME); + private static final StringManager sm = StringManager.getManager(Constants.PACKAGE_NAME); // ------------------------------------------------------------- Properties @@ -98,8 +95,7 @@ /** - * The name of this filter, which must be unique among the filters - * defined for a particular web application. + * The name of this filter, which must be unique among the filters defined for a particular web application. */ private String filterName = null; @@ -109,8 +105,7 @@ public void setFilterName(String filterName) { if (filterName == null || filterName.isEmpty()) { - throw new IllegalArgumentException( - sm.getString("filterDef.invalidFilterName", filterName)); + throw new IllegalArgumentException(sm.getString("filterDef.invalidFilterName", filterName)); } this.filterName = filterName; } @@ -131,12 +126,11 @@ /** - * The set of initialization parameters for this filter, keyed by - * parameter name. + * The set of initialization parameters for this filter, keyed by parameter name. */ - private final Map parameters = new HashMap<>(); + private final Map parameters = new HashMap<>(); - public Map getParameterMap() { + public Map getParameterMap() { return this.parameters; } @@ -175,10 +169,9 @@ /** - * Add an initialization parameter to the set of parameters associated - * with this filter. + * Add an initialization parameter to the set of parameters associated with this filter. * - * @param name The initialization parameter name + * @param name The initialization parameter name * @param value The initialization parameter value */ public void addInitParameter(String name, String value) { diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/descriptor/web/FilterMap.java tomcat10-10.1.52/java/org/apache/tomcat/util/descriptor/web/FilterMap.java --- tomcat10-10.1.40/java/org/apache/tomcat/util/descriptor/web/FilterMap.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/descriptor/web/FilterMap.java 2026-01-23 19:33:36.000000000 +0000 @@ -26,12 +26,9 @@ import org.apache.tomcat.util.buf.UDecoder; /** - * Representation of a filter mapping for a web application, as represented - * in a <filter-mapping> element in the deployment - * descriptor. Each filter mapping must contain a filter name plus either - * a URL pattern or a servlet name. - * - * @author Craig R. McClanahan + * Representation of a filter mapping for a web application, as represented in a <filter-mapping> + * element in the deployment descriptor. Each filter mapping must contain a filter name plus either a URL pattern or a + * servlet name. */ public class FilterMap extends XmlEncodingBase implements Serializable { @@ -42,8 +39,7 @@ private static final long serialVersionUID = 1L; /** - * The name of this filter to be executed when this mapping matches - * a particular request. + * The name of this filter to be executed when this mapping matches a particular request. */ public static final int ERROR = 1; @@ -130,6 +126,7 @@ public void addURLPattern(String urlPattern) { addURLPatternDecoded(UDecoder.URLDecode(urlPattern, getCharset())); } + public void addURLPatternDecoded(String urlPattern) { if ("*".equals(urlPattern)) { this.matchAllUrlPatterns = true; @@ -142,10 +139,10 @@ } /** - * This method will be used to set the current state of the FilterMap - * representing the state of when filters should be applied. - * @param dispatcherString the dispatcher type which should - * match this filter + * This method will be used to set the current state of the FilterMap representing the state of when filters should + * be applied. + * + * @param dispatcherString the dispatcher type which should match this filter */ public void setDispatcher(String dispatcherString) { String dispatcher = dispatcherString.toUpperCase(Locale.ENGLISH); @@ -159,10 +156,10 @@ } else if (dispatcher.equals(DispatcherType.REQUEST.name())) { // apply REQUEST to the global dispatcherMapping. dispatcherMapping |= REQUEST; - } else if (dispatcher.equals(DispatcherType.ERROR.name())) { + } else if (dispatcher.equals(DispatcherType.ERROR.name())) { // apply ERROR to the global dispatcherMapping. dispatcherMapping |= ERROR; - } else if (dispatcher.equals(DispatcherType.ASYNC.name())) { + } else if (dispatcher.equals(DispatcherType.ASYNC.name())) { // apply ERROR to the global dispatcherMapping. dispatcherMapping |= ASYNC; } diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/descriptor/web/FragmentJarScannerCallback.java tomcat10-10.1.52/java/org/apache/tomcat/util/descriptor/web/FragmentJarScannerCallback.java --- tomcat10-10.1.40/java/org/apache/tomcat/util/descriptor/web/FragmentJarScannerCallback.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/descriptor/web/FragmentJarScannerCallback.java 2026-01-23 19:33:36.000000000 +0000 @@ -33,16 +33,14 @@ */ public class FragmentJarScannerCallback implements JarScannerCallback { - private static final String FRAGMENT_LOCATION = - "META-INF/web-fragment.xml"; + private static final String FRAGMENT_LOCATION = "META-INF/web-fragment.xml"; private final WebXmlParser webXmlParser; private final boolean delegate; private final boolean parseRequired; private final Map fragments = new HashMap<>(); - private boolean ok = true; + private boolean ok = true; - public FragmentJarScannerCallback(WebXmlParser webXmlParser, boolean delegate, - boolean parseRequired) { + public FragmentJarScannerCallback(WebXmlParser webXmlParser, boolean delegate, boolean parseRequired) { this.webXmlParser = webXmlParser; this.delegate = delegate; this.parseRequired = parseRequired; @@ -107,8 +105,7 @@ try { if (fragmentFile.isFile()) { try (InputStream stream = new FileInputStream(fragmentFile)) { - InputSource source = - new InputSource(fragmentFile.toURI().toURL().toString()); + InputSource source = new InputSource(fragmentFile.toURI().toURL().toString()); source.setByteStream(stream); if (!webXmlParser.parseWebXml(source, fragment, true)) { ok = false; diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/descriptor/web/Injectable.java tomcat10-10.1.52/java/org/apache/tomcat/util/descriptor/web/Injectable.java --- tomcat10-10.1.40/java/org/apache/tomcat/util/descriptor/web/Injectable.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/descriptor/web/Injectable.java 2026-01-23 19:33:36.000000000 +0000 @@ -20,6 +20,8 @@ public interface Injectable { String getName(); + void addInjectionTarget(String injectionTargetName, String jndiName); + List getInjectionTargets(); } diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/descriptor/web/JspConfigDescriptorImpl.java tomcat10-10.1.52/java/org/apache/tomcat/util/descriptor/web/JspConfigDescriptorImpl.java --- tomcat10-10.1.40/java/org/apache/tomcat/util/descriptor/web/JspConfigDescriptorImpl.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/descriptor/web/JspConfigDescriptorImpl.java 2026-01-23 19:33:36.000000000 +0000 @@ -29,7 +29,7 @@ private final Collection taglibs; public JspConfigDescriptorImpl(Collection jspPropertyGroups, - Collection taglibs) { + Collection taglibs) { this.jspPropertyGroups = jspPropertyGroups; this.taglibs = taglibs; } diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/descriptor/web/JspPropertyGroup.java tomcat10-10.1.52/java/org/apache/tomcat/util/descriptor/web/JspPropertyGroup.java --- tomcat10-10.1.40/java/org/apache/tomcat/util/descriptor/web/JspPropertyGroup.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/descriptor/web/JspPropertyGroup.java 2026-01-23 19:33:36.000000000 +0000 @@ -29,86 +29,135 @@ public class JspPropertyGroup extends XmlEncodingBase { private Boolean deferredSyntax = null; + public void setDeferredSyntax(String deferredSyntax) { this.deferredSyntax = Boolean.valueOf(deferredSyntax); } - public Boolean getDeferredSyntax() { return deferredSyntax; } + + public Boolean getDeferredSyntax() { + return deferredSyntax; + } private Boolean errorOnELNotFound = null; + public void setErrorOnELNotFound(String errorOnELNotFound) { this.errorOnELNotFound = Boolean.valueOf(errorOnELNotFound); } - public Boolean getErrorOnELNotFound() { return errorOnELNotFound; } + + public Boolean getErrorOnELNotFound() { + return errorOnELNotFound; + } private Boolean elIgnored = null; + public void setElIgnored(String elIgnored) { this.elIgnored = Boolean.valueOf(elIgnored); } - public Boolean getElIgnored() { return elIgnored; } + + public Boolean getElIgnored() { + return elIgnored; + } private final Collection includeCodas = new ArrayList<>(); + public void addIncludeCoda(String includeCoda) { includeCodas.add(includeCoda); } - public Collection getIncludeCodas() { return includeCodas; } + + public Collection getIncludeCodas() { + return includeCodas; + } private final Collection includePreludes = new ArrayList<>(); + public void addIncludePrelude(String includePrelude) { includePreludes.add(includePrelude); } - public Collection getIncludePreludes() { return includePreludes; } + + public Collection getIncludePreludes() { + return includePreludes; + } private Boolean isXml = null; + public void setIsXml(String isXml) { this.isXml = Boolean.valueOf(isXml); } - public Boolean getIsXml() { return isXml; } + + public Boolean getIsXml() { + return isXml; + } private String pageEncoding = null; + public void setPageEncoding(String pageEncoding) { this.pageEncoding = pageEncoding; } - public String getPageEncoding() { return this.pageEncoding; } + + public String getPageEncoding() { + return this.pageEncoding; + } private Boolean scriptingInvalid = null; + public void setScriptingInvalid(String scriptingInvalid) { this.scriptingInvalid = Boolean.valueOf(scriptingInvalid); } - public Boolean getScriptingInvalid() { return scriptingInvalid; } + + public Boolean getScriptingInvalid() { + return scriptingInvalid; + } private Boolean trimWhitespace = null; + public void setTrimWhitespace(String trimWhitespace) { this.trimWhitespace = Boolean.valueOf(trimWhitespace); } - public Boolean getTrimWhitespace() { return trimWhitespace; } + + public Boolean getTrimWhitespace() { + return trimWhitespace; + } private final LinkedHashSet urlPattern = new LinkedHashSet<>(); + public void addUrlPattern(String urlPattern) { addUrlPatternDecoded(UDecoder.URLDecode(urlPattern, getCharset())); } + public void addUrlPatternDecoded(String urlPattern) { this.urlPattern.add(urlPattern); } - public Set getUrlPatterns() { return this.urlPattern; } + + public Set getUrlPatterns() { + return this.urlPattern; + } private String defaultContentType = null; + public void setDefaultContentType(String defaultContentType) { this.defaultContentType = defaultContentType; } - public String getDefaultContentType() { return this.defaultContentType; } + + public String getDefaultContentType() { + return this.defaultContentType; + } private String buffer = null; + public void setBuffer(String buffer) { this.buffer = buffer; } - public String getBuffer() { return this.buffer; } + + public String getBuffer() { + return this.buffer; + } private Boolean errorOnUndeclaredNamespace = null; - public void setErrorOnUndeclaredNamespace( - String errorOnUndeclaredNamespace) { - this.errorOnUndeclaredNamespace = - Boolean.valueOf(errorOnUndeclaredNamespace); + + public void setErrorOnUndeclaredNamespace(String errorOnUndeclaredNamespace) { + this.errorOnUndeclaredNamespace = Boolean.valueOf(errorOnUndeclaredNamespace); } + public Boolean getErrorOnUndeclaredNamespace() { return this.errorOnUndeclaredNamespace; } diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/descriptor/web/JspPropertyGroupDescriptorImpl.java tomcat10-10.1.52/java/org/apache/tomcat/util/descriptor/web/JspPropertyGroupDescriptorImpl.java --- tomcat10-10.1.40/java/org/apache/tomcat/util/descriptor/web/JspPropertyGroupDescriptorImpl.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/descriptor/web/JspPropertyGroupDescriptorImpl.java 2026-01-23 19:33:36.000000000 +0000 @@ -22,15 +22,12 @@ import jakarta.servlet.descriptor.JspPropertyGroupDescriptor; - -public class JspPropertyGroupDescriptorImpl - implements JspPropertyGroupDescriptor{ +public class JspPropertyGroupDescriptorImpl implements JspPropertyGroupDescriptor { private final JspPropertyGroup jspPropertyGroup; - public JspPropertyGroupDescriptorImpl( - JspPropertyGroup jspPropertyGroup) { + public JspPropertyGroupDescriptorImpl(JspPropertyGroup jspPropertyGroup) { this.jspPropertyGroup = jspPropertyGroup; } @@ -88,8 +85,7 @@ String result = null; if (jspPropertyGroup.getErrorOnUndeclaredNamespace() != null) { - result = - jspPropertyGroup.getErrorOnUndeclaredNamespace().toString(); + result = jspPropertyGroup.getErrorOnUndeclaredNamespace().toString(); } return result; diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/descriptor/web/LocalStrings_es.properties tomcat10-10.1.52/java/org/apache/tomcat/util/descriptor/web/LocalStrings_es.properties --- tomcat10-10.1.40/java/org/apache/tomcat/util/descriptor/web/LocalStrings_es.properties 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/descriptor/web/LocalStrings_es.properties 2026-01-23 19:33:36.000000000 +0000 @@ -26,6 +26,7 @@ webXml.duplicateFilter=Filtro de nombre duplicado [{0}]\n webXml.duplicateServletMapping=Los servlets llamados [{0}] y [{1}] estan ambos mapeados al patrón de URL [{2}] el cual no esta permitido +webXml.mergeConflictFilter=El filtro [{0}] se definió de forma inconsistente en varios fragmentos, incluido el fragmento con nombre [{1}] ubicado en [{2}] webXml.mergeConflictSessionTrackingMode=Los modos de seguimiento fueron definidos inconsistentemente en multiples fragmentos, incluyendo fragmentos con el nombre [{0}] localizado en [{1}]\n webXml.reservedName=Un archivo web.xml fue detectado usando un nombre reservado [{0}]. El nombre será ignorado para este fragmento. diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/descriptor/web/LoginConfig.java tomcat10-10.1.52/java/org/apache/tomcat/util/descriptor/web/LoginConfig.java --- tomcat10-10.1.40/java/org/apache/tomcat/util/descriptor/web/LoginConfig.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/descriptor/web/LoginConfig.java 2026-01-23 19:33:36.000000000 +0000 @@ -21,11 +21,8 @@ import org.apache.tomcat.util.buf.UDecoder; /** - * Representation of a login configuration element for a web application, - * as represented in a <login-config> element in the - * deployment descriptor. - * - * @author Craig R. McClanahan + * Representation of a login configuration element for a web application, as represented in a + * <login-config> element in the deployment descriptor. */ public class LoginConfig extends XmlEncodingBase implements Serializable { @@ -49,12 +46,11 @@ * Construct a new LoginConfig with the specified properties. * * @param authMethod The authentication method - * @param realmName The realm name - * @param loginPage The login page URI - * @param errorPage The error page URI + * @param realmName The realm name + * @param loginPage The login page URI + * @param errorPage The error page URI */ - public LoginConfig(String authMethod, String realmName, - String loginPage, String errorPage) { + public LoginConfig(String authMethod, String realmName, String loginPage, String errorPage) { super(); setAuthMethod(authMethod); @@ -69,8 +65,7 @@ /** - * The authentication method to use for application login. Must be - * BASIC, DIGEST, FORM, or CLIENT-CERT. + * The authentication method to use for application login. Must be BASIC, DIGEST, FORM, or CLIENT-CERT. */ private String authMethod = null; @@ -112,8 +107,7 @@ /** - * The realm name used when challenging the user for authentication - * credentials. + * The realm name used when challenging the user for authentication credentials. */ private String realmName = null; @@ -154,26 +148,26 @@ } - /* (non-Javadoc) + /* + * (non-Javadoc) + * * @see java.lang.Object#hashCode() */ @Override public int hashCode() { final int prime = 31; int result = 1; - result = prime * result - + ((authMethod == null) ? 0 : authMethod.hashCode()); - result = prime * result - + ((errorPage == null) ? 0 : errorPage.hashCode()); - result = prime * result - + ((loginPage == null) ? 0 : loginPage.hashCode()); - result = prime * result - + ((realmName == null) ? 0 : realmName.hashCode()); + result = prime * result + ((authMethod == null) ? 0 : authMethod.hashCode()); + result = prime * result + ((errorPage == null) ? 0 : errorPage.hashCode()); + result = prime * result + ((loginPage == null) ? 0 : loginPage.hashCode()); + result = prime * result + ((realmName == null) ? 0 : realmName.hashCode()); return result; } - /* (non-Javadoc) + /* + * (non-Javadoc) + * * @see java.lang.Object#equals(java.lang.Object) */ @Override diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/descriptor/web/MessageDestination.java tomcat10-10.1.52/java/org/apache/tomcat/util/descriptor/web/MessageDestination.java --- tomcat10-10.1.40/java/org/apache/tomcat/util/descriptor/web/MessageDestination.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/descriptor/web/MessageDestination.java 2026-01-23 19:33:36.000000000 +0000 @@ -18,11 +18,11 @@ /** - *

      Representation of a message destination for a web application, as - * represented in a <message-destination> element - * in the deployment descriptor.

      + *

      + * Representation of a message destination for a web application, as represented in a + * <message-destination> element in the deployment descriptor. + *

      * - * @author Craig R. McClanahan * @since Tomcat 5.0 */ public class MessageDestination extends ResourceBase { @@ -110,12 +110,9 @@ public int hashCode() { final int prime = 31; int result = super.hashCode(); - result = prime * result + - ((displayName == null) ? 0 : displayName.hashCode()); - result = prime * result + - ((largeIcon == null) ? 0 : largeIcon.hashCode()); - result = prime * result + - ((smallIcon == null) ? 0 : smallIcon.hashCode()); + result = prime * result + ((displayName == null) ? 0 : displayName.hashCode()); + result = prime * result + ((largeIcon == null) ? 0 : largeIcon.hashCode()); + result = prime * result + ((smallIcon == null) ? 0 : smallIcon.hashCode()); return result; } diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/descriptor/web/MessageDestinationRef.java tomcat10-10.1.52/java/org/apache/tomcat/util/descriptor/web/MessageDestinationRef.java --- tomcat10-10.1.40/java/org/apache/tomcat/util/descriptor/web/MessageDestinationRef.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/descriptor/web/MessageDestinationRef.java 2026-01-23 19:33:36.000000000 +0000 @@ -18,11 +18,11 @@ /** - *

      Representation of a message destination reference for a web application, - * as represented in a <message-destination-ref> element - * in the deployment descriptor.

      + *

      + * Representation of a message destination reference for a web application, as represented in a + * <message-destination-ref> element in the deployment descriptor. + *

      * - * @author Craig R. McClanahan * @since Tomcat 5.0 */ public class MessageDestinationRef extends ResourceBase { diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/descriptor/web/MultipartDef.java tomcat10-10.1.52/java/org/apache/tomcat/util/descriptor/web/MultipartDef.java --- tomcat10-10.1.40/java/org/apache/tomcat/util/descriptor/web/MultipartDef.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/descriptor/web/MultipartDef.java 2026-01-23 19:33:36.000000000 +0000 @@ -77,16 +77,10 @@ public int hashCode() { final int prime = 31; int result = 1; - result = prime - * result - + ((fileSizeThreshold == null) ? 0 : fileSizeThreshold - .hashCode()); - result = prime * result - + ((location == null) ? 0 : location.hashCode()); - result = prime * result - + ((maxFileSize == null) ? 0 : maxFileSize.hashCode()); - result = prime * result - + ((maxRequestSize == null) ? 0 : maxRequestSize.hashCode()); + result = prime * result + ((fileSizeThreshold == null) ? 0 : fileSizeThreshold.hashCode()); + result = prime * result + ((location == null) ? 0 : location.hashCode()); + result = prime * result + ((maxFileSize == null) ? 0 : maxFileSize.hashCode()); + result = prime * result + ((maxRequestSize == null) ? 0 : maxRequestSize.hashCode()); return result; } diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/descriptor/web/NamingResources.java tomcat10-10.1.52/java/org/apache/tomcat/util/descriptor/web/NamingResources.java --- tomcat10-10.1.40/java/org/apache/tomcat/util/descriptor/web/NamingResources.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/descriptor/web/NamingResources.java 2026-01-23 19:33:36.000000000 +0000 @@ -17,13 +17,10 @@ package org.apache.tomcat.util.descriptor.web; - /** - * Defines an interface for the object that is added to the representation of a - * JNDI resource in web.xml to enable it to also be the implementation of that - * JNDI resource. Only Catalina implements this interface but because the - * web.xml representation is shared this interface has to be visible to Catalina - * and Jasper. + * Defines an interface for the object that is added to the representation of a JNDI resource in web.xml to enable it to + * also be the implementation of that JNDI resource. Only Catalina implements this interface but because the web.xml + * representation is shared this interface has to be visible to Catalina and Jasper. */ public interface NamingResources { diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/descriptor/web/ResourceBase.java tomcat10-10.1.52/java/org/apache/tomcat/util/descriptor/web/ResourceBase.java --- tomcat10-10.1.40/java/org/apache/tomcat/util/descriptor/web/ResourceBase.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/descriptor/web/ResourceBase.java 2026-01-23 19:33:36.000000000 +0000 @@ -25,9 +25,7 @@ /** - * Representation of a Context element - * - * @author Peter Rossbach (pero@apache.org) + * Representation of a Context element. */ public class ResourceBase implements Serializable, Injectable { @@ -50,7 +48,6 @@ } - /** * The name of this resource. */ @@ -98,10 +95,11 @@ /** * Holder for our configured properties. */ - private final Map properties = new HashMap<>(); + private final Map properties = new HashMap<>(); /** * @param name The property name + * * @return a configured property. */ public Object getProperty(String name) { @@ -110,7 +108,8 @@ /** * Set a configured property. - * @param name The property name + * + * @param name The property name * @param value The property value */ public void setProperty(String name, Object value) { @@ -119,6 +118,7 @@ /** * Remove a configured property. + * * @param name The property name */ public void removeProperty(String name) { @@ -127,6 +127,7 @@ /** * List properties. + * * @return the property names iterator */ public Iterator listProperties() { diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/descriptor/web/SecurityCollection.java tomcat10-10.1.52/java/org/apache/tomcat/util/descriptor/web/SecurityCollection.java --- tomcat10-10.1.40/java/org/apache/tomcat/util/descriptor/web/SecurityCollection.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/descriptor/web/SecurityCollection.java 2026-01-23 19:33:36.000000000 +0000 @@ -24,17 +24,12 @@ /** - * Representation of a web resource collection for a web application's security - * constraint, as represented in a <web-resource-collection> - * element in the deployment descriptor. + * Representation of a web resource collection for a web application's security constraint, as represented in a + * <web-resource-collection> element in the deployment descriptor. *

      - * WARNING: It is assumed that instances of this class will be created - * and modified only within the context of a single thread, before the instance - * is made visible to the remainder of the application. After that, only read - * access is expected. Therefore, none of the read and write access within - * this class is synchronized. - * - * @author Craig R. McClanahan + * WARNING: It is assumed that instances of this class will be created and modified only within the context of a + * single thread, before the instance is made visible to the remainder of the application. After that, only read access + * is expected. Therefore, none of the read and write access within this class is synchronized. */ public class SecurityCollection extends XmlEncodingBase implements Serializable { @@ -56,7 +51,7 @@ /** * Construct a new security collection instance with specified values. * - * @param name Name of this security collection + * @param name Name of this security collection * @param description Description of this security collection */ public SecurityCollection(String name, String description) { @@ -101,8 +96,7 @@ /** - * This security collection was established by a deployment descriptor. - * Defaults to true. + * This security collection was established by a deployment descriptor. Defaults to true. */ private boolean isFromDescriptor = true; @@ -155,6 +149,7 @@ /** * Set if this constraint was defined in a deployment descriptor. + * * @param isFromDescriptor true was declared in a descriptor */ public void setFromDescriptor(boolean isFromDescriptor) { @@ -166,8 +161,8 @@ /** - * Add an HTTP request method to be explicitly part of this web resource - * collection. + * Add an HTTP request method to be explicitly part of this web resource collection. + * * @param method The method */ public void addMethod(String method) { @@ -183,8 +178,8 @@ /** - * Add an HTTP request method to the methods explicitly excluded from this - * web resource collection. + * Add an HTTP request method to the methods explicitly excluded from this web resource collection. + * * @param method The method */ public void addOmittedMethod(String method) { @@ -198,11 +193,13 @@ /** * Add a URL pattern to be part of this web resource collection. + * * @param pattern The pattern */ public void addPattern(String pattern) { addPatternDecoded(UDecoder.URLDecode(pattern, StandardCharsets.UTF_8)); } + public void addPatternDecoded(String pattern) { if (pattern == null) { @@ -218,9 +215,10 @@ /** * Check if the collection applies to the specified method. + * * @param method Request method to check - * @return true if the specified HTTP request method is - * part of this web resource collection. + * + * @return true if the specified HTTP request method is part of this web resource collection. */ public boolean findMethod(String method) { @@ -245,9 +243,8 @@ /** - * @return the array of HTTP request methods that are part of this web - * resource collection, or a zero-length array if no methods have been - * explicitly included. + * @return the array of HTTP request methods that are part of this web resource collection, or a zero-length array + * if no methods have been explicitly included. */ public String[] findMethods() { return methods; @@ -255,9 +252,8 @@ /** - * @return the array of HTTP request methods that are explicitly excluded from - * this web resource collection, or a zero-length array if no request - * methods are excluded. + * @return the array of HTTP request methods that are explicitly excluded from this web resource collection, or a + * zero-length array if no request methods are excluded. */ public String[] findOmittedMethods() { return omittedMethods; @@ -268,6 +264,7 @@ * Is the specified pattern part of this web resource collection? * * @param pattern Pattern to be compared + * * @return true if the pattern is part of the collection */ public boolean findPattern(String pattern) { @@ -281,9 +278,8 @@ /** - * @return the array of URL patterns that are part of this web resource - * collection. If none have been specified, a zero-length array is - * returned. + * @return the array of URL patterns that are part of this web resource collection. If none have been specified, a + * zero-length array is returned. */ public String[] findPatterns() { return patterns; @@ -291,8 +287,7 @@ /** - * Remove the specified HTTP request method from those that are part - * of this web resource collection. + * Remove the specified HTTP request method from those that are part of this web resource collection. * * @param method Request method to be removed */ @@ -323,8 +318,8 @@ /** - * Remove the specified HTTP request method from those that are explicitly - * excluded from this web resource collection. + * Remove the specified HTTP request method from those that are explicitly excluded from this web resource + * collection. * * @param method Request method to be removed */ @@ -355,8 +350,7 @@ /** - * Remove the specified URL pattern from those that are part of this - * web resource collection. + * Remove the specified URL pattern from those that are part of this web resource collection. * * @param pattern Pattern to be removed */ diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/descriptor/web/SecurityConstraint.java tomcat10-10.1.52/java/org/apache/tomcat/util/descriptor/web/SecurityConstraint.java --- tomcat10-10.1.40/java/org/apache/tomcat/util/descriptor/web/SecurityConstraint.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/descriptor/web/SecurityConstraint.java 2026-01-23 19:33:36.000000000 +0000 @@ -38,17 +38,12 @@ /** - * Representation of a security constraint element for a web application, - * as represented in a <security-constraint> element in the - * deployment descriptor. + * Representation of a security constraint element for a web application, as represented in a + * <security-constraint> element in the deployment descriptor. *

      - * WARNING: It is assumed that instances of this class will be created - * and modified only within the context of a single thread, before the instance - * is made visible to the remainder of the application. After that, only read - * access is expected. Therefore, none of the read and write access within - * this class is synchronized. - * - * @author Craig R. McClanahan + * WARNING: It is assumed that instances of this class will be created and modified only within the context of a + * single thread, before the instance is made visible to the remainder of the application. After that, only read access + * is expected. Therefore, none of the read and write access within this class is synchronized. */ public class SecurityConstraint extends XmlEncodingBase implements Serializable { @@ -57,8 +52,7 @@ public static final String ROLE_ALL_ROLES = "*"; public static final String ROLE_ALL_AUTHENTICATED_USERS = "**"; - private static final StringManager sm = - StringManager.getManager(Constants.PACKAGE_NAME); + private static final StringManager sm = StringManager.getManager(Constants.PACKAGE_NAME); // ----------------------------------------------------------- Constructors @@ -75,39 +69,35 @@ /** - * Was the "all roles" wildcard - {@link #ROLE_ALL_ROLES} - included in the - * authorization constraints for this security constraint? + * Was the "all roles" wildcard - {@link #ROLE_ALL_ROLES} - included in the authorization constraints for this + * security constraint? */ private boolean allRoles = false; /** - * Was the "all authenticated users" wildcard - - * {@link #ROLE_ALL_AUTHENTICATED_USERS} - included in the authorization - * constraints for this security constraint? + * Was the "all authenticated users" wildcard - {@link #ROLE_ALL_AUTHENTICATED_USERS} - included in the + * authorization constraints for this security constraint? */ private boolean authenticatedUsers = false; /** - * Was an authorization constraint included in this security constraint? - * This is necessary to distinguish the case where an auth-constraint with - * no roles (signifying no direct access at all) was requested, versus - * a lack of auth-constraint which implies no access control checking. + * Was an authorization constraint included in this security constraint? This is necessary to distinguish the case + * where an auth-constraint with no roles (signifying no direct access at all) was requested, versus a lack of + * auth-constraint which implies no access control checking. */ private boolean authConstraint = false; /** - * The set of roles permitted to access resources protected by this - * security constraint. + * The set of roles permitted to access resources protected by this security constraint. */ private String[] authRoles = new String[0]; /** - * The set of web resource collections protected by this security - * constraint. + * The set of web resource collections protected by this security constraint. */ private SecurityCollection[] collections = new SecurityCollection[0]; @@ -119,8 +109,7 @@ /** - * The user data constraint for this security constraint. Must be NONE, - * INTEGRAL, or CONFIDENTIAL. + * The user data constraint for this security constraint. Must be NONE, INTEGRAL, or CONFIDENTIAL. */ private String userConstraint = "NONE"; @@ -129,8 +118,8 @@ /** - * Was the "all roles" wildcard included in this authentication - * constraint? + * Was the "all roles" wildcard included in this authentication constraint? + * * @return true if all roles */ public boolean getAllRoles() { @@ -141,8 +130,8 @@ /** - * Was the "all authenticated users" wildcard included in this - * authentication constraint? + * Was the "all authenticated users" wildcard included in this authentication constraint? + * * @return true if all authenticated users */ public boolean getAuthenticatedUsers() { @@ -151,8 +140,8 @@ /** - * Return the authorization constraint present flag for this security - * constraint. + * Return the authorization constraint present flag for this security constraint. + * * @return true if this needs authorization */ public boolean getAuthConstraint() { @@ -163,8 +152,8 @@ /** - * Set the authorization constraint present flag for this security - * constraint. + * Set the authorization constraint present flag for this security constraint. + * * @param authConstraint The new value */ public void setAuthConstraint(boolean authConstraint) { @@ -186,6 +175,7 @@ /** * Set the display name of this security constraint. + * * @param displayName The new value */ public void setDisplayName(String displayName) { @@ -197,6 +187,7 @@ /** * Return the user data constraint for this security constraint. + * * @return the user constraint */ public String getUserConstraint() { @@ -221,8 +212,7 @@ /** - * Called in the unlikely event that an application defines a role named - * "**". + * Called in the unlikely event that an application defines a role named "**". */ public void treatAllAuthenticatedUsersAsApplicationRole() { if (authenticatedUsers) { @@ -240,8 +230,8 @@ /** - * Add an authorization role, which is a role name that will be - * permitted access to the resources protected by this security constraint. + * Add an authorization role, which is a role name that will be permitted access to the resources protected by this + * security constraint. * * @param authRole Role name to be added */ @@ -278,8 +268,7 @@ /** - * Add a new web resource collection to those protected by this - * security constraint. + * Add a new web resource collection to those protected by this security constraint. * * @param collection The new web resource collection */ @@ -302,8 +291,9 @@ * Check a role. * * @param role Role name to be checked - * @return true if the specified role is permitted access to - * the resources protected by this security constraint. + * + * @return true if the specified role is permitted access to the resources protected by this security + * constraint. */ public boolean findAuthRole(String role) { @@ -321,10 +311,10 @@ /** - * Return the set of roles that are permitted access to the resources - * protected by this security constraint. If none have been defined, - * a zero-length array is returned (which implies that all authenticated - * users are permitted access). + * Return the set of roles that are permitted access to the resources protected by this security constraint. If none + * have been defined, a zero-length array is returned (which implies that all authenticated users are permitted + * access). + * * @return the roles array */ public String[] findAuthRoles() { @@ -333,10 +323,10 @@ /** - * Return the web resource collection for the specified name, if any; - * otherwise, return null. + * Return the web resource collection for the specified name, if any; otherwise, return null. * * @param name Web resource collection name to return + * * @return the collection */ public SecurityCollection findCollection(String name) { @@ -353,9 +343,9 @@ /** - * Return all of the web resource collections protected by this - * security constraint. If there are none, a zero-length array is - * returned. + * Return all of the web resource collections protected by this security constraint. If there are none, a + * zero-length array is returned. + * * @return the collections array */ public SecurityCollection[] findCollections() { @@ -365,10 +355,12 @@ /** * Check if the constraint applies to a URI and method. - * @param uri Context-relative URI to check + * + * @param uri Context-relative URI to check * @param method Request method being used - * @return true if the specified context-relative URI (and - * associated HTTP method) are protected by this security constraint. + * + * @return true if the specified context-relative URI (and associated HTTP method) are protected by + * this security constraint. */ public boolean included(String uri, String method) { @@ -397,8 +389,8 @@ /** - * Remove the specified role from the set of roles permitted to access - * the resources protected by this security constraint. + * Remove the specified role from the set of roles permitted to access the resources protected by this security + * constraint. * * @param authRole Role name to be removed */ @@ -439,8 +431,7 @@ /** - * Remove the specified web resource collection from those protected by - * this security constraint. + * Remove the specified web resource collection from those protected by this security constraint. * * @param collection Web resource collection to be removed */ @@ -458,8 +449,7 @@ } if (n >= 0) { int j = 0; - SecurityCollection[] results = - new SecurityCollection[collections.length - 1]; + SecurityCollection[] results = new SecurityCollection[collections.length - 1]; for (int i = 0; i < collections.length; i++) { if (i != n) { results[j++] = collections[i]; @@ -492,12 +482,10 @@ /** - * Does the specified request path match the specified URL pattern? - * This method follows the same rules (in the same order) as those used - * for mapping requests to servlets. + * Does the specified request path match the specified URL pattern? This method follows the same rules (in the same + * order) as those used for mapping requests to servlets. * - * @param path Context-relative request path to be checked - * (must start with '/') + * @param path Context-relative request path to be checked (must start with '/') * @param pattern URL pattern to be compared against */ private boolean matchPattern(String path, String pattern) { @@ -519,7 +507,7 @@ if (pattern.startsWith("/") && pattern.endsWith("/*")) { pattern = pattern.substring(0, pattern.length() - 2); if (pattern.isEmpty()) { - return true; // "/*" is the same as "/" + return true; // "/*" is the same as "/" } if (path.endsWith("/")) { path = path.substring(0, path.length() - 1); @@ -541,8 +529,7 @@ if (pattern.startsWith("*.")) { int slash = path.lastIndexOf('/'); int period = path.lastIndexOf('.'); - return (slash >= 0) && (period > slash) && - path.endsWith(pattern.substring(1)); + return (slash >= 0) && (period > slash) && path.endsWith(pattern.substring(1)); } // Check for universal mapping @@ -552,25 +539,20 @@ /** - * Convert a {@link ServletSecurityElement} to an array of - * {@link SecurityConstraint}(s). + * Convert a {@link ServletSecurityElement} to an array of {@link SecurityConstraint}(s). + * + * @param element The element to be converted + * @param urlPattern The url pattern that the element should be applied to * - * @param element The element to be converted - * @param urlPattern The url pattern that the element should be applied - * to - * @return The (possibly zero length) array of constraints that - * are the equivalent to the input + * @return The (possibly zero length) array of constraints that are the equivalent to the input */ - public static SecurityConstraint[] createConstraints( - ServletSecurityElement element, String urlPattern) { + public static SecurityConstraint[] createConstraints(ServletSecurityElement element, String urlPattern) { Set result = new HashSet<>(); // Add the per method constraints - Collection methods = - element.getHttpMethodConstraints(); + Collection methods = element.getHttpMethodConstraints(); for (HttpMethodConstraintElement methodElement : methods) { - SecurityConstraint constraint = - createConstraint(methodElement, urlPattern, true); + SecurityConstraint constraint = createConstraint(methodElement, urlPattern, true); // There will always be a single collection SecurityCollection collection = constraint.findCollections()[0]; collection.addMethod(methodElement.getMethodName()); @@ -593,15 +575,14 @@ return result.toArray(new SecurityConstraint[0]); } - private static SecurityConstraint createConstraint( - HttpConstraintElement element, String urlPattern, boolean alwaysCreate) { + private static SecurityConstraint createConstraint(HttpConstraintElement element, String urlPattern, + boolean alwaysCreate) { SecurityConstraint constraint = new SecurityConstraint(); SecurityCollection collection = new SecurityCollection(); boolean create = alwaysCreate; - if (element.getTransportGuarantee() != - ServletSecurity.TransportGuarantee.NONE) { + if (element.getTransportGuarantee() != ServletSecurity.TransportGuarantee.NONE) { constraint.setUserConstraint(element.getTransportGuarantee().name()); create = true; } @@ -627,8 +608,7 @@ } - public static SecurityConstraint[] findUncoveredHttpMethods( - SecurityConstraint[] constraints, + public static SecurityConstraint[] findUncoveredHttpMethods(SecurityConstraint[] constraints, boolean denyUncoveredHttpMethods, Log log) { Set coveredPatterns = new HashSet<>(); @@ -682,7 +662,7 @@ } // Now check the potentially uncovered patterns - for (Map.Entry> entry : urlMethodMap.entrySet()) { + for (Map.Entry> entry : urlMethodMap.entrySet()) { String pattern = entry.getKey(); if (coveredPatterns.contains(pattern)) { // Fully covered. Ignore any partial coverage @@ -700,9 +680,7 @@ msg.append(' '); } if (denyUncoveredHttpMethods) { - log.info(sm.getString( - "securityConstraint.uncoveredHttpMethodFix", - pattern, msg.toString().trim())); + log.info(sm.getString("securityConstraint.uncoveredHttpMethodFix", pattern, msg.toString().trim())); SecurityCollection collection = new SecurityCollection(); for (String method : methods) { collection.addOmittedMethod(method); @@ -714,9 +692,7 @@ constraint.addCollection(collection); newConstraints.add(constraint); } else { - log.error(sm.getString( - "securityConstraint.uncoveredHttpMethod", - pattern, msg.toString().trim())); + log.error(sm.getString("securityConstraint.uncoveredHttpMethod", pattern, msg.toString().trim())); } continue; } @@ -725,19 +701,16 @@ // pattern is fully covered. omittedMethods.removeAll(methods); - handleOmittedMethods(omittedMethods, pattern, denyUncoveredHttpMethods, - newConstraints, log); + handleOmittedMethods(omittedMethods, pattern, denyUncoveredHttpMethods, newConstraints, log); } - for (Map.Entry> entry : - urlOmittedMethodMap.entrySet()) { + for (Map.Entry> entry : urlOmittedMethodMap.entrySet()) { String pattern = entry.getKey(); if (coveredPatterns.contains(pattern)) { // Fully covered. Ignore any partial coverage continue; } - handleOmittedMethods(entry.getValue(), pattern, denyUncoveredHttpMethods, - newConstraints, log); + handleOmittedMethods(entry.getValue(), pattern, denyUncoveredHttpMethods, newConstraints, log); } return newConstraints.toArray(new SecurityConstraint[0]); @@ -753,9 +726,8 @@ msg.append(' '); } if (denyUncoveredHttpMethods) { - log.info(sm.getString( - "securityConstraint.uncoveredHttpOmittedMethodFix", - pattern, msg.toString().trim())); + log.info(sm.getString("securityConstraint.uncoveredHttpOmittedMethodFix", pattern, + msg.toString().trim())); SecurityCollection collection = new SecurityCollection(); for (String method : omittedMethods) { collection.addMethod(method); @@ -767,9 +739,8 @@ constraint.addCollection(collection); newConstraints.add(constraint); } else { - log.error(sm.getString( - "securityConstraint.uncoveredHttpOmittedMethod", - pattern, msg.toString().trim())); + log.error( + sm.getString("securityConstraint.uncoveredHttpOmittedMethod", pattern, msg.toString().trim())); } } } diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/descriptor/web/SecurityRoleRef.java tomcat10-10.1.52/java/org/apache/tomcat/util/descriptor/web/SecurityRoleRef.java --- tomcat10-10.1.40/java/org/apache/tomcat/util/descriptor/web/SecurityRoleRef.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/descriptor/web/SecurityRoleRef.java 2026-01-23 19:33:36.000000000 +0000 @@ -20,9 +20,10 @@ /** - *

      Representation of a security role reference for a web application, as - * represented in a <security-role-ref> element - * in the deployment descriptor.

      + *

      + * Representation of a security role reference for a web application, as represented in a + * <security-role-ref> element in the deployment descriptor. + *

      * * @since Tomcat 5.5 */ @@ -61,7 +62,6 @@ } - // --------------------------------------------------------- Public Methods diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/descriptor/web/ServletDef.java tomcat10-10.1.52/java/org/apache/tomcat/util/descriptor/web/ServletDef.java --- tomcat10-10.1.40/java/org/apache/tomcat/util/descriptor/web/ServletDef.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/descriptor/web/ServletDef.java 2026-01-23 19:33:36.000000000 +0000 @@ -26,16 +26,15 @@ /** - * Representation of a servlet definition for a web application, as represented - * in a <servlet> element in the deployment descriptor. + * Representation of a servlet definition for a web application, as represented in a <servlet> + * element in the deployment descriptor. */ public class ServletDef implements Serializable { private static final long serialVersionUID = 1L; - private static final StringManager sm = - StringManager.getManager(Constants.PACKAGE_NAME); + private static final StringManager sm = StringManager.getManager(Constants.PACKAGE_NAME); // ------------------------------------------------------------- Properties @@ -96,8 +95,7 @@ /** - * The name of this servlet, which must be unique among the servlets - * defined for a particular web application. + * The name of this servlet, which must be unique among the servlets defined for a particular web application. */ private String servletName = null; @@ -107,8 +105,7 @@ public void setServletName(String servletName) { if (servletName == null || servletName.isEmpty()) { - throw new IllegalArgumentException( - sm.getString("servletDef.invalidServletName", servletName)); + throw new IllegalArgumentException(sm.getString("servletDef.invalidServletName", servletName)); } this.servletName = servletName; } @@ -143,20 +140,18 @@ /** - * The set of initialization parameters for this servlet, keyed by - * parameter name. + * The set of initialization parameters for this servlet, keyed by parameter name. */ - private final Map parameters = new HashMap<>(); + private final Map parameters = new HashMap<>(); - public Map getParameterMap() { + public Map getParameterMap() { return this.parameters; } /** - * Add an initialization parameter to the set of parameters associated - * with this servlet. + * Add an initialization parameter to the set of parameters associated with this servlet. * - * @param name The initialisation parameter name + * @param name The initialisation parameter name * @param value The initialisation parameter value */ public void addInitParameter(String name, String value) { @@ -208,8 +203,8 @@ } /** - * Add a security-role-ref to the set of security-role-refs associated - * with this servlet. + * Add a security-role-ref to the set of security-role-refs associated with this servlet. + * * @param securityRoleRef The security role */ public void addSecurityRoleRef(SecurityRoleRef securityRoleRef) { diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/descriptor/web/SessionConfig.java tomcat10-10.1.52/java/org/apache/tomcat/util/descriptor/web/SessionConfig.java --- tomcat10-10.1.40/java/org/apache/tomcat/util/descriptor/web/SessionConfig.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/descriptor/web/SessionConfig.java 2026-01-23 19:33:36.000000000 +0000 @@ -23,21 +23,20 @@ import jakarta.servlet.SessionTrackingMode; /** - * Representation of a session configuration element for a web application, - * as represented in a <session-config> element in the - * deployment descriptor. + * Representation of a session configuration element for a web application, as represented in a + * <session-config> element in the deployment descriptor. */ public class SessionConfig { private Integer sessionTimeout; private String cookieName; private final Map cookieAttributes = new TreeMap<>(String.CASE_INSENSITIVE_ORDER); - private final EnumSet sessionTrackingModes = - EnumSet.noneOf(SessionTrackingMode.class); + private final EnumSet sessionTrackingModes = EnumSet.noneOf(SessionTrackingMode.class); public Integer getSessionTimeout() { return sessionTimeout; } + public void setSessionTimeout(String sessionTimeout) { this.sessionTimeout = Integer.valueOf(sessionTimeout); } @@ -45,6 +44,7 @@ public String getCookieName() { return cookieName; } + public void setCookieName(String cookieName) { this.cookieName = cookieName; } @@ -52,6 +52,7 @@ public String getCookieDomain() { return getCookieAttribute(Constants.COOKIE_DOMAIN_ATTR); } + public void setCookieDomain(String cookieDomain) { setCookieAttribute(Constants.COOKIE_DOMAIN_ATTR, cookieDomain); } @@ -59,6 +60,7 @@ public String getCookiePath() { return getCookieAttribute(Constants.COOKIE_PATH_ATTR); } + public void setCookiePath(String cookiePath) { setCookieAttribute(Constants.COOKIE_PATH_ATTR, cookiePath); } @@ -66,6 +68,7 @@ public String getCookieComment() { return getCookieAttribute(Constants.COOKIE_COMMENT_ATTR); } + public void setCookieComment(String cookieComment) { setCookieAttribute(Constants.COOKIE_COMMENT_ATTR, cookieComment); } @@ -77,6 +80,7 @@ } return Boolean.valueOf(httpOnly); } + public void setCookieHttpOnly(String cookieHttpOnly) { setCookieAttribute(Constants.COOKIE_HTTP_ONLY_ATTR, cookieHttpOnly); } @@ -88,6 +92,7 @@ } return Boolean.valueOf(secure); } + public void setCookieSecure(String cookieSecure) { setCookieAttribute(Constants.COOKIE_SECURE_ATTR, cookieSecure); } @@ -99,6 +104,7 @@ } return Integer.valueOf(maxAge); } + public void setCookieMaxAge(String cookieMaxAge) { setCookieAttribute(Constants.COOKIE_MAX_AGE_ATTR, cookieMaxAge); } @@ -106,9 +112,11 @@ public Map getCookieAttributes() { return cookieAttributes; } + public void setCookieAttribute(String name, String value) { cookieAttributes.put(name, value); } + public String getCookieAttribute(String name) { return cookieAttributes.get(name); } @@ -116,8 +124,8 @@ public EnumSet getSessionTrackingModes() { return sessionTrackingModes; } + public void addSessionTrackingMode(String sessionTrackingMode) { - sessionTrackingModes.add( - SessionTrackingMode.valueOf(sessionTrackingMode)); + sessionTrackingModes.add(SessionTrackingMode.valueOf(sessionTrackingMode)); } } diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/descriptor/web/TaglibDescriptorImpl.java tomcat10-10.1.52/java/org/apache/tomcat/util/descriptor/web/TaglibDescriptorImpl.java --- tomcat10-10.1.40/java/org/apache/tomcat/util/descriptor/web/TaglibDescriptorImpl.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/descriptor/web/TaglibDescriptorImpl.java 2026-01-23 19:33:36.000000000 +0000 @@ -42,8 +42,7 @@ public int hashCode() { final int prime = 31; int result = 1; - result = prime * result - + ((location == null) ? 0 : location.hashCode()); + result = prime * result + ((location == null) ? 0 : location.hashCode()); result = prime * result + ((uri == null) ? 0 : uri.hashCode()); return result; } diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/descriptor/web/WebRuleSet.java tomcat10-10.1.52/java/org/apache/tomcat/util/descriptor/web/WebRuleSet.java --- tomcat10-10.1.40/java/org/apache/tomcat/util/descriptor/web/WebRuleSet.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/descriptor/web/WebRuleSet.java 2026-01-23 19:33:36.000000000 +0000 @@ -30,18 +30,17 @@ import org.xml.sax.Attributes; /** - *

      RuleSet for processing the contents of a web application - * deployment descriptor (/WEB-INF/web.xml) resource.

      - * - * @author Craig R. McClanahan + *

      + * RuleSet for processing the contents of a web application deployment descriptor + * (/WEB-INF/web.xml) resource. + *

      */ public class WebRuleSet implements RuleSet { /** * The string resources for this package. */ - protected static final StringManager sm = - StringManager.getManager(Constants.PACKAGE_NAME); + protected static final StringManager sm = StringManager.getManager(Constants.PACKAGE_NAME); // ----------------------------------------------------- Instance Variables @@ -52,14 +51,12 @@ protected final String prefix; /** - * The full pattern matching prefix, including the webapp or web-fragment - * component, to use for matching elements + * The full pattern matching prefix, including the webapp or web-fragment component, to use for matching elements */ protected final String fullPrefix; /** - * Flag that indicates if this ruleset is for a web-fragment.xml file or for - * a web.xml file. + * Flag that indicates if this ruleset is for a web-fragment.xml file or for a web.xml file. */ protected final boolean fragment; @@ -99,13 +96,12 @@ protected final RelativeOrderingRule relativeOrdering; - // ------------------------------------------------------------ Constructor /** - * Construct an instance of this RuleSet with the default - * matching pattern prefix and default fragment setting. + * Construct an instance of this RuleSet with the default matching pattern prefix and default fragment + * setting. */ public WebRuleSet() { @@ -115,8 +111,8 @@ /** - * Construct an instance of this RuleSet with the default - * matching pattern prefix. + * Construct an instance of this RuleSet with the default matching pattern prefix. + * * @param fragment true if this is a web fragment */ public WebRuleSet(boolean fragment) { @@ -127,18 +123,16 @@ /** - * Construct an instance of this RuleSet with the specified - * matching pattern prefix. + * Construct an instance of this RuleSet with the specified matching pattern prefix. * - * @param prefix Prefix for matching pattern rules (including the - * trailing slash character) + * @param prefix Prefix for matching pattern rules (including the trailing slash character) * @param fragment true if this is a web fragment */ public WebRuleSet(String prefix, boolean fragment) { this.prefix = prefix; this.fragment = fragment; - if(fragment) { + if (fragment) { fullPrefix = prefix + "web-fragment"; } else { fullPrefix = prefix + "web-app"; @@ -152,22 +146,18 @@ // --------------------------------------------------------- Public Methods /** - *

      Add the set of Rule instances defined in this RuleSet to the - * specified Digester instance, associating them with - * our namespace URI (if any). This method should only be called - * by a Digester instance.

      + *

      + * Add the set of Rule instances defined in this RuleSet to the specified Digester instance, + * associating them with our namespace URI (if any). This method should only be called by a Digester instance. + *

      * - * @param digester Digester instance to which the new Rule instances - * should be added. + * @param digester Digester instance to which the new Rule instances should be added. */ @Override public void addRuleInstances(Digester digester) { - digester.addRule(fullPrefix, - new SetPublicIdRule("setPublicId")); - digester.addRule(fullPrefix, - new IgnoreAnnotationsRule()); - digester.addRule(fullPrefix, - new VersionRule()); + digester.addRule(fullPrefix, new SetPublicIdRule("setPublicId")); + digester.addRule(fullPrefix, new IgnoreAnnotationsRule()); + digester.addRule(fullPrefix, new VersionRule()); // Required for both fragments and non-fragments digester.addRule(fullPrefix + "/absolute-ordering", absoluteOrdering); @@ -176,515 +166,344 @@ if (fragment) { // web-fragment.xml digester.addRule(fullPrefix + "/name", name); - digester.addCallMethod(fullPrefix + "/ordering/after/name", - "addAfterOrdering", 0); - digester.addCallMethod(fullPrefix + "/ordering/after/others", - "addAfterOrderingOthers"); - digester.addCallMethod(fullPrefix + "/ordering/before/name", - "addBeforeOrdering", 0); - digester.addCallMethod(fullPrefix + "/ordering/before/others", - "addBeforeOrderingOthers"); + digester.addCallMethod(fullPrefix + "/ordering/after/name", "addAfterOrdering", 0); + digester.addCallMethod(fullPrefix + "/ordering/after/others", "addAfterOrderingOthers"); + digester.addCallMethod(fullPrefix + "/ordering/before/name", "addBeforeOrdering", 0); + digester.addCallMethod(fullPrefix + "/ordering/before/others", "addBeforeOrderingOthers"); } else { // web.xml - digester.addCallMethod(fullPrefix + "/absolute-ordering/name", - "addAbsoluteOrdering", 0); - digester.addCallMethod(fullPrefix + "/absolute-ordering/others", - "addAbsoluteOrderingOthers"); - digester.addRule(fullPrefix + "/deny-uncovered-http-methods", - new SetDenyUncoveredHttpMethodsRule()); - digester.addCallMethod(fullPrefix + "/request-character-encoding", - "setRequestCharacterEncoding", 0); - digester.addCallMethod(fullPrefix + "/response-character-encoding", - "setResponseCharacterEncoding", 0); + digester.addCallMethod(fullPrefix + "/absolute-ordering/name", "addAbsoluteOrdering", 0); + digester.addCallMethod(fullPrefix + "/absolute-ordering/others", "addAbsoluteOrderingOthers"); + digester.addRule(fullPrefix + "/deny-uncovered-http-methods", new SetDenyUncoveredHttpMethodsRule()); + digester.addCallMethod(fullPrefix + "/request-character-encoding", "setRequestCharacterEncoding", 0); + digester.addCallMethod(fullPrefix + "/response-character-encoding", "setResponseCharacterEncoding", 0); } - digester.addCallMethod(fullPrefix + "/context-param", - "addContextParam", 2); + digester.addCallMethod(fullPrefix + "/context-param", "addContextParam", 2); digester.addCallParam(fullPrefix + "/context-param/param-name", 0); digester.addCallParam(fullPrefix + "/context-param/param-value", 1); - digester.addCallMethod(fullPrefix + "/display-name", - "setDisplayName", 0); + digester.addCallMethod(fullPrefix + "/display-name", "setDisplayName", 0); - digester.addRule(fullPrefix + "/distributable", - new SetDistributableRule()); + digester.addRule(fullPrefix + "/distributable", new SetDistributableRule()); configureNamingRules(digester); - digester.addObjectCreate(fullPrefix + "/error-page", - "org.apache.tomcat.util.descriptor.web.ErrorPage"); - digester.addSetNext(fullPrefix + "/error-page", - "addErrorPage", - "org.apache.tomcat.util.descriptor.web.ErrorPage"); - - digester.addCallMethod(fullPrefix + "/error-page/error-code", - "setErrorCode", 0); - digester.addCallMethod(fullPrefix + "/error-page/exception-type", - "setExceptionType", 0); - digester.addCallMethod(fullPrefix + "/error-page/location", - "setLocation", 0); - - digester.addObjectCreate(fullPrefix + "/filter", - "org.apache.tomcat.util.descriptor.web.FilterDef"); - digester.addSetNext(fullPrefix + "/filter", - "addFilter", - "org.apache.tomcat.util.descriptor.web.FilterDef"); - - digester.addCallMethod(fullPrefix + "/filter/description", - "setDescription", 0); - digester.addCallMethod(fullPrefix + "/filter/display-name", - "setDisplayName", 0); - digester.addCallMethod(fullPrefix + "/filter/filter-class", - "setFilterClass", 0); - digester.addCallMethod(fullPrefix + "/filter/filter-name", - "setFilterName", 0); - digester.addCallMethod(fullPrefix + "/filter/icon/large-icon", - "setLargeIcon", 0); - digester.addCallMethod(fullPrefix + "/filter/icon/small-icon", - "setSmallIcon", 0); - digester.addCallMethod(fullPrefix + "/filter/async-supported", - "setAsyncSupported", 0); - - digester.addCallMethod(fullPrefix + "/filter/init-param", - "addInitParameter", 2); - digester.addCallParam(fullPrefix + "/filter/init-param/param-name", - 0); - digester.addCallParam(fullPrefix + "/filter/init-param/param-value", - 1); - - digester.addObjectCreate(fullPrefix + "/filter-mapping", - "org.apache.tomcat.util.descriptor.web.FilterMap"); - digester.addSetNext(fullPrefix + "/filter-mapping", - "addFilterMapping", - "org.apache.tomcat.util.descriptor.web.FilterMap"); - - digester.addCallMethod(fullPrefix + "/filter-mapping/filter-name", - "setFilterName", 0); - digester.addCallMethod(fullPrefix + "/filter-mapping/servlet-name", - "addServletName", 0); - digester.addCallMethod(fullPrefix + "/filter-mapping/url-pattern", - "addURLPattern", 0); + digester.addObjectCreate(fullPrefix + "/error-page", "org.apache.tomcat.util.descriptor.web.ErrorPage"); + digester.addSetNext(fullPrefix + "/error-page", "addErrorPage", + "org.apache.tomcat.util.descriptor.web.ErrorPage"); + + digester.addCallMethod(fullPrefix + "/error-page/error-code", "setErrorCode", 0); + digester.addCallMethod(fullPrefix + "/error-page/exception-type", "setExceptionType", 0); + digester.addCallMethod(fullPrefix + "/error-page/location", "setLocation", 0); + + digester.addObjectCreate(fullPrefix + "/filter", "org.apache.tomcat.util.descriptor.web.FilterDef"); + digester.addSetNext(fullPrefix + "/filter", "addFilter", "org.apache.tomcat.util.descriptor.web.FilterDef"); + + digester.addCallMethod(fullPrefix + "/filter/description", "setDescription", 0); + digester.addCallMethod(fullPrefix + "/filter/display-name", "setDisplayName", 0); + digester.addCallMethod(fullPrefix + "/filter/filter-class", "setFilterClass", 0); + digester.addCallMethod(fullPrefix + "/filter/filter-name", "setFilterName", 0); + digester.addCallMethod(fullPrefix + "/filter/icon/large-icon", "setLargeIcon", 0); + digester.addCallMethod(fullPrefix + "/filter/icon/small-icon", "setSmallIcon", 0); + digester.addCallMethod(fullPrefix + "/filter/async-supported", "setAsyncSupported", 0); + + digester.addCallMethod(fullPrefix + "/filter/init-param", "addInitParameter", 2); + digester.addCallParam(fullPrefix + "/filter/init-param/param-name", 0); + digester.addCallParam(fullPrefix + "/filter/init-param/param-value", 1); + + digester.addObjectCreate(fullPrefix + "/filter-mapping", "org.apache.tomcat.util.descriptor.web.FilterMap"); + digester.addSetNext(fullPrefix + "/filter-mapping", "addFilterMapping", + "org.apache.tomcat.util.descriptor.web.FilterMap"); + + digester.addCallMethod(fullPrefix + "/filter-mapping/filter-name", "setFilterName", 0); + digester.addCallMethod(fullPrefix + "/filter-mapping/servlet-name", "addServletName", 0); + digester.addCallMethod(fullPrefix + "/filter-mapping/url-pattern", "addURLPattern", 0); - digester.addCallMethod(fullPrefix + "/filter-mapping/dispatcher", - "setDispatcher", 0); + digester.addCallMethod(fullPrefix + "/filter-mapping/dispatcher", "setDispatcher", 0); - digester.addCallMethod(fullPrefix + "/listener/listener-class", - "addListener", 0); + digester.addCallMethod(fullPrefix + "/listener/listener-class", "addListener", 0); - digester.addRule(fullPrefix + "/jsp-config", - jspConfig); + digester.addRule(fullPrefix + "/jsp-config", jspConfig); digester.addObjectCreate(fullPrefix + "/jsp-config/jsp-property-group", - "org.apache.tomcat.util.descriptor.web.JspPropertyGroup"); - digester.addSetNext(fullPrefix + "/jsp-config/jsp-property-group", - "addJspPropertyGroup", - "org.apache.tomcat.util.descriptor.web.JspPropertyGroup"); + "org.apache.tomcat.util.descriptor.web.JspPropertyGroup"); + digester.addSetNext(fullPrefix + "/jsp-config/jsp-property-group", "addJspPropertyGroup", + "org.apache.tomcat.util.descriptor.web.JspPropertyGroup"); digester.addCallMethod(fullPrefix + "/jsp-config/jsp-property-group/deferred-syntax-allowed-as-literal", - "setDeferredSyntax", 0); - digester.addCallMethod(fullPrefix + "/jsp-config/jsp-property-group/el-ignored", - "setElIgnored", 0); + "setDeferredSyntax", 0); + digester.addCallMethod(fullPrefix + "/jsp-config/jsp-property-group/el-ignored", "setElIgnored", 0); digester.addCallMethod(fullPrefix + "/jsp-config/jsp-property-group/error-on-el-not-found", - "setErrorOnELNotFound", 0); - digester.addCallMethod(fullPrefix + "/jsp-config/jsp-property-group/include-coda", - "addIncludeCoda", 0); - digester.addCallMethod(fullPrefix + "/jsp-config/jsp-property-group/include-prelude", - "addIncludePrelude", 0); - digester.addCallMethod(fullPrefix + "/jsp-config/jsp-property-group/is-xml", - "setIsXml", 0); - digester.addCallMethod(fullPrefix + "/jsp-config/jsp-property-group/page-encoding", - "setPageEncoding", 0); - digester.addCallMethod(fullPrefix + "/jsp-config/jsp-property-group/scripting-invalid", - "setScriptingInvalid", 0); + "setErrorOnELNotFound", 0); + digester.addCallMethod(fullPrefix + "/jsp-config/jsp-property-group/include-coda", "addIncludeCoda", 0); + digester.addCallMethod(fullPrefix + "/jsp-config/jsp-property-group/include-prelude", "addIncludePrelude", 0); + digester.addCallMethod(fullPrefix + "/jsp-config/jsp-property-group/is-xml", "setIsXml", 0); + digester.addCallMethod(fullPrefix + "/jsp-config/jsp-property-group/page-encoding", "setPageEncoding", 0); + digester.addCallMethod(fullPrefix + "/jsp-config/jsp-property-group/scripting-invalid", "setScriptingInvalid", + 0); digester.addCallMethod(fullPrefix + "/jsp-config/jsp-property-group/trim-directive-whitespaces", - "setTrimWhitespace", 0); - digester.addCallMethod(fullPrefix + "/jsp-config/jsp-property-group/url-pattern", - "addUrlPattern", 0); + "setTrimWhitespace", 0); + digester.addCallMethod(fullPrefix + "/jsp-config/jsp-property-group/url-pattern", "addUrlPattern", 0); digester.addCallMethod(fullPrefix + "/jsp-config/jsp-property-group/default-content-type", - "setDefaultContentType", 0); - digester.addCallMethod(fullPrefix + "/jsp-config/jsp-property-group/buffer", - "setBuffer", 0); + "setDefaultContentType", 0); + digester.addCallMethod(fullPrefix + "/jsp-config/jsp-property-group/buffer", "setBuffer", 0); digester.addCallMethod(fullPrefix + "/jsp-config/jsp-property-group/error-on-undeclared-namespace", - "setErrorOnUndeclaredNamespace", 0); + "setErrorOnUndeclaredNamespace", 0); + + digester.addRule(fullPrefix + "/login-config", loginConfig); - digester.addRule(fullPrefix + "/login-config", - loginConfig); + digester.addObjectCreate(fullPrefix + "/login-config", "org.apache.tomcat.util.descriptor.web.LoginConfig"); + digester.addSetNext(fullPrefix + "/login-config", "setLoginConfig", + "org.apache.tomcat.util.descriptor.web.LoginConfig"); - digester.addObjectCreate(fullPrefix + "/login-config", - "org.apache.tomcat.util.descriptor.web.LoginConfig"); - digester.addSetNext(fullPrefix + "/login-config", - "setLoginConfig", - "org.apache.tomcat.util.descriptor.web.LoginConfig"); - - digester.addCallMethod(fullPrefix + "/login-config/auth-method", - "setAuthMethod", 0); - digester.addCallMethod(fullPrefix + "/login-config/realm-name", - "setRealmName", 0); - digester.addCallMethod(fullPrefix + "/login-config/form-login-config/form-error-page", - "setErrorPage", 0); - digester.addCallMethod(fullPrefix + "/login-config/form-login-config/form-login-page", - "setLoginPage", 0); + digester.addCallMethod(fullPrefix + "/login-config/auth-method", "setAuthMethod", 0); + digester.addCallMethod(fullPrefix + "/login-config/realm-name", "setRealmName", 0); + digester.addCallMethod(fullPrefix + "/login-config/form-login-config/form-error-page", "setErrorPage", 0); + digester.addCallMethod(fullPrefix + "/login-config/form-login-config/form-login-page", "setLoginPage", 0); - digester.addCallMethod(fullPrefix + "/mime-mapping", - "addMimeMapping", 2); + digester.addCallMethod(fullPrefix + "/mime-mapping", "addMimeMapping", 2); digester.addCallParam(fullPrefix + "/mime-mapping/extension", 0); digester.addCallParam(fullPrefix + "/mime-mapping/mime-type", 1); digester.addObjectCreate(fullPrefix + "/security-constraint", - "org.apache.tomcat.util.descriptor.web.SecurityConstraint"); - digester.addSetNext(fullPrefix + "/security-constraint", - "addSecurityConstraint", - "org.apache.tomcat.util.descriptor.web.SecurityConstraint"); - - digester.addRule(fullPrefix + "/security-constraint/auth-constraint", - new SetAuthConstraintRule()); - digester.addCallMethod(fullPrefix + "/security-constraint/auth-constraint/role-name", - "addAuthRole", 0); - digester.addCallMethod(fullPrefix + "/security-constraint/display-name", - "setDisplayName", 0); + "org.apache.tomcat.util.descriptor.web.SecurityConstraint"); + digester.addSetNext(fullPrefix + "/security-constraint", "addSecurityConstraint", + "org.apache.tomcat.util.descriptor.web.SecurityConstraint"); + + digester.addRule(fullPrefix + "/security-constraint/auth-constraint", new SetAuthConstraintRule()); + digester.addCallMethod(fullPrefix + "/security-constraint/auth-constraint/role-name", "addAuthRole", 0); + digester.addCallMethod(fullPrefix + "/security-constraint/display-name", "setDisplayName", 0); digester.addCallMethod(fullPrefix + "/security-constraint/user-data-constraint/transport-guarantee", - "setUserConstraint", 0); + "setUserConstraint", 0); digester.addObjectCreate(fullPrefix + "/security-constraint/web-resource-collection", - "org.apache.tomcat.util.descriptor.web.SecurityCollection"); - digester.addSetNext(fullPrefix + "/security-constraint/web-resource-collection", - "addCollection", - "org.apache.tomcat.util.descriptor.web.SecurityCollection"); - digester.addCallMethod(fullPrefix + "/security-constraint/web-resource-collection/http-method", - "addMethod", 0); + "org.apache.tomcat.util.descriptor.web.SecurityCollection"); + digester.addSetNext(fullPrefix + "/security-constraint/web-resource-collection", "addCollection", + "org.apache.tomcat.util.descriptor.web.SecurityCollection"); + digester.addCallMethod(fullPrefix + "/security-constraint/web-resource-collection/http-method", "addMethod", 0); digester.addCallMethod(fullPrefix + "/security-constraint/web-resource-collection/http-method-omission", - "addOmittedMethod", 0); - digester.addCallMethod(fullPrefix + "/security-constraint/web-resource-collection/url-pattern", - "addPattern", 0); - digester.addCallMethod(fullPrefix + "/security-constraint/web-resource-collection/web-resource-name", - "setName", 0); - - digester.addCallMethod(fullPrefix + "/security-role/role-name", - "addSecurityRole", 0); - - digester.addRule(fullPrefix + "/servlet", - new ServletDefCreateRule()); - digester.addSetNext(fullPrefix + "/servlet", - "addServlet", - "org.apache.tomcat.util.descriptor.web.ServletDef"); - - digester.addCallMethod(fullPrefix + "/servlet/init-param", - "addInitParameter", 2); - digester.addCallParam(fullPrefix + "/servlet/init-param/param-name", - 0); - digester.addCallParam(fullPrefix + "/servlet/init-param/param-value", - 1); - - digester.addCallMethod(fullPrefix + "/servlet/jsp-file", - "setJspFile", 0); - digester.addCallMethod(fullPrefix + "/servlet/load-on-startup", - "setLoadOnStartup", 0); - digester.addCallMethod(fullPrefix + "/servlet/run-as/role-name", - "setRunAs", 0); + "addOmittedMethod", 0); + digester.addCallMethod(fullPrefix + "/security-constraint/web-resource-collection/url-pattern", "addPattern", + 0); + digester.addCallMethod(fullPrefix + "/security-constraint/web-resource-collection/web-resource-name", "setName", + 0); + + digester.addCallMethod(fullPrefix + "/security-role/role-name", "addSecurityRole", 0); + + digester.addRule(fullPrefix + "/servlet", new ServletDefCreateRule()); + digester.addSetNext(fullPrefix + "/servlet", "addServlet", "org.apache.tomcat.util.descriptor.web.ServletDef"); + + digester.addCallMethod(fullPrefix + "/servlet/init-param", "addInitParameter", 2); + digester.addCallParam(fullPrefix + "/servlet/init-param/param-name", 0); + digester.addCallParam(fullPrefix + "/servlet/init-param/param-value", 1); + + digester.addCallMethod(fullPrefix + "/servlet/jsp-file", "setJspFile", 0); + digester.addCallMethod(fullPrefix + "/servlet/load-on-startup", "setLoadOnStartup", 0); + digester.addCallMethod(fullPrefix + "/servlet/run-as/role-name", "setRunAs", 0); digester.addObjectCreate(fullPrefix + "/servlet/security-role-ref", - "org.apache.tomcat.util.descriptor.web.SecurityRoleRef"); - digester.addSetNext(fullPrefix + "/servlet/security-role-ref", - "addSecurityRoleRef", - "org.apache.tomcat.util.descriptor.web.SecurityRoleRef"); - digester.addCallMethod(fullPrefix + "/servlet/security-role-ref/role-link", - "setLink", 0); - digester.addCallMethod(fullPrefix + "/servlet/security-role-ref/role-name", - "setName", 0); - - digester.addCallMethod(fullPrefix + "/servlet/servlet-class", - "setServletClass", 0); - digester.addCallMethod(fullPrefix + "/servlet/servlet-name", - "setServletName", 0); + "org.apache.tomcat.util.descriptor.web.SecurityRoleRef"); + digester.addSetNext(fullPrefix + "/servlet/security-role-ref", "addSecurityRoleRef", + "org.apache.tomcat.util.descriptor.web.SecurityRoleRef"); + digester.addCallMethod(fullPrefix + "/servlet/security-role-ref/role-link", "setLink", 0); + digester.addCallMethod(fullPrefix + "/servlet/security-role-ref/role-name", "setName", 0); + + digester.addCallMethod(fullPrefix + "/servlet/servlet-class", "setServletClass", 0); + digester.addCallMethod(fullPrefix + "/servlet/servlet-name", "setServletName", 0); digester.addObjectCreate(fullPrefix + "/servlet/multipart-config", - "org.apache.tomcat.util.descriptor.web.MultipartDef"); - digester.addSetNext(fullPrefix + "/servlet/multipart-config", - "setMultipartDef", - "org.apache.tomcat.util.descriptor.web.MultipartDef"); - digester.addCallMethod(fullPrefix + "/servlet/multipart-config/location", - "setLocation", 0); - digester.addCallMethod(fullPrefix + "/servlet/multipart-config/max-file-size", - "setMaxFileSize", 0); - digester.addCallMethod(fullPrefix + "/servlet/multipart-config/max-request-size", - "setMaxRequestSize", 0); - digester.addCallMethod(fullPrefix + "/servlet/multipart-config/file-size-threshold", - "setFileSizeThreshold", 0); - - digester.addCallMethod(fullPrefix + "/servlet/async-supported", - "setAsyncSupported", 0); - digester.addCallMethod(fullPrefix + "/servlet/enabled", - "setEnabled", 0); + "org.apache.tomcat.util.descriptor.web.MultipartDef"); + digester.addSetNext(fullPrefix + "/servlet/multipart-config", "setMultipartDef", + "org.apache.tomcat.util.descriptor.web.MultipartDef"); + digester.addCallMethod(fullPrefix + "/servlet/multipart-config/location", "setLocation", 0); + digester.addCallMethod(fullPrefix + "/servlet/multipart-config/max-file-size", "setMaxFileSize", 0); + digester.addCallMethod(fullPrefix + "/servlet/multipart-config/max-request-size", "setMaxRequestSize", 0); + digester.addCallMethod(fullPrefix + "/servlet/multipart-config/file-size-threshold", "setFileSizeThreshold", 0); + + digester.addCallMethod(fullPrefix + "/servlet/async-supported", "setAsyncSupported", 0); + digester.addCallMethod(fullPrefix + "/servlet/enabled", "setEnabled", 0); - digester.addRule(fullPrefix + "/servlet-mapping", - new CallMethodMultiRule("addServletMapping", 2, 0)); + digester.addRule(fullPrefix + "/servlet-mapping", new CallMethodMultiRule("addServletMapping", 2, 0)); digester.addCallParam(fullPrefix + "/servlet-mapping/servlet-name", 1); digester.addRule(fullPrefix + "/servlet-mapping/url-pattern", new CallParamMultiRule(0)); digester.addRule(fullPrefix + "/session-config", sessionConfig); - digester.addObjectCreate(fullPrefix + "/session-config", - "org.apache.tomcat.util.descriptor.web.SessionConfig"); + digester.addObjectCreate(fullPrefix + "/session-config", "org.apache.tomcat.util.descriptor.web.SessionConfig"); digester.addSetNext(fullPrefix + "/session-config", "setSessionConfig", - "org.apache.tomcat.util.descriptor.web.SessionConfig"); - digester.addCallMethod(fullPrefix + "/session-config/session-timeout", - "setSessionTimeout", 0); - digester.addCallMethod(fullPrefix + "/session-config/cookie-config/name", - "setCookieName", 0); - digester.addCallMethod(fullPrefix + "/session-config/cookie-config/domain", - "setCookieDomain", 0); - digester.addCallMethod(fullPrefix + "/session-config/cookie-config/path", - "setCookiePath", 0); - digester.addCallMethod(fullPrefix + "/session-config/cookie-config/comment", - "setCookieComment", 0); - digester.addCallMethod(fullPrefix + "/session-config/cookie-config/http-only", - "setCookieHttpOnly", 0); - digester.addCallMethod(fullPrefix + "/session-config/cookie-config/secure", - "setCookieSecure", 0); - digester.addCallMethod(fullPrefix + "/session-config/cookie-config/max-age", - "setCookieMaxAge", 0); - digester.addCallMethod(fullPrefix + "/session-config/cookie-config/attribute", - "setCookieAttribute", 2); + "org.apache.tomcat.util.descriptor.web.SessionConfig"); + digester.addCallMethod(fullPrefix + "/session-config/session-timeout", "setSessionTimeout", 0); + digester.addCallMethod(fullPrefix + "/session-config/cookie-config/name", "setCookieName", 0); + digester.addCallMethod(fullPrefix + "/session-config/cookie-config/domain", "setCookieDomain", 0); + digester.addCallMethod(fullPrefix + "/session-config/cookie-config/path", "setCookiePath", 0); + digester.addCallMethod(fullPrefix + "/session-config/cookie-config/comment", "setCookieComment", 0); + digester.addCallMethod(fullPrefix + "/session-config/cookie-config/http-only", "setCookieHttpOnly", 0); + digester.addCallMethod(fullPrefix + "/session-config/cookie-config/secure", "setCookieSecure", 0); + digester.addCallMethod(fullPrefix + "/session-config/cookie-config/max-age", "setCookieMaxAge", 0); + digester.addCallMethod(fullPrefix + "/session-config/cookie-config/attribute", "setCookieAttribute", 2); digester.addCallParam(fullPrefix + "/session-config/cookie-config/attribute/attribute-name", 0); digester.addCallParam(fullPrefix + "/session-config/cookie-config/attribute/attribute-value", 1); - digester.addCallMethod(fullPrefix + "/session-config/tracking-mode", - "addSessionTrackingMode", 0); + digester.addCallMethod(fullPrefix + "/session-config/tracking-mode", "addSessionTrackingMode", 0); // Taglibs pre Servlet 2.4 digester.addRule(fullPrefix + "/taglib", new TaglibLocationRule(false)); - digester.addCallMethod(fullPrefix + "/taglib", - "addTaglib", 2); + digester.addCallMethod(fullPrefix + "/taglib", "addTaglib", 2); digester.addCallParam(fullPrefix + "/taglib/taglib-location", 1); digester.addCallParam(fullPrefix + "/taglib/taglib-uri", 0); // Taglibs Servlet 2.4 onwards digester.addRule(fullPrefix + "/jsp-config/taglib", new TaglibLocationRule(true)); - digester.addCallMethod(fullPrefix + "/jsp-config/taglib", - "addTaglib", 2); + digester.addCallMethod(fullPrefix + "/jsp-config/taglib", "addTaglib", 2); digester.addCallParam(fullPrefix + "/jsp-config/taglib/taglib-location", 1); digester.addCallParam(fullPrefix + "/jsp-config/taglib/taglib-uri", 0); - digester.addCallMethod(fullPrefix + "/welcome-file-list/welcome-file", - "addWelcomeFile", 0); + digester.addCallMethod(fullPrefix + "/welcome-file-list/welcome-file", "addWelcomeFile", 0); digester.addCallMethod(fullPrefix + "/locale-encoding-mapping-list/locale-encoding-mapping", - "addLocaleEncodingMapping", 2); + "addLocaleEncodingMapping", 2); digester.addCallParam(fullPrefix + "/locale-encoding-mapping-list/locale-encoding-mapping/locale", 0); digester.addCallParam(fullPrefix + "/locale-encoding-mapping-list/locale-encoding-mapping/encoding", 1); - digester.addRule(fullPrefix + "/post-construct", - new LifecycleCallbackRule("addPostConstructMethods", 2, true)); + digester.addRule(fullPrefix + "/post-construct", new LifecycleCallbackRule("addPostConstructMethods", 2, true)); digester.addCallParam(fullPrefix + "/post-construct/lifecycle-callback-class", 0); digester.addCallParam(fullPrefix + "/post-construct/lifecycle-callback-method", 1); - digester.addRule(fullPrefix + "/pre-destroy", - new LifecycleCallbackRule("addPreDestroyMethods", 2, false)); + digester.addRule(fullPrefix + "/pre-destroy", new LifecycleCallbackRule("addPreDestroyMethods", 2, false)); digester.addCallParam(fullPrefix + "/pre-destroy/lifecycle-callback-class", 0); digester.addCallParam(fullPrefix + "/pre-destroy/lifecycle-callback-method", 1); } protected void configureNamingRules(Digester digester) { - //ejb-local-ref + // ejb-local-ref digester.addObjectCreate(fullPrefix + "/ejb-local-ref", - "org.apache.tomcat.util.descriptor.web.ContextLocalEjb"); - digester.addSetNext(fullPrefix + "/ejb-local-ref", - "addEjbLocalRef", - "org.apache.tomcat.util.descriptor.web.ContextLocalEjb"); - digester.addCallMethod(fullPrefix + "/ejb-local-ref/description", - "setDescription", 0); - digester.addCallMethod(fullPrefix + "/ejb-local-ref/ejb-link", - "setLink", 0); - digester.addCallMethod(fullPrefix + "/ejb-local-ref/ejb-ref-name", - "setName", 0); - digester.addCallMethod(fullPrefix + "/ejb-local-ref/ejb-ref-type", - "setType", 0); - digester.addCallMethod(fullPrefix + "/ejb-local-ref/local", - "setLocal", 0); - digester.addCallMethod(fullPrefix + "/ejb-local-ref/local-home", - "setHome", 0); - digester.addRule(fullPrefix + "/ejb-local-ref/mapped-name", - new MappedNameRule()); + "org.apache.tomcat.util.descriptor.web.ContextLocalEjb"); + digester.addSetNext(fullPrefix + "/ejb-local-ref", "addEjbLocalRef", + "org.apache.tomcat.util.descriptor.web.ContextLocalEjb"); + digester.addCallMethod(fullPrefix + "/ejb-local-ref/description", "setDescription", 0); + digester.addCallMethod(fullPrefix + "/ejb-local-ref/ejb-link", "setLink", 0); + digester.addCallMethod(fullPrefix + "/ejb-local-ref/ejb-ref-name", "setName", 0); + digester.addCallMethod(fullPrefix + "/ejb-local-ref/ejb-ref-type", "setType", 0); + digester.addCallMethod(fullPrefix + "/ejb-local-ref/local", "setLocal", 0); + digester.addCallMethod(fullPrefix + "/ejb-local-ref/local-home", "setHome", 0); + digester.addRule(fullPrefix + "/ejb-local-ref/mapped-name", new MappedNameRule()); digester.addCallMethod(fullPrefix + "/ejb-local-ref/lookup-name", "setLookupName", 0); configureInjectionRules(digester, "web-app/ejb-local-ref/"); - //ejb-ref - digester.addObjectCreate(fullPrefix + "/ejb-ref", - "org.apache.tomcat.util.descriptor.web.ContextEjb"); - digester.addSetNext(fullPrefix + "/ejb-ref", - "addEjbRef", - "org.apache.tomcat.util.descriptor.web.ContextEjb"); - digester.addCallMethod(fullPrefix + "/ejb-ref/description", - "setDescription", 0); - digester.addCallMethod(fullPrefix + "/ejb-ref/ejb-link", - "setLink", 0); - digester.addCallMethod(fullPrefix + "/ejb-ref/ejb-ref-name", - "setName", 0); - digester.addCallMethod(fullPrefix + "/ejb-ref/ejb-ref-type", - "setType", 0); - digester.addCallMethod(fullPrefix + "/ejb-ref/home", - "setHome", 0); - digester.addCallMethod(fullPrefix + "/ejb-ref/remote", - "setRemote", 0); - digester.addRule(fullPrefix + "/ejb-ref/mapped-name", - new MappedNameRule()); + // ejb-ref + digester.addObjectCreate(fullPrefix + "/ejb-ref", "org.apache.tomcat.util.descriptor.web.ContextEjb"); + digester.addSetNext(fullPrefix + "/ejb-ref", "addEjbRef", "org.apache.tomcat.util.descriptor.web.ContextEjb"); + digester.addCallMethod(fullPrefix + "/ejb-ref/description", "setDescription", 0); + digester.addCallMethod(fullPrefix + "/ejb-ref/ejb-link", "setLink", 0); + digester.addCallMethod(fullPrefix + "/ejb-ref/ejb-ref-name", "setName", 0); + digester.addCallMethod(fullPrefix + "/ejb-ref/ejb-ref-type", "setType", 0); + digester.addCallMethod(fullPrefix + "/ejb-ref/home", "setHome", 0); + digester.addCallMethod(fullPrefix + "/ejb-ref/remote", "setRemote", 0); + digester.addRule(fullPrefix + "/ejb-ref/mapped-name", new MappedNameRule()); digester.addCallMethod(fullPrefix + "/ejb-ref/lookup-name", "setLookupName", 0); configureInjectionRules(digester, "web-app/ejb-ref/"); - //env-entry - digester.addObjectCreate(fullPrefix + "/env-entry", - "org.apache.tomcat.util.descriptor.web.ContextEnvironment"); - digester.addSetNext(fullPrefix + "/env-entry", - "addEnvEntry", - "org.apache.tomcat.util.descriptor.web.ContextEnvironment"); + // env-entry + digester.addObjectCreate(fullPrefix + "/env-entry", "org.apache.tomcat.util.descriptor.web.ContextEnvironment"); + digester.addSetNext(fullPrefix + "/env-entry", "addEnvEntry", + "org.apache.tomcat.util.descriptor.web.ContextEnvironment"); digester.addRule(fullPrefix + "/env-entry", new SetOverrideRule()); - digester.addCallMethod(fullPrefix + "/env-entry/description", - "setDescription", 0); - digester.addCallMethod(fullPrefix + "/env-entry/env-entry-name", - "setName", 0); - digester.addCallMethod(fullPrefix + "/env-entry/env-entry-type", - "setType", 0); - digester.addCallMethod(fullPrefix + "/env-entry/env-entry-value", - "setValue", 0); - digester.addRule(fullPrefix + "/env-entry/mapped-name", - new MappedNameRule()); + digester.addCallMethod(fullPrefix + "/env-entry/description", "setDescription", 0); + digester.addCallMethod(fullPrefix + "/env-entry/env-entry-name", "setName", 0); + digester.addCallMethod(fullPrefix + "/env-entry/env-entry-type", "setType", 0); + digester.addCallMethod(fullPrefix + "/env-entry/env-entry-value", "setValue", 0); + digester.addRule(fullPrefix + "/env-entry/mapped-name", new MappedNameRule()); digester.addCallMethod(fullPrefix + "/env-entry/lookup-name", "setLookupName", 0); configureInjectionRules(digester, "web-app/env-entry/"); - //resource-env-ref + // resource-env-ref digester.addObjectCreate(fullPrefix + "/resource-env-ref", - "org.apache.tomcat.util.descriptor.web.ContextResourceEnvRef"); - digester.addSetNext(fullPrefix + "/resource-env-ref", - "addResourceEnvRef", - "org.apache.tomcat.util.descriptor.web.ContextResourceEnvRef"); - digester.addCallMethod(fullPrefix + "/resource-env-ref/resource-env-ref-name", - "setName", 0); - digester.addCallMethod(fullPrefix + "/resource-env-ref/resource-env-ref-type", - "setType", 0); - digester.addRule(fullPrefix + "/resource-env-ref/mapped-name", - new MappedNameRule()); + "org.apache.tomcat.util.descriptor.web.ContextResourceEnvRef"); + digester.addSetNext(fullPrefix + "/resource-env-ref", "addResourceEnvRef", + "org.apache.tomcat.util.descriptor.web.ContextResourceEnvRef"); + digester.addCallMethod(fullPrefix + "/resource-env-ref/resource-env-ref-name", "setName", 0); + digester.addCallMethod(fullPrefix + "/resource-env-ref/resource-env-ref-type", "setType", 0); + digester.addRule(fullPrefix + "/resource-env-ref/mapped-name", new MappedNameRule()); digester.addCallMethod(fullPrefix + "/resource-env-ref/lookup-name", "setLookupName", 0); configureInjectionRules(digester, "web-app/resource-env-ref/"); - //message-destination + // message-destination digester.addObjectCreate(fullPrefix + "/message-destination", - "org.apache.tomcat.util.descriptor.web.MessageDestination"); - digester.addSetNext(fullPrefix + "/message-destination", - "addMessageDestination", - "org.apache.tomcat.util.descriptor.web.MessageDestination"); - digester.addCallMethod(fullPrefix + "/message-destination/description", - "setDescription", 0); - digester.addCallMethod(fullPrefix + "/message-destination/display-name", - "setDisplayName", 0); - digester.addCallMethod(fullPrefix + "/message-destination/icon/large-icon", - "setLargeIcon", 0); - digester.addCallMethod(fullPrefix + "/message-destination/icon/small-icon", - "setSmallIcon", 0); - digester.addCallMethod(fullPrefix + "/message-destination/message-destination-name", - "setName", 0); - digester.addRule(fullPrefix + "/message-destination/mapped-name", - new MappedNameRule()); + "org.apache.tomcat.util.descriptor.web.MessageDestination"); + digester.addSetNext(fullPrefix + "/message-destination", "addMessageDestination", + "org.apache.tomcat.util.descriptor.web.MessageDestination"); + digester.addCallMethod(fullPrefix + "/message-destination/description", "setDescription", 0); + digester.addCallMethod(fullPrefix + "/message-destination/display-name", "setDisplayName", 0); + digester.addCallMethod(fullPrefix + "/message-destination/icon/large-icon", "setLargeIcon", 0); + digester.addCallMethod(fullPrefix + "/message-destination/icon/small-icon", "setSmallIcon", 0); + digester.addCallMethod(fullPrefix + "/message-destination/message-destination-name", "setName", 0); + digester.addRule(fullPrefix + "/message-destination/mapped-name", new MappedNameRule()); digester.addCallMethod(fullPrefix + "/message-destination/lookup-name", "setLookupName", 0); - //message-destination-ref + // message-destination-ref digester.addObjectCreate(fullPrefix + "/message-destination-ref", - "org.apache.tomcat.util.descriptor.web.MessageDestinationRef"); - digester.addSetNext(fullPrefix + "/message-destination-ref", - "addMessageDestinationRef", - "org.apache.tomcat.util.descriptor.web.MessageDestinationRef"); - digester.addCallMethod(fullPrefix + "/message-destination-ref/description", - "setDescription", 0); - digester.addCallMethod(fullPrefix + "/message-destination-ref/message-destination-link", - "setLink", 0); - digester.addCallMethod(fullPrefix + "/message-destination-ref/message-destination-ref-name", - "setName", 0); - digester.addCallMethod(fullPrefix + "/message-destination-ref/message-destination-type", - "setType", 0); - digester.addCallMethod(fullPrefix + "/message-destination-ref/message-destination-usage", - "setUsage", 0); - digester.addRule(fullPrefix + "/message-destination-ref/mapped-name", - new MappedNameRule()); - digester.addCallMethod(fullPrefix + "/message-destination-ref/lookup-name", - "setLookupName", 0); + "org.apache.tomcat.util.descriptor.web.MessageDestinationRef"); + digester.addSetNext(fullPrefix + "/message-destination-ref", "addMessageDestinationRef", + "org.apache.tomcat.util.descriptor.web.MessageDestinationRef"); + digester.addCallMethod(fullPrefix + "/message-destination-ref/description", "setDescription", 0); + digester.addCallMethod(fullPrefix + "/message-destination-ref/message-destination-link", "setLink", 0); + digester.addCallMethod(fullPrefix + "/message-destination-ref/message-destination-ref-name", "setName", 0); + digester.addCallMethod(fullPrefix + "/message-destination-ref/message-destination-type", "setType", 0); + digester.addCallMethod(fullPrefix + "/message-destination-ref/message-destination-usage", "setUsage", 0); + digester.addRule(fullPrefix + "/message-destination-ref/mapped-name", new MappedNameRule()); + digester.addCallMethod(fullPrefix + "/message-destination-ref/lookup-name", "setLookupName", 0); configureInjectionRules(digester, "web-app/message-destination-ref/"); - //resource-ref - digester.addObjectCreate(fullPrefix + "/resource-ref", - "org.apache.tomcat.util.descriptor.web.ContextResource"); - digester.addSetNext(fullPrefix + "/resource-ref", - "addResourceRef", - "org.apache.tomcat.util.descriptor.web.ContextResource"); - digester.addCallMethod(fullPrefix + "/resource-ref/description", - "setDescription", 0); - digester.addCallMethod(fullPrefix + "/resource-ref/res-auth", - "setAuth", 0); - digester.addCallMethod(fullPrefix + "/resource-ref/res-ref-name", - "setName", 0); - digester.addCallMethod(fullPrefix + "/resource-ref/res-sharing-scope", - "setScope", 0); - digester.addCallMethod(fullPrefix + "/resource-ref/res-type", - "setType", 0); - digester.addRule(fullPrefix + "/resource-ref/mapped-name", - new MappedNameRule()); + // resource-ref + digester.addObjectCreate(fullPrefix + "/resource-ref", "org.apache.tomcat.util.descriptor.web.ContextResource"); + digester.addSetNext(fullPrefix + "/resource-ref", "addResourceRef", + "org.apache.tomcat.util.descriptor.web.ContextResource"); + digester.addCallMethod(fullPrefix + "/resource-ref/description", "setDescription", 0); + digester.addCallMethod(fullPrefix + "/resource-ref/res-auth", "setAuth", 0); + digester.addCallMethod(fullPrefix + "/resource-ref/res-ref-name", "setName", 0); + digester.addCallMethod(fullPrefix + "/resource-ref/res-sharing-scope", "setScope", 0); + digester.addCallMethod(fullPrefix + "/resource-ref/res-type", "setType", 0); + digester.addRule(fullPrefix + "/resource-ref/mapped-name", new MappedNameRule()); digester.addCallMethod(fullPrefix + "/resource-ref/lookup-name", "setLookupName", 0); configureInjectionRules(digester, "web-app/resource-ref/"); - //service-ref - digester.addObjectCreate(fullPrefix + "/service-ref", - "org.apache.tomcat.util.descriptor.web.ContextService"); - digester.addSetNext(fullPrefix + "/service-ref", - "addServiceRef", - "org.apache.tomcat.util.descriptor.web.ContextService"); - digester.addCallMethod(fullPrefix + "/service-ref/description", - "setDescription", 0); - digester.addCallMethod(fullPrefix + "/service-ref/display-name", - "setDisplayname", 0); - digester.addCallMethod(fullPrefix + "/service-ref/icon/large-icon", - "setLargeIcon", 0); - digester.addCallMethod(fullPrefix + "/service-ref/icon/small-icon", - "setSmallIcon", 0); - digester.addCallMethod(fullPrefix + "/service-ref/service-ref-name", - "setName", 0); - digester.addCallMethod(fullPrefix + "/service-ref/service-interface", - "setInterface", 0); - digester.addCallMethod(fullPrefix + "/service-ref/service-ref-type", - "setType", 0); - digester.addCallMethod(fullPrefix + "/service-ref/wsdl-file", - "setWsdlfile", 0); - digester.addCallMethod(fullPrefix + "/service-ref/jaxrpc-mapping-file", - "setJaxrpcmappingfile", 0); + // service-ref + digester.addObjectCreate(fullPrefix + "/service-ref", "org.apache.tomcat.util.descriptor.web.ContextService"); + digester.addSetNext(fullPrefix + "/service-ref", "addServiceRef", + "org.apache.tomcat.util.descriptor.web.ContextService"); + digester.addCallMethod(fullPrefix + "/service-ref/description", "setDescription", 0); + digester.addCallMethod(fullPrefix + "/service-ref/display-name", "setDisplayname", 0); + digester.addCallMethod(fullPrefix + "/service-ref/icon/large-icon", "setLargeIcon", 0); + digester.addCallMethod(fullPrefix + "/service-ref/icon/small-icon", "setSmallIcon", 0); + digester.addCallMethod(fullPrefix + "/service-ref/service-ref-name", "setName", 0); + digester.addCallMethod(fullPrefix + "/service-ref/service-interface", "setInterface", 0); + digester.addCallMethod(fullPrefix + "/service-ref/service-ref-type", "setType", 0); + digester.addCallMethod(fullPrefix + "/service-ref/wsdl-file", "setWsdlfile", 0); + digester.addCallMethod(fullPrefix + "/service-ref/jaxrpc-mapping-file", "setJaxrpcmappingfile", 0); digester.addRule(fullPrefix + "/service-ref/service-qname", new ServiceQnameRule()); digester.addRule(fullPrefix + "/service-ref/port-component-ref", - new CallMethodMultiRule("addPortcomponent", 2, 1)); + new CallMethodMultiRule("addPortcomponent", 2, 1)); digester.addCallParam(fullPrefix + "/service-ref/port-component-ref/service-endpoint-interface", 0); digester.addRule(fullPrefix + "/service-ref/port-component-ref/port-component-link", new CallParamMultiRule(1)); digester.addObjectCreate(fullPrefix + "/service-ref/handler", - "org.apache.tomcat.util.descriptor.web.ContextHandler"); + "org.apache.tomcat.util.descriptor.web.ContextHandler"); digester.addRule(fullPrefix + "/service-ref/handler", - new SetNextRule("addHandler", - "org.apache.tomcat.util.descriptor.web.ContextHandler")); + new SetNextRule("addHandler", "org.apache.tomcat.util.descriptor.web.ContextHandler")); + + digester.addCallMethod(fullPrefix + "/service-ref/handler/handler-name", "setName", 0); + digester.addCallMethod(fullPrefix + "/service-ref/handler/handler-class", "setHandlerclass", 0); - digester.addCallMethod(fullPrefix + "/service-ref/handler/handler-name", - "setName", 0); - digester.addCallMethod(fullPrefix + "/service-ref/handler/handler-class", - "setHandlerclass", 0); - - digester.addCallMethod(fullPrefix + "/service-ref/handler/init-param", - "setProperty", 2); - digester.addCallParam(fullPrefix + "/service-ref/handler/init-param/param-name", - 0); - digester.addCallParam(fullPrefix + "/service-ref/handler/init-param/param-value", - 1); + digester.addCallMethod(fullPrefix + "/service-ref/handler/init-param", "setProperty", 2); + digester.addCallParam(fullPrefix + "/service-ref/handler/init-param/param-name", 0); + digester.addCallParam(fullPrefix + "/service-ref/handler/init-param/param-value", 1); digester.addRule(fullPrefix + "/service-ref/handler/soap-header", new SoapHeaderRule()); - digester.addCallMethod(fullPrefix + "/service-ref/handler/soap-role", - "addSoapRole", 0); - digester.addCallMethod(fullPrefix + "/service-ref/handler/port-name", - "addPortName", 0); - digester.addRule(fullPrefix + "/service-ref/mapped-name", - new MappedNameRule()); + digester.addCallMethod(fullPrefix + "/service-ref/handler/soap-role", "addSoapRole", 0); + digester.addCallMethod(fullPrefix + "/service-ref/handler/port-name", "addPortName", 0); + digester.addRule(fullPrefix + "/service-ref/mapped-name", new MappedNameRule()); digester.addCallMethod(fullPrefix + "/service-ref/lookup-name", "setLookupName", 0); configureInjectionRules(digester, "web-app/service-ref/"); } @@ -701,7 +520,7 @@ /** * Reset counter used for validating the web.xml file. */ - public void recycle(){ + public void recycle() { jspConfig.isJspConfigSet = false; sessionConfig.isSessionConfigSet = false; loginConfig.isLoginConfigSet = false; @@ -716,21 +535,19 @@ /** - * Rule to check that the login-config is occurring - * only 1 time within the web.xml + * Rule to check that the login-config is occurring only 1 time within the web.xml */ final class SetLoginConfig extends Rule { boolean isLoginConfigSet = false; + SetLoginConfig() { // NO-OP } @Override - public void begin(String namespace, String name, Attributes attributes) - throws Exception { - if (isLoginConfigSet){ - throw new IllegalArgumentException( - " element is limited to 1 occurrence"); + public void begin(String namespace, String name, Attributes attributes) throws Exception { + if (isLoginConfigSet) { + throw new IllegalArgumentException(" element is limited to 1 occurrence"); } isLoginConfigSet = true; } @@ -739,21 +556,19 @@ /** - * Rule to check that the jsp-config is occurring - * only 1 time within the web.xml + * Rule to check that the jsp-config is occurring only 1 time within the web.xml */ final class SetJspConfig extends Rule { boolean isJspConfigSet = false; + SetJspConfig() { // NO-OP } @Override - public void begin(String namespace, String name, Attributes attributes) - throws Exception { - if (isJspConfigSet){ - throw new IllegalArgumentException( - " element is limited to 1 occurrence"); + public void begin(String namespace, String name, Attributes attributes) throws Exception { + if (isJspConfigSet) { + throw new IllegalArgumentException(" element is limited to 1 occurrence"); } isJspConfigSet = true; } @@ -762,21 +577,19 @@ /** - * Rule to check that the session-config is occurring - * only 1 time within the web.xml + * Rule to check that the session-config is occurring only 1 time within the web.xml */ final class SetSessionConfig extends Rule { boolean isSessionConfigSet = false; + SetSessionConfig() { // NO-OP } @Override - public void begin(String namespace, String name, Attributes attributes) - throws Exception { - if (isSessionConfigSet){ - throw new IllegalArgumentException( - " element is limited to 1 occurrence"); + public void begin(String namespace, String name, Attributes attributes) throws Exception { + if (isSessionConfigSet) { + throw new IllegalArgumentException(" element is limited to 1 occurrence"); } isSessionConfigSet = true; } @@ -784,8 +597,7 @@ } /** - * A Rule that calls the setAuthConstraint(true) method of - * the top item on the stack, which must be of type + * A Rule that calls the setAuthConstraint(true) method of the top item on the stack, which must be of type * org.apache.tomcat.util.descriptor.web.SecurityConstraint. */ @@ -796,14 +608,11 @@ } @Override - public void begin(String namespace, String name, Attributes attributes) - throws Exception { - SecurityConstraint securityConstraint = - (SecurityConstraint) digester.peek(); + public void begin(String namespace, String name, Attributes attributes) throws Exception { + SecurityConstraint securityConstraint = (SecurityConstraint) digester.peek(); securityConstraint.setAuthConstraint(true); if (digester.getLogger().isTraceEnabled()) { - digester.getLogger() - .trace("Calling SecurityConstraint.setAuthConstraint(true)"); + digester.getLogger().trace("Calling SecurityConstraint.setAuthConstraint(true)"); } StringBuilder code = digester.getGeneratedCode(); @@ -818,8 +627,8 @@ /** - * Class that calls setDistributable(true) for the top object - * on the stack, which must be a {@link WebXml} instance. + * Class that calls setDistributable(true) for the top object on the stack, which must be a {@link WebXml} + * instance. */ final class SetDistributableRule extends Rule { @@ -828,13 +637,11 @@ } @Override - public void begin(String namespace, String name, Attributes attributes) - throws Exception { + public void begin(String namespace, String name, Attributes attributes) throws Exception { WebXml webXml = (WebXml) digester.peek(); webXml.setDistributable(true); if (digester.getLogger().isTraceEnabled()) { - digester.getLogger().trace - (webXml.getClass().getName() + ".setDistributable(true)"); + digester.getLogger().trace(webXml.getClass().getName() + ".setDistributable(true)"); } StringBuilder code = digester.getGeneratedCode(); @@ -848,8 +655,8 @@ /** - * Class that calls setDenyUncoveredHttpMethods(true) for the top - * object on the stack, which must be a {@link WebXml} instance. + * Class that calls setDenyUncoveredHttpMethods(true) for the top object on the stack, which must be a + * {@link WebXml} instance. */ final class SetDenyUncoveredHttpMethodsRule extends Rule { @@ -858,13 +665,11 @@ } @Override - public void begin(String namespace, String name, Attributes attributes) - throws Exception { + public void begin(String namespace, String name, Attributes attributes) throws Exception { WebXml webXml = (WebXml) digester.peek(); webXml.setDenyUncoveredHttpMethods(true); if (digester.getLogger().isTraceEnabled()) { - digester.getLogger().trace(webXml.getClass().getName() + - ".setDenyUncoveredHttpMethods(true)"); + digester.getLogger().trace(webXml.getClass().getName() + ".setDenyUncoveredHttpMethods(true)"); } StringBuilder code = digester.getGeneratedCode(); @@ -878,8 +683,8 @@ /** - * Class that calls a property setter for the top object on the stack, - * passing the public ID of the entity we are currently processing. + * Class that calls a property setter for the top object on the stack, passing the public ID of the entity we are + * currently processing. */ final class SetPublicIdRule extends Rule { @@ -891,8 +696,7 @@ private final String method; @Override - public void begin(String namespace, String name, Attributes attributes) - throws Exception { + public void begin(String namespace, String name, Attributes attributes) throws Exception { Object top = digester.peek(); Class[] paramClasses = new Class[1]; @@ -908,10 +712,9 @@ return; } - m.invoke(top, (Object [])paramValues); + m.invoke(top, (Object[]) paramValues); if (digester.getLogger().isTraceEnabled()) { - digester.getLogger().trace(top.getClass().getName() + "." - + method + "(" + paramValues[0] + ")"); + digester.getLogger().trace(top.getClass().getName() + "." + method + "(" + paramValues[0] + ")"); } StringBuilder code = digester.getGeneratedCode(); @@ -927,8 +730,7 @@ /** - * A Rule that calls the factory method on the specified Context to - * create the object that is to be added to the stack. + * A Rule that calls the factory method on the specified Context to create the object that is to be added to the stack. */ final class ServletDefCreateRule extends Rule { @@ -938,8 +740,7 @@ } @Override - public void begin(String namespace, String name, Attributes attributes) - throws Exception { + public void begin(String namespace, String name, Attributes attributes) throws Exception { ServletDef servletDef = new ServletDef(); digester.push(servletDef); if (digester.getLogger().isTraceEnabled()) { @@ -949,14 +750,14 @@ StringBuilder code = digester.getGeneratedCode(); if (code != null) { code.append(System.lineSeparator()); - code.append(ServletDef.class.getName()).append(' ').append(digester.toVariableName(servletDef)).append(" = new "); + code.append(ServletDef.class.getName()).append(' ').append(digester.toVariableName(servletDef)) + .append(" = new "); code.append(ServletDef.class.getName()).append("();").append(System.lineSeparator()); } } @Override - public void end(String namespace, String name) - throws Exception { + public void end(String namespace, String name) throws Exception { ServletDef servletDef = (ServletDef) digester.pop(); if (digester.getLogger().isTraceEnabled()) { digester.getLogger().trace("pop " + servletDef.getClass().getName()); @@ -972,8 +773,7 @@ /** - * A Rule that can be used to call multiple times a method as many times as needed - * (used for addServletMapping). + * A Rule that can be used to call multiple times a method as many times as needed (used for addServletMapping). */ final class CallParamMultiRule extends CallParamRule { @@ -1000,8 +800,7 @@ /** - * A Rule that can be used to call multiple times a method as many times as needed - * (used for addServletMapping). + * A Rule that can be used to call multiple times a method as many times as needed (used for addServletMapping). */ final class CallMethodMultiRule extends CallMethodRule { @@ -1015,11 +814,9 @@ /** * Process the end of this element. * - * @param namespace the namespace URI of the matching element, or an - * empty string if the parser is not namespace aware or the element has - * no namespace - * @param name the local name if the parser is namespace aware, or just - * the element name otherwise + * @param namespace the namespace URI of the matching element, or an empty string if the parser is not namespace + * aware or the element has no namespace + * @param name the local name if the parser is namespace aware, or just the element name otherwise */ @Override public void end(String namespace, String name) throws Exception { @@ -1043,10 +840,9 @@ if (i != multiParamIndex) { // convert nulls and convert stringy parameters // for non-stringy param types - if(parameters[i] == null || (parameters[i] instanceof String - && !String.class.isAssignableFrom(paramTypes[i]))) { - paramValues[i] = - IntrospectionUtils.convert((String) parameters[i], paramTypes[i]); + if (parameters[i] == null || + (parameters[i] instanceof String && !String.class.isAssignableFrom(paramTypes[i]))) { + paramValues[i] = IntrospectionUtils.convert((String) parameters[i], paramTypes[i]); } else { paramValues[i] = parameters[i]; } @@ -1062,28 +858,25 @@ } if (target == null) { - String sb = "[CallMethodRule]{" + "} Call target is null (" + "targetOffset=" - + targetOffset + ",stackdepth=" + digester.getCount() + ')'; + String sb = "[CallMethodRule]{" + "} Call target is null (" + "targetOffset=" + targetOffset + + ",stackdepth=" + digester.getCount() + ')'; throw new org.xml.sax.SAXException(sb); } if (multiParams == null) { paramValues[multiParamIndex] = null; - IntrospectionUtils.callMethodN(target, methodName, paramValues, - paramTypes); + IntrospectionUtils.callMethodN(target, methodName, paramValues, paramTypes); return; } for (Object param : multiParams) { - if (param == null || (param instanceof String - && !String.class.isAssignableFrom(paramTypes[multiParamIndex]))) { - paramValues[multiParamIndex] = - IntrospectionUtils.convert((String) param, paramTypes[multiParamIndex]); + if (param == null || + (param instanceof String && !String.class.isAssignableFrom(paramTypes[multiParamIndex]))) { + paramValues[multiParamIndex] = IntrospectionUtils.convert((String) param, paramTypes[multiParamIndex]); } else { paramValues[multiParamIndex] = param; } - IntrospectionUtils.callMethodN(target, methodName, paramValues, - paramTypes); + IntrospectionUtils.callMethodN(target, methodName, paramValues, paramTypes); StringBuilder code = digester.getGeneratedCode(); if (code != null) { @@ -1109,10 +902,8 @@ } - /** * A Rule that check if the annotations have to be loaded. - * */ final class IgnoreAnnotationsRule extends Rule { @@ -1122,8 +913,7 @@ } @Override - public void begin(String namespace, String name, Attributes attributes) - throws Exception { + public void begin(String namespace, String name, Attributes attributes) throws Exception { WebXml webXml = (WebXml) digester.peek(digester.getCount() - 1); String value = attributes.getValue("metadata-complete"); if ("true".equals(value)) { @@ -1134,9 +924,8 @@ value = null; } if (digester.getLogger().isTraceEnabled()) { - digester.getLogger().trace - (webXml.getClass().getName() + ".setMetadataComplete( " + - webXml.isMetadataComplete() + ")"); + digester.getLogger() + .trace(webXml.getClass().getName() + ".setMetadataComplete( " + webXml.isMetadataComplete() + ")"); } StringBuilder code = digester.getGeneratedCode(); @@ -1152,7 +941,6 @@ /** * A Rule that records the spec version of the web.xml being parsed - * */ final class VersionRule extends Rule { @@ -1162,15 +950,12 @@ } @Override - public void begin(String namespace, String name, Attributes attributes) - throws Exception { + public void begin(String namespace, String name, Attributes attributes) throws Exception { WebXml webXml = (WebXml) digester.peek(digester.getCount() - 1); webXml.setVersion(attributes.getValue("version")); if (digester.getLogger().isTraceEnabled()) { - digester.getLogger().trace - (webXml.getClass().getName() + ".setVersion( " + - webXml.getVersion() + ")"); + digester.getLogger().trace(webXml.getClass().getName() + ".setVersion( " + webXml.getVersion() + ")"); } StringBuilder code = digester.getGeneratedCode(); @@ -1197,18 +982,15 @@ } @Override - public void begin(String namespace, String name, Attributes attributes) - throws Exception { - if (isNameSet){ - throw new IllegalArgumentException(WebRuleSet.sm.getString( - "webRuleSet.nameCount")); + public void begin(String namespace, String name, Attributes attributes) throws Exception { + if (isNameSet) { + throw new IllegalArgumentException(WebRuleSet.sm.getString("webRuleSet.nameCount")); } isNameSet = true; } @Override - public void body(String namespace, String name, String text) - throws Exception { + public void body(String namespace, String name, String text) throws Exception { ((WebXml) digester.peek()).setName(text); StringBuilder code = digester.getGeneratedCode(); @@ -1223,8 +1005,8 @@ /** - * A rule that logs a warning if absolute ordering is configured for a fragment - * and fails if multiple absolute orders are configured. + * A rule that logs a warning if absolute ordering is configured for a fragment and fails if multiple absolute orders + * are configured. */ final class AbsoluteOrderingRule extends Rule { @@ -1236,22 +1018,18 @@ } @Override - public void begin(String namespace, String name, Attributes attributes) - throws Exception { + public void begin(String namespace, String name, Attributes attributes) throws Exception { if (fragment) { - digester.getLogger().warn( - WebRuleSet.sm.getString("webRuleSet.absoluteOrdering")); + digester.getLogger().warn(WebRuleSet.sm.getString("webRuleSet.absoluteOrdering")); } if (isAbsoluteOrderingSet) { - throw new IllegalArgumentException(WebRuleSet.sm.getString( - "webRuleSet.absoluteOrderingCount")); + throw new IllegalArgumentException(WebRuleSet.sm.getString("webRuleSet.absoluteOrderingCount")); } else { isAbsoluteOrderingSet = true; WebXml webXml = (WebXml) digester.peek(); webXml.createAbsoluteOrdering(); if (digester.getLogger().isTraceEnabled()) { - digester.getLogger().trace( - webXml.getClass().getName() + ".setAbsoluteOrdering()"); + digester.getLogger().trace(webXml.getClass().getName() + ".setAbsoluteOrdering()"); } StringBuilder code = digester.getGeneratedCode(); @@ -1277,15 +1055,12 @@ } @Override - public void begin(String namespace, String name, Attributes attributes) - throws Exception { + public void begin(String namespace, String name, Attributes attributes) throws Exception { if (!fragment) { - digester.getLogger().warn( - WebRuleSet.sm.getString("webRuleSet.relativeOrdering")); + digester.getLogger().warn(WebRuleSet.sm.getString("webRuleSet.relativeOrdering")); } if (isRelativeOrderingSet) { - throw new IllegalArgumentException(WebRuleSet.sm.getString( - "webRuleSet.relativeOrderingCount")); + throw new IllegalArgumentException(WebRuleSet.sm.getString("webRuleSet.relativeOrderingCount")); } else { isRelativeOrderingSet = true; } @@ -1294,7 +1069,6 @@ /** * A Rule that sets soap headers on the ContextHandler. - * */ final class SoapHeaderRule extends Rule { @@ -1305,23 +1079,20 @@ /** * Process the body text of this element. * - * @param namespace the namespace URI of the matching element, or an - * empty string if the parser is not namespace aware or the element has - * no namespace - * @param name the local name if the parser is namespace aware, or just - * the element name otherwise - * @param text The body text of this element + * @param namespace the namespace URI of the matching element, or an empty string if the parser is not namespace + * aware or the element has no namespace + * @param name the local name if the parser is namespace aware, or just the element name otherwise + * @param text The body text of this element */ @Override - public void body(String namespace, String name, String text) - throws Exception { + public void body(String namespace, String name, String text) throws Exception { String namespaceuri = null; String localpart = text; int colon = text.indexOf(':'); if (colon >= 0) { - String prefix = text.substring(0,colon); + String prefix = text.substring(0, colon); namespaceuri = digester.findNamespaceURI(prefix); - localpart = text.substring(colon+1); + localpart = text.substring(colon + 1); } ContextHandler contextHandler = (ContextHandler) digester.peek(); contextHandler.addSoapHeaders(localpart, namespaceuri); @@ -1338,7 +1109,6 @@ /** * A Rule that sets service qname on the ContextService. - * */ final class ServiceQnameRule extends Rule { @@ -1349,23 +1119,20 @@ /** * Process the body text of this element. * - * @param namespace the namespace URI of the matching element, or an - * empty string if the parser is not namespace aware or the element has - * no namespace - * @param name the local name if the parser is namespace aware, or just - * the element name otherwise - * @param text The body text of this element + * @param namespace the namespace URI of the matching element, or an empty string if the parser is not namespace + * aware or the element has no namespace + * @param name the local name if the parser is namespace aware, or just the element name otherwise + * @param text The body text of this element */ @Override - public void body(String namespace, String name, String text) - throws Exception { + public void body(String namespace, String name, String text) throws Exception { String namespaceuri = null; String localpart = text; int colon = text.indexOf(':'); if (colon >= 0) { - String prefix = text.substring(0,colon); + String prefix = text.substring(0, colon); namespaceuri = digester.findNamespaceURI(prefix); - localpart = text.substring(colon+1); + localpart = text.substring(colon + 1); } ContextService contextService = (ContextService) digester.peek(); contextService.setServiceqnameLocalpart(localpart); @@ -1397,15 +1164,13 @@ } @Override - public void begin(String namespace, String name, Attributes attributes) - throws Exception { + public void begin(String namespace, String name, Attributes attributes) throws Exception { WebXml webXml = (WebXml) digester.peek(digester.getCount() - 1); // If we have a public ID, this is not a 2.4 or later webapp boolean havePublicId = (webXml.getPublicId() != null); // havePublicId and isServlet24OrLater should be mutually exclusive if (havePublicId == isServlet24OrLater) { - throw new IllegalArgumentException( - "taglib definition not consistent with specification version"); + throw new IllegalArgumentException("taglib definition not consistent with specification version"); } } } @@ -1422,16 +1187,13 @@ /** * Process the body text of this element. * - * @param namespace the namespace URI of the matching element, or an - * empty string if the parser is not namespace aware or the element has - * no namespace - * @param name the local name if the parser is namespace aware, or just - * the element name otherwise - * @param text The body text of this element + * @param namespace the namespace URI of the matching element, or an empty string if the parser is not namespace + * aware or the element has no namespace + * @param name the local name if the parser is namespace aware, or just the element name otherwise + * @param text The body text of this element */ @Override - public void body(String namespace, String name, String text) - throws Exception { + public void body(String namespace, String name, String text) throws Exception { ResourceBase resourceBase = (ResourceBase) digester.peek(); resourceBase.setProperty("mappedName", text.trim()); @@ -1446,15 +1208,13 @@ } /** - * A rule that fails if more than one post construct or pre destroy methods - * are configured per class. + * A rule that fails if more than one post construct or pre destroy methods are configured per class. */ final class LifecycleCallbackRule extends CallMethodRule { private final boolean postConstruct; - LifecycleCallbackRule(String methodName, int paramCount, - boolean postConstruct) { + LifecycleCallbackRule(String methodName, int paramCount, boolean postConstruct) { super(methodName, paramCount); this.postConstruct = postConstruct; } @@ -1466,13 +1226,13 @@ WebXml webXml = (WebXml) digester.peek(); if (postConstruct) { if (webXml.getPostConstructMethods().containsKey(params[0])) { - throw new IllegalArgumentException(WebRuleSet.sm.getString( - "webRuleSet.postconstruct.duplicate", params[0])); + throw new IllegalArgumentException( + WebRuleSet.sm.getString("webRuleSet.postconstruct.duplicate", params[0])); } } else { if (webXml.getPreDestroyMethods().containsKey(params[0])) { - throw new IllegalArgumentException(WebRuleSet.sm.getString( - "webRuleSet.predestroy.duplicate", params[0])); + throw new IllegalArgumentException( + WebRuleSet.sm.getString("webRuleSet.predestroy.duplicate", params[0])); } } } diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/descriptor/web/WebXml.java tomcat10-10.1.52/java/org/apache/tomcat/util/descriptor/web/WebXml.java --- tomcat10-10.1.40/java/org/apache/tomcat/util/descriptor/web/WebXml.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/descriptor/web/WebXml.java 2026-01-23 19:33:36.000000000 +0000 @@ -51,103 +51,112 @@ import org.apache.tomcat.util.security.Escape; /** - * Representation of common elements of web.xml and web-fragment.xml. Provides - * a repository for parsed data before the elements are merged. - * Validation is spread between multiple classes: - * The digester checks for structural correctness (e.g. single login-config) - * This class checks for invalid duplicates (e.g. filter/servlet names) - * StandardContext will check validity of values (e.g. URL formats etc) + * Representation of common elements of web.xml and web-fragment.xml. Provides a repository for parsed data before the + * elements are merged. Validation is spread between multiple classes: The digester checks for structural correctness + * (e.g. single login-config) This class checks for invalid duplicates (e.g. filter/servlet names) StandardContext will + * check validity of values (e.g. URL formats etc) */ public class WebXml extends XmlEncodingBase implements DocumentProperties.Charset { - protected static final String ORDER_OTHERS = - "org.apache.catalina.order.others"; + protected static final String ORDER_OTHERS = "org.apache.catalina.order.others"; - private static final StringManager sm = - StringManager.getManager(Constants.PACKAGE_NAME); + private static final StringManager sm = StringManager.getManager(Constants.PACKAGE_NAME); private final Log log = LogFactory.getLog(WebXml.class); // must not be static /** - * Global defaults are overridable but Servlets and Servlet mappings need to - * be unique. Duplicates normally trigger an error. This flag indicates if - * newly added Servlet elements are marked as overridable. + * Global defaults are overridable but Servlets and Servlet mappings need to be unique. Duplicates normally trigger + * an error. This flag indicates if newly added Servlet elements are marked as overridable. */ private boolean overridable = false; + public boolean isOverridable() { return overridable; } + public void setOverridable(boolean overridable) { this.overridable = overridable; } /* - * Ideally, fragment names will be unique. If they are not, Tomcat needs - * to know as the action that the specification requires (see 8.2.2 1.e and - * 2.c) varies depending on the ordering method used. + * Ideally, fragment names will be unique. If they are not, Tomcat needs to know as the action that the + * specification requires (see 8.2.2 1.e and 2.c) varies depending on the ordering method used. */ private final List duplicates = new ArrayList<>(); + public boolean isDuplicated() { return !duplicates.isEmpty(); } + public void addDuplicate(String duplicate) { this.duplicates.add(duplicate); } + public List getDuplicates() { return new ArrayList<>(this.duplicates); } /** - * web.xml only elements - * Absolute Ordering + * web.xml only elements Absolute Ordering */ private Set absoluteOrdering = null; + public void createAbsoluteOrdering() { if (absoluteOrdering == null) { absoluteOrdering = new LinkedHashSet<>(); } } + public void addAbsoluteOrdering(String fragmentName) { createAbsoluteOrdering(); absoluteOrdering.add(fragmentName); } + public void addAbsoluteOrderingOthers() { createAbsoluteOrdering(); absoluteOrdering.add(ORDER_OTHERS); } + public Set getAbsoluteOrdering() { return absoluteOrdering; } /** - * web-fragment.xml only elements - * Relative ordering + * web-fragment.xml only elements Relative ordering */ private final Set after = new LinkedHashSet<>(); + public void addAfterOrdering(String fragmentName) { after.add(fragmentName); } + public void addAfterOrderingOthers() { if (before.contains(ORDER_OTHERS)) { - throw new IllegalArgumentException(sm.getString( - "webXml.multipleOther")); + throw new IllegalArgumentException(sm.getString("webXml.multipleOther")); } after.add(ORDER_OTHERS); } - public Set getAfterOrdering() { return after; } + + public Set getAfterOrdering() { + return after; + } private final Set before = new LinkedHashSet<>(); + public void addBeforeOrdering(String fragmentName) { before.add(fragmentName); } + public void addBeforeOrderingOthers() { if (after.contains(ORDER_OTHERS)) { - throw new IllegalArgumentException(sm.getString( - "webXml.multipleOther")); + throw new IllegalArgumentException(sm.getString("webXml.multipleOther")); } before.add(ORDER_OTHERS); } - public Set getBeforeOrdering() { return before; } + + public Set getBeforeOrdering() { + return before; + } // Common elements and attributes // Required attribute of web-app element @@ -158,9 +167,11 @@ sb.append(minorVersion); return sb.toString(); } + /** * Set the version for this web.xml file - * @param version Values of null will be ignored + * + * @param version Values of null will be ignored */ public void setVersion(String version) { if (version == null) { @@ -201,10 +212,13 @@ } - // Optional publicId attribute private String publicId = null; - public String getPublicId() { return publicId; } + + public String getPublicId() { + return publicId; + } + public void setPublicId(String publicId) { // Update major and minor version if (publicId == null) { @@ -229,13 +243,22 @@ // Optional metadata-complete attribute private boolean metadataComplete = false; - public boolean isMetadataComplete() { return metadataComplete; } + + public boolean isMetadataComplete() { + return metadataComplete; + } + public void setMetadataComplete(boolean metadataComplete) { - this.metadataComplete = metadataComplete; } + this.metadataComplete = metadataComplete; + } // Optional name element private String name = null; - public String getName() { return name; } + + public String getName() { + return name; + } + public void setName(String name) { if (ORDER_OTHERS.equalsIgnoreCase(name)) { // This is unusual. This name will be ignored. Log the fact. @@ -248,8 +271,14 @@ // Derived major and minor version attributes private int majorVersion = 6; private int minorVersion = 0; - public int getMajorVersion() { return majorVersion; } - public int getMinorVersion() { return minorVersion; } + + public int getMajorVersion() { + return majorVersion; + } + + public int getMinorVersion() { + return minorVersion; + } // web-app elements // TODO: Ignored elements: @@ -258,23 +287,33 @@ // display-name - TODO should support multiple with language private String displayName = null; - public String getDisplayName() { return displayName; } + + public String getDisplayName() { + return displayName; + } + public void setDisplayName(String displayName) { this.displayName = displayName; } // distributable private boolean distributable = false; - public boolean isDistributable() { return distributable; } + + public boolean isDistributable() { + return distributable; + } + public void setDistributable(boolean distributable) { this.distributable = distributable; } // deny-uncovered-http-methods private boolean denyUncoveredHttpMethods = false; + public boolean getDenyUncoveredHttpMethods() { return denyUncoveredHttpMethods; } + public void setDenyUncoveredHttpMethods(boolean denyUncoveredHttpMethods) { this.denyUncoveredHttpMethods = denyUncoveredHttpMethods; } @@ -282,10 +321,14 @@ // context-param // TODO: description (multiple with language) is ignored private final Map contextParams = new HashMap<>(); + public void addContextParam(String param, String value) { contextParams.put(param, value); } - public Map getContextParams() { return contextParams; } + + public Map getContextParams() { + return contextParams; + } // filter // TODO: Should support multiple description elements with language @@ -293,36 +336,46 @@ // TODO: Should support multiple icon elements // TODO: Description for init-param is ignored private final Map filters = new LinkedHashMap<>(); + public void addFilter(FilterDef filter) { if (filters.containsKey(filter.getFilterName())) { // Filter names must be unique within a web(-fragment).xml - throw new IllegalArgumentException( - sm.getString("webXml.duplicateFilter", - filter.getFilterName())); + throw new IllegalArgumentException(sm.getString("webXml.duplicateFilter", filter.getFilterName())); } filters.put(filter.getFilterName(), filter); } - public Map getFilters() { return filters; } + + public Map getFilters() { + return filters; + } // filter-mapping private final Set filterMaps = new LinkedHashSet<>(); private final Set filterMappingNames = new HashSet<>(); + public void addFilterMapping(FilterMap filterMap) { filterMap.setCharset(getCharset()); filterMaps.add(filterMap); filterMappingNames.add(filterMap.getFilterName()); } - public Set getFilterMappings() { return filterMaps; } + + public Set getFilterMappings() { + return filterMaps; + } // listener // TODO: description (multiple with language) is ignored // TODO: display-name (multiple with language) is ignored // TODO: icon (multiple) is ignored private final Set listeners = new LinkedHashSet<>(); + public void addListener(String className) { listeners.add(className); } - public Set getListeners() { return listeners; } + + public Set getListeners() { + return listeners; + } // servlet // TODO: description (multiple with language) is ignored @@ -331,65 +384,83 @@ // TODO: init-param/description (multiple with language) is ignored // TODO: security-role-ref/description (multiple with language) is ignored private final Map servlets = new HashMap<>(); + public void addServlet(ServletDef servletDef) { servlets.put(servletDef.getServletName(), servletDef); if (overridable) { servletDef.setOverridable(true); } } - public Map getServlets() { return servlets; } + + public Map getServlets() { + return servlets; + } // servlet-mapping // Note: URLPatterns from web.xml may be URL encoded - // (https://svn.apache.org/r285186) + // (https://svn.apache.org/r285186) private final Map servletMappings = new HashMap<>(); private final Set servletMappingNames = new HashSet<>(); + public void addServletMapping(String urlPattern, String servletName) { addServletMappingDecoded(UDecoder.URLDecode(urlPattern, getCharset()), servletName); } + public void addServletMappingDecoded(String urlPattern, String servletName) { String oldServletName = servletMappings.put(urlPattern, servletName); if (oldServletName != null) { // Duplicate mapping. As per clarification from the Servlet EG, // deployment should fail. - throw new IllegalArgumentException(sm.getString( - "webXml.duplicateServletMapping", oldServletName, - servletName, urlPattern)); + throw new IllegalArgumentException( + sm.getString("webXml.duplicateServletMapping", oldServletName, servletName, urlPattern)); } servletMappingNames.add(servletName); } - public Map getServletMappings() { return servletMappings; } + + public Map getServletMappings() { + return servletMappings; + } // session-config // Digester will check there is only one of these private SessionConfig sessionConfig = new SessionConfig(); + public void setSessionConfig(SessionConfig sessionConfig) { this.sessionConfig = sessionConfig; } - public SessionConfig getSessionConfig() { return sessionConfig; } + + public SessionConfig getSessionConfig() { + return sessionConfig; + } // mime-mapping private final Map mimeMappings = new HashMap<>(); + public void addMimeMapping(String extension, String mimeType) { mimeMappings.put(extension, mimeType); } - public Map getMimeMappings() { return mimeMappings; } + + public Map getMimeMappings() { + return mimeMappings; + } // welcome-file-list merge control private boolean replaceWelcomeFiles = false; private boolean alwaysAddWelcomeFiles = true; + /** - * When merging/parsing web.xml files into this web.xml should the current - * set be completely replaced? - * @param replaceWelcomeFiles true to replace welcome files - * rather than add to the list + * When merging/parsing web.xml files into this web.xml should the current set be completely replaced? + * + * @param replaceWelcomeFiles true to replace welcome files rather than add to the list */ public void setReplaceWelcomeFiles(boolean replaceWelcomeFiles) { this.replaceWelcomeFiles = replaceWelcomeFiles; } + /** - * When merging from this web.xml, should the welcome files be added to the - * target web.xml even if it already contains welcome file definitions. + * When merging from this web.xml, should the welcome files be added to the target web.xml even if it already + * contains welcome file definitions. + * * @param alwaysAddWelcomeFiles true to add welcome files */ public void setAlwaysAddWelcomeFiles(boolean alwaysAddWelcomeFiles) { @@ -398,6 +469,7 @@ // welcome-file-list private final Set welcomeFiles = new LinkedHashSet<>(); + public void addWelcomeFile(String welcomeFile) { if (replaceWelcomeFiles) { welcomeFiles.clear(); @@ -405,35 +477,47 @@ } welcomeFiles.add(welcomeFile); } - public Set getWelcomeFiles() { return welcomeFiles; } + + public Set getWelcomeFiles() { + return welcomeFiles; + } // error-page private final Map errorPages = new HashMap<>(); + public void addErrorPage(ErrorPage errorPage) { errorPage.setCharset(getCharset()); errorPages.put(errorPage.getName(), errorPage); } - public Map getErrorPages() { return errorPages; } + + public Map getErrorPages() { + return errorPages; + } // Digester will check there is only one jsp-config // jsp-config/taglib or taglib (2.3 and earlier) private final Map taglibs = new HashMap<>(); + public void addTaglib(String uri, String location) { if (taglibs.containsKey(uri)) { // Taglib URIs must be unique within a web(-fragment).xml - throw new IllegalArgumentException( - sm.getString("webXml.duplicateTaglibUri", uri)); + throw new IllegalArgumentException(sm.getString("webXml.duplicateTaglibUri", uri)); } taglibs.put(uri, location); } - public Map getTaglibs() { return taglibs; } + + public Map getTaglibs() { + return taglibs; + } // jsp-config/jsp-property-group private final Set jspPropertyGroups = new LinkedHashSet<>(); + public void addJspPropertyGroup(JspPropertyGroup propertyGroup) { propertyGroup.setCharset(getCharset()); jspPropertyGroups.add(propertyGroup); } + public Set getJspPropertyGroups() { return jspPropertyGroups; } @@ -442,10 +526,12 @@ // TODO: Should support multiple display-name elements with language // TODO: Should support multiple description elements with language private final Set securityConstraints = new HashSet<>(); + public void addSecurityConstraint(SecurityConstraint securityConstraint) { securityConstraint.setCharset(getCharset()); securityConstraints.add(securityConstraint); } + public Set getSecurityConstraints() { return securityConstraints; } @@ -453,48 +539,64 @@ // login-config // Digester will check there is only one of these private LoginConfig loginConfig = null; + public void setLoginConfig(LoginConfig loginConfig) { loginConfig.setCharset(getCharset()); this.loginConfig = loginConfig; } - public LoginConfig getLoginConfig() { return loginConfig; } + + public LoginConfig getLoginConfig() { + return loginConfig; + } // security-role // TODO: description (multiple with language) is ignored private final Set securityRoles = new HashSet<>(); + public void addSecurityRole(String securityRole) { securityRoles.add(securityRole); } - public Set getSecurityRoles() { return securityRoles; } + + public Set getSecurityRoles() { + return securityRoles; + } // env-entry // TODO: Should support multiple description elements with language private final Map envEntries = new HashMap<>(); + public void addEnvEntry(ContextEnvironment envEntry) { if (envEntries.containsKey(envEntry.getName())) { // env-entry names must be unique within a web(-fragment).xml - throw new IllegalArgumentException( - sm.getString("webXml.duplicateEnvEntry", - envEntry.getName())); + throw new IllegalArgumentException(sm.getString("webXml.duplicateEnvEntry", envEntry.getName())); } - envEntries.put(envEntry.getName(),envEntry); + envEntries.put(envEntry.getName(), envEntry); + } + + public Map getEnvEntries() { + return envEntries; } - public Map getEnvEntries() { return envEntries; } // ejb-ref // TODO: Should support multiple description elements with language private final Map ejbRefs = new HashMap<>(); + public void addEjbRef(ContextEjb ejbRef) { - ejbRefs.put(ejbRef.getName(),ejbRef); + ejbRefs.put(ejbRef.getName(), ejbRef); + } + + public Map getEjbRefs() { + return ejbRefs; } - public Map getEjbRefs() { return ejbRefs; } // ejb-local-ref // TODO: Should support multiple description elements with language private final Map ejbLocalRefs = new HashMap<>(); + public void addEjbLocalRef(ContextLocalEjb ejbLocalRef) { - ejbLocalRefs.put(ejbLocalRef.getName(),ejbLocalRef); + ejbLocalRefs.put(ejbLocalRef.getName(), ejbLocalRef); } + public Map getEjbLocalRefs() { return ejbLocalRefs; } @@ -504,23 +606,27 @@ // TODO: Should support multiple display-names elements with language // TODO: Should support multiple icon elements ??? private final Map serviceRefs = new HashMap<>(); + public void addServiceRef(ContextService serviceRef) { serviceRefs.put(serviceRef.getName(), serviceRef); } - public Map getServiceRefs() { return serviceRefs; } + + public Map getServiceRefs() { + return serviceRefs; + } // resource-ref // TODO: Should support multiple description elements with language private final Map resourceRefs = new HashMap<>(); + public void addResourceRef(ContextResource resourceRef) { if (resourceRefs.containsKey(resourceRef.getName())) { // resource-ref names must be unique within a web(-fragment).xml - throw new IllegalArgumentException( - sm.getString("webXml.duplicateResourceRef", - resourceRef.getName())); + throw new IllegalArgumentException(sm.getString("webXml.duplicateResourceRef", resourceRef.getName())); } resourceRefs.put(resourceRef.getName(), resourceRef); } + public Map getResourceRefs() { return resourceRefs; } @@ -528,36 +634,34 @@ // resource-env-ref // TODO: Should support multiple description elements with language private final Map resourceEnvRefs = new HashMap<>(); + public void addResourceEnvRef(ContextResourceEnvRef resourceEnvRef) { if (resourceEnvRefs.containsKey(resourceEnvRef.getName())) { // resource-env-ref names must be unique within a web(-fragment).xml throw new IllegalArgumentException( - sm.getString("webXml.duplicateResourceEnvRef", - resourceEnvRef.getName())); + sm.getString("webXml.duplicateResourceEnvRef", resourceEnvRef.getName())); } resourceEnvRefs.put(resourceEnvRef.getName(), resourceEnvRef); } + public Map getResourceEnvRefs() { return resourceEnvRefs; } // message-destination-ref // TODO: Should support multiple description elements with language - private final Map messageDestinationRefs = - new HashMap<>(); - public void addMessageDestinationRef( - MessageDestinationRef messageDestinationRef) { - if (messageDestinationRefs.containsKey( - messageDestinationRef.getName())) { + private final Map messageDestinationRefs = new HashMap<>(); + + public void addMessageDestinationRef(MessageDestinationRef messageDestinationRef) { + if (messageDestinationRefs.containsKey(messageDestinationRef.getName())) { // message-destination-ref names must be unique within a // web(-fragment).xml - throw new IllegalArgumentException(sm.getString( - "webXml.duplicateMessageDestinationRef", - messageDestinationRef.getName())); + throw new IllegalArgumentException( + sm.getString("webXml.duplicateMessageDestinationRef", messageDestinationRef.getName())); } - messageDestinationRefs.put(messageDestinationRef.getName(), - messageDestinationRef); + messageDestinationRefs.put(messageDestinationRef.getName(), messageDestinationRef); } + public Map getMessageDestinationRefs() { return messageDestinationRefs; } @@ -566,53 +670,56 @@ // TODO: Should support multiple description elements with language // TODO: Should support multiple display-names elements with language // TODO: Should support multiple icon elements ??? - private final Map messageDestinations = - new HashMap<>(); - public void addMessageDestination( - MessageDestination messageDestination) { - if (messageDestinations.containsKey( - messageDestination.getName())) { + private final Map messageDestinations = new HashMap<>(); + + public void addMessageDestination(MessageDestination messageDestination) { + if (messageDestinations.containsKey(messageDestination.getName())) { // message-destination names must be unique within a // web(-fragment).xml throw new IllegalArgumentException( - sm.getString("webXml.duplicateMessageDestination", - messageDestination.getName())); + sm.getString("webXml.duplicateMessageDestination", messageDestination.getName())); } - messageDestinations.put(messageDestination.getName(), - messageDestination); + messageDestinations.put(messageDestination.getName(), messageDestination); } + public Map getMessageDestinations() { return messageDestinations; } // locale-encoding-mapping-list private final Map localeEncodingMappings = new HashMap<>(); + public void addLocaleEncodingMapping(String locale, String encoding) { localeEncodingMappings.put(locale, encoding); } + public Map getLocaleEncodingMappings() { return localeEncodingMappings; } // post-construct elements - private final Map postConstructMethods = new HashMap<>(); + private final Map postConstructMethods = new HashMap<>(); + public void addPostConstructMethods(String clazz, String method) { if (!postConstructMethods.containsKey(clazz)) { postConstructMethods.put(clazz, method); } } - public Map getPostConstructMethods() { + + public Map getPostConstructMethods() { return postConstructMethods; } // pre-destroy elements - private final Map preDestroyMethods = new HashMap<>(); + private final Map preDestroyMethods = new HashMap<>(); + public void addPreDestroyMethods(String clazz, String method) { if (!preDestroyMethods.containsKey(clazz)) { preDestroyMethods.put(clazz, method); } } - public Map getPreDestroyMethods() { + + public Map getPreDestroyMethods() { return preDestroyMethods; } @@ -621,28 +728,27 @@ return null; } - Collection descriptors = - new ArrayList<>(jspPropertyGroups.size()); + Collection descriptors = new ArrayList<>(jspPropertyGroups.size()); for (JspPropertyGroup jspPropertyGroup : jspPropertyGroups) { - JspPropertyGroupDescriptor descriptor = - new JspPropertyGroupDescriptorImpl(jspPropertyGroup); + JspPropertyGroupDescriptor descriptor = new JspPropertyGroupDescriptorImpl(jspPropertyGroup); descriptors.add(descriptor); } Collection tlds = new HashSet<>(taglibs.size()); - for (Entry entry : taglibs.entrySet()) { - TaglibDescriptor descriptor = new TaglibDescriptorImpl( - entry.getValue(), entry.getKey()); + for (Entry entry : taglibs.entrySet()) { + TaglibDescriptor descriptor = new TaglibDescriptorImpl(entry.getValue(), entry.getKey()); tlds.add(descriptor); } return new JspConfigDescriptorImpl(descriptors, tlds); } private String requestCharacterEncoding; + public String getRequestCharacterEncoding() { return requestCharacterEncoding; } + public void setRequestCharacterEncoding(String requestCharacterEncoding) { if (requestCharacterEncoding != null) { try { @@ -655,9 +761,11 @@ } private String responseCharacterEncoding; + public String getResponseCharacterEncoding() { return responseCharacterEncoding; } + public void setResponseCharacterEncoding(String responseCharacterEncoding) { if (responseCharacterEncoding != null) { try { @@ -673,24 +781,48 @@ // URL of JAR / exploded JAR for this web-fragment private URL uRL = null; - public void setURL(URL url) { this.uRL = url; } - public URL getURL() { return uRL; } + + public void setURL(URL url) { + this.uRL = url; + } + + public URL getURL() { + return uRL; + } // Name of jar file private String jarName = null; - public void setJarName(String jarName) { this.jarName = jarName; } - public String getJarName() { return jarName; } + + public void setJarName(String jarName) { + this.jarName = jarName; + } + + public String getJarName() { + return jarName; + } // Is this JAR part of the application or is it a container JAR? Assume it // is. private boolean webappJar = true; - public void setWebappJar(boolean webappJar) { this.webappJar = webappJar; } - public boolean getWebappJar() { return webappJar; } + + public void setWebappJar(boolean webappJar) { + this.webappJar = webappJar; + } + + public boolean getWebappJar() { + return webappJar; + } // Does this web application delegate first for class loading? private boolean delegate = false; - public boolean getDelegate() { return delegate; } - public void setDelegate(boolean delegate) { this.delegate = delegate; } + + public boolean getDelegate() { + return delegate; + } + + public void setDelegate(boolean delegate) { + this.delegate = delegate; + } @Override public String toString() { @@ -707,23 +839,22 @@ private static final String INDENT6 = " "; /** - * Generate a web.xml in String form that matches the representation stored - * in this object. + * Generate a web.xml in String form that matches the representation stored in this object. * * @return The complete contents of web.xml as a String */ public String toXml() { StringBuilder sb = new StringBuilder(2048); // TODO - Various, icon, description etc elements are skipped - mainly - // because they are ignored when web.xml is parsed - see above + // because they are ignored when web.xml is parsed - see above // NOTE - Elements need to be written in the order defined in the 2.3 - // DTD else validation of the merged web.xml will fail + // DTD else validation of the merged web.xml will fail // NOTE - Some elements need to be skipped based on the version of the - // specification being used. Version is validated and starts at - // 2.2. The version tests used in this method take advantage of - // this. + // specification being used. Version is validated and starts at + // 2.2. The version tests used in this method take advantage of + // this. // Declaration sb.append("\n"); @@ -794,7 +925,7 @@ sb.append(" \n\n"); } - for (Map.Entry entry : contextParams.entrySet()) { + for (Map.Entry entry : contextParams.entrySet()) { sb.append(" \n"); appendElement(sb, INDENT4, "param-name", entry.getKey()); appendElement(sb, INDENT4, "param-value", entry.getValue()); @@ -804,24 +935,18 @@ // Filters were introduced in Servlet 2.3 if (getMajorVersion() > 2 || getMinorVersion() > 2) { - for (Map.Entry entry : filters.entrySet()) { + for (Map.Entry entry : filters.entrySet()) { FilterDef filterDef = entry.getValue(); sb.append(" \n"); - appendElement(sb, INDENT4, "description", - filterDef.getDescription()); - appendElement(sb, INDENT4, "display-name", - filterDef.getDisplayName()); - appendElement(sb, INDENT4, "filter-name", - filterDef.getFilterName()); - appendElement(sb, INDENT4, "filter-class", - filterDef.getFilterClass()); + appendElement(sb, INDENT4, "description", filterDef.getDescription()); + appendElement(sb, INDENT4, "display-name", filterDef.getDisplayName()); + appendElement(sb, INDENT4, "filter-name", filterDef.getFilterName()); + appendElement(sb, INDENT4, "filter-class", filterDef.getFilterClass()); // Async support was introduced for Servlet 3.0 onwards if (getMajorVersion() != 2) { - appendElement(sb, INDENT4, "async-supported", - filterDef.getAsyncSupported()); + appendElement(sb, INDENT4, "async-supported", filterDef.getAsyncSupported()); } - for (Map.Entry param : - filterDef.getParameterMap().entrySet()) { + for (Map.Entry param : filterDef.getParameterMap().entrySet()) { sb.append(" \n"); appendElement(sb, INDENT6, "param-name", param.getKey()); appendElement(sb, INDENT6, "param-value", param.getValue()); @@ -833,8 +958,7 @@ for (FilterMap filterMap : filterMaps) { sb.append(" \n"); - appendElement(sb, INDENT4, "filter-name", - filterMap.getFilterName()); + appendElement(sb, INDENT4, "filter-name", filterMap.getFilterName()); if (filterMap.getMatchAllServletNames()) { sb.append(" *\n"); } else { @@ -852,8 +976,7 @@ // dispatcher was added in Servlet 2.4 if (getMajorVersion() > 2 || getMinorVersion() > 3) { for (String dispatcher : filterMap.getDispatcherNames()) { - if (getMajorVersion() == 2 && - DispatcherType.ASYNC.name().equals(dispatcher)) { + if (getMajorVersion() == 2 && DispatcherType.ASYNC.name().equals(dispatcher)) { continue; } appendElement(sb, INDENT4, "dispatcher", dispatcher); @@ -874,31 +997,25 @@ sb.append('\n'); } - for (Map.Entry entry : servlets.entrySet()) { + for (Map.Entry entry : servlets.entrySet()) { ServletDef servletDef = entry.getValue(); sb.append(" \n"); - appendElement(sb, INDENT4, "description", - servletDef.getDescription()); - appendElement(sb, INDENT4, "display-name", - servletDef.getDisplayName()); + appendElement(sb, INDENT4, "description", servletDef.getDescription()); + appendElement(sb, INDENT4, "display-name", servletDef.getDisplayName()); appendElement(sb, INDENT4, "servlet-name", entry.getKey()); - appendElement(sb, INDENT4, "servlet-class", - servletDef.getServletClass()); + appendElement(sb, INDENT4, "servlet-class", servletDef.getServletClass()); appendElement(sb, INDENT4, "jsp-file", servletDef.getJspFile()); - for (Map.Entry param : - servletDef.getParameterMap().entrySet()) { + for (Map.Entry param : servletDef.getParameterMap().entrySet()) { sb.append(" \n"); appendElement(sb, INDENT6, "param-name", param.getKey()); appendElement(sb, INDENT6, "param-value", param.getValue()); sb.append(" \n"); } - appendElement(sb, INDENT4, "load-on-startup", - servletDef.getLoadOnStartup()); + appendElement(sb, INDENT4, "load-on-startup", servletDef.getLoadOnStartup()); appendElement(sb, INDENT4, "enabled", servletDef.getEnabled()); // Async support was introduced for Servlet 3.0 onwards if (getMajorVersion() != 2) { - appendElement(sb, INDENT4, "async-supported", - servletDef.getAsyncSupported()); + appendElement(sb, INDENT4, "async-supported", servletDef.getAsyncSupported()); } // servlet/run-as was introduced in Servlet 2.3 if (getMajorVersion() > 2 || getMinorVersion() > 2) { @@ -919,14 +1036,10 @@ MultipartDef multipartDef = servletDef.getMultipartDef(); if (multipartDef != null) { sb.append(" \n"); - appendElement(sb, INDENT6, "location", - multipartDef.getLocation()); - appendElement(sb, INDENT6, "max-file-size", - multipartDef.getMaxFileSize()); - appendElement(sb, INDENT6, "max-request-size", - multipartDef.getMaxRequestSize()); - appendElement(sb, INDENT6, "file-size-threshold", - multipartDef.getFileSizeThreshold()); + appendElement(sb, INDENT6, "location", multipartDef.getLocation()); + appendElement(sb, INDENT6, "max-file-size", multipartDef.getMaxFileSize()); + appendElement(sb, INDENT6, "max-request-size", multipartDef.getMaxRequestSize()); + appendElement(sb, INDENT6, "file-size-threshold", multipartDef.getFileSizeThreshold()); sb.append(" \n"); } } @@ -934,7 +1047,7 @@ } sb.append('\n'); - for (Map.Entry entry : servletMappings.entrySet()) { + for (Map.Entry entry : servletMappings.entrySet()) { sb.append(" \n"); appendElement(sb, INDENT4, "servlet-name", entry.getValue()); appendElement(sb, INDENT4, "url-pattern", encodeUrl(entry.getKey())); @@ -944,32 +1057,25 @@ if (sessionConfig != null) { sb.append(" \n"); - appendElement(sb, INDENT4, "session-timeout", - sessionConfig.getSessionTimeout()); + appendElement(sb, INDENT4, "session-timeout", sessionConfig.getSessionTimeout()); if (majorVersion >= 3) { sb.append(" \n"); appendElement(sb, INDENT6, "name", sessionConfig.getCookieName()); - appendElement(sb, INDENT6, "domain", - sessionConfig.getCookieDomain()); + appendElement(sb, INDENT6, "domain", sessionConfig.getCookieDomain()); appendElement(sb, INDENT6, "path", sessionConfig.getCookiePath()); - appendElement(sb, INDENT6, "comment", - sessionConfig.getCookieComment()); - appendElement(sb, INDENT6, "http-only", - sessionConfig.getCookieHttpOnly()); - appendElement(sb, INDENT6, "secure", - sessionConfig.getCookieSecure()); - appendElement(sb, INDENT6, "max-age", - sessionConfig.getCookieMaxAge()); + appendElement(sb, INDENT6, "comment", sessionConfig.getCookieComment()); + appendElement(sb, INDENT6, "http-only", sessionConfig.getCookieHttpOnly()); + appendElement(sb, INDENT6, "secure", sessionConfig.getCookieSecure()); + appendElement(sb, INDENT6, "max-age", sessionConfig.getCookieMaxAge()); sb.append(" \n"); - for (SessionTrackingMode stm : - sessionConfig.getSessionTrackingModes()) { + for (SessionTrackingMode stm : sessionConfig.getSessionTrackingModes()) { appendElement(sb, INDENT4, "tracking-mode", stm.name()); } } sb.append(" \n\n"); } - for (Map.Entry entry : mimeMappings.entrySet()) { + for (Map.Entry entry : mimeMappings.entrySet()) { sb.append(" \n"); appendElement(sb, INDENT4, "extension", entry.getKey()); appendElement(sb, INDENT4, "mime-type", entry.getValue()); @@ -997,8 +1103,7 @@ if (errorPage.getExceptionType() != null) { appendElement(sb, INDENT4, "exception-type", exceptionType); } else if (errorPage.getErrorCode() > 0) { - appendElement(sb, INDENT4, "error-code", - Integer.toString(errorCode)); + appendElement(sb, INDENT4, "error-code", Integer.toString(errorCode)); } appendElement(sb, INDENT4, "location", errorPage.getLocation()); sb.append(" \n"); @@ -1011,7 +1116,7 @@ if (getMajorVersion() > 2 || getMinorVersion() > 3) { sb.append(" \n"); } - for (Map.Entry entry : taglibs.entrySet()) { + for (Map.Entry entry : taglibs.entrySet()) { sb.append(" \n"); appendElement(sb, INDENT6, "taglib-uri", entry.getKey()); appendElement(sb, INDENT6, "taglib-location", entry.getValue()); @@ -1024,10 +1129,8 @@ appendElement(sb, INDENT6, "url-pattern", encodeUrl(urlPattern)); } appendElement(sb, INDENT6, "el-ignored", jpg.getElIgnored()); - appendElement(sb, INDENT6, "page-encoding", - jpg.getPageEncoding()); - appendElement(sb, INDENT6, "scripting-invalid", - jpg.getScriptingInvalid()); + appendElement(sb, INDENT6, "page-encoding", jpg.getPageEncoding()); + appendElement(sb, INDENT6, "scripting-invalid", jpg.getScriptingInvalid()); appendElement(sb, INDENT6, "is-xml", jpg.getIsXml()); for (String prelude : jpg.getIncludePreludes()) { appendElement(sb, INDENT6, "include-prelude", prelude); @@ -1035,15 +1138,11 @@ for (String coda : jpg.getIncludeCodas()) { appendElement(sb, INDENT6, "include-coda", coda); } - appendElement(sb, INDENT6, "deferred-syntax-allowed-as-literal", - jpg.getDeferredSyntax()); - appendElement(sb, INDENT6, "trim-directive-whitespaces", - jpg.getTrimWhitespace()); - appendElement(sb, INDENT6, "default-content-type", - jpg.getDefaultContentType()); + appendElement(sb, INDENT6, "deferred-syntax-allowed-as-literal", jpg.getDeferredSyntax()); + appendElement(sb, INDENT6, "trim-directive-whitespaces", jpg.getTrimWhitespace()); + appendElement(sb, INDENT6, "default-content-type", jpg.getDefaultContentType()); appendElement(sb, INDENT6, "buffer", jpg.getBuffer()); - appendElement(sb, INDENT6, "error-on-undeclared-namespace", - jpg.getErrorOnUndeclaredNamespace()); + appendElement(sb, INDENT6, "error-on-undeclared-namespace", jpg.getErrorOnUndeclaredNamespace()); sb.append(" \n"); } sb.append(" \n\n"); @@ -1054,21 +1153,14 @@ if (getMajorVersion() > 2 || getMinorVersion() > 2) { for (ContextResourceEnvRef resourceEnvRef : resourceEnvRefs.values()) { sb.append(" \n"); - appendElement(sb, INDENT4, "description", - resourceEnvRef.getDescription()); - appendElement(sb, INDENT4, "resource-env-ref-name", - resourceEnvRef.getName()); - appendElement(sb, INDENT4, "resource-env-ref-type", - resourceEnvRef.getType()); - appendElement(sb, INDENT4, "mapped-name", - resourceEnvRef.getProperty("mappedName")); - for (InjectionTarget target : - resourceEnvRef.getInjectionTargets()) { + appendElement(sb, INDENT4, "description", resourceEnvRef.getDescription()); + appendElement(sb, INDENT4, "resource-env-ref-name", resourceEnvRef.getName()); + appendElement(sb, INDENT4, "resource-env-ref-type", resourceEnvRef.getType()); + appendElement(sb, INDENT4, "mapped-name", resourceEnvRef.getProperty("mappedName")); + for (InjectionTarget target : resourceEnvRef.getInjectionTargets()) { sb.append(" \n"); - appendElement(sb, INDENT6, "injection-target-class", - target.getTargetClass()); - appendElement(sb, INDENT6, "injection-target-name", - target.getTargetName()); + appendElement(sb, INDENT6, "injection-target-class", target.getTargetClass()); + appendElement(sb, INDENT6, "injection-target-name", target.getTargetName()); sb.append(" \n"); } appendElement(sb, INDENT4, "lookup-name", resourceEnvRef.getLookupName()); @@ -1079,8 +1171,7 @@ for (ContextResource resourceRef : resourceRefs.values()) { sb.append(" \n"); - appendElement(sb, INDENT4, "description", - resourceRef.getDescription()); + appendElement(sb, INDENT4, "description", resourceRef.getDescription()); appendElement(sb, INDENT4, "res-ref-name", resourceRef.getName()); appendElement(sb, INDENT4, "res-type", resourceRef.getType()); appendElement(sb, INDENT4, "res-auth", resourceRef.getAuth()); @@ -1091,10 +1182,8 @@ appendElement(sb, INDENT4, "mapped-name", resourceRef.getProperty("mappedName")); for (InjectionTarget target : resourceRef.getInjectionTargets()) { sb.append(" \n"); - appendElement(sb, INDENT6, "injection-target-class", - target.getTargetClass()); - appendElement(sb, INDENT6, "injection-target-name", - target.getTargetName()); + appendElement(sb, INDENT6, "injection-target-class", target.getTargetClass()); + appendElement(sb, INDENT6, "injection-target-name", target.getTargetName()); sb.append(" \n"); } appendElement(sb, INDENT4, "lookup-name", resourceRef.getLookupName()); @@ -1106,15 +1195,12 @@ sb.append(" \n"); // security-constraint/display-name was introduced in Servlet 2.3 if (getMajorVersion() > 2 || getMinorVersion() > 2) { - appendElement(sb, INDENT4, "display-name", - constraint.getDisplayName()); + appendElement(sb, INDENT4, "display-name", constraint.getDisplayName()); } for (SecurityCollection collection : constraint.findCollections()) { sb.append(" \n"); - appendElement(sb, INDENT6, "web-resource-name", - collection.getName()); - appendElement(sb, INDENT6, "description", - collection.getDescription()); + appendElement(sb, INDENT6, "web-resource-name", collection.getName()); + appendElement(sb, INDENT6, "description", collection.getDescription()); for (String urlPattern : collection.findPatterns()) { appendElement(sb, INDENT6, "url-pattern", encodeUrl(urlPattern)); } @@ -1135,8 +1221,7 @@ } if (constraint.getUserConstraint() != null) { sb.append(" \n"); - appendElement(sb, INDENT6, "transport-guarantee", - constraint.getUserConstraint()); + appendElement(sb, INDENT6, "transport-guarantee", constraint.getUserConstraint()); sb.append(" \n"); } sb.append(" \n"); @@ -1145,17 +1230,12 @@ if (loginConfig != null) { sb.append(" \n"); - appendElement(sb, INDENT4, "auth-method", - loginConfig.getAuthMethod()); - appendElement(sb,INDENT4, "realm-name", - loginConfig.getRealmName()); - if (loginConfig.getErrorPage() != null || - loginConfig.getLoginPage() != null) { + appendElement(sb, INDENT4, "auth-method", loginConfig.getAuthMethod()); + appendElement(sb, INDENT4, "realm-name", loginConfig.getRealmName()); + if (loginConfig.getErrorPage() != null || loginConfig.getLoginPage() != null) { sb.append(" \n"); - appendElement(sb, INDENT6, "form-login-page", - loginConfig.getLoginPage()); - appendElement(sb, INDENT6, "form-error-page", - loginConfig.getErrorPage()); + appendElement(sb, INDENT6, "form-login-page", loginConfig.getLoginPage()); + appendElement(sb, INDENT6, "form-error-page", loginConfig.getErrorPage()); sb.append(" \n"); } sb.append(" \n\n"); @@ -1169,18 +1249,15 @@ for (ContextEnvironment envEntry : envEntries.values()) { sb.append(" \n"); - appendElement(sb, INDENT4, "description", - envEntry.getDescription()); + appendElement(sb, INDENT4, "description", envEntry.getDescription()); appendElement(sb, INDENT4, "env-entry-name", envEntry.getName()); appendElement(sb, INDENT4, "env-entry-type", envEntry.getType()); appendElement(sb, INDENT4, "env-entry-value", envEntry.getValue()); appendElement(sb, INDENT4, "mapped-name", envEntry.getProperty("mappedName")); for (InjectionTarget target : envEntry.getInjectionTargets()) { sb.append(" \n"); - appendElement(sb, INDENT6, "injection-target-class", - target.getTargetClass()); - appendElement(sb, INDENT6, "injection-target-name", - target.getTargetName()); + appendElement(sb, INDENT6, "injection-target-class", target.getTargetClass()); + appendElement(sb, INDENT6, "injection-target-name", target.getTargetName()); sb.append(" \n"); } appendElement(sb, INDENT4, "lookup-name", envEntry.getLookupName()); @@ -1199,10 +1276,8 @@ appendElement(sb, INDENT4, "mapped-name", ejbRef.getProperty("mappedName")); for (InjectionTarget target : ejbRef.getInjectionTargets()) { sb.append(" \n"); - appendElement(sb, INDENT6, "injection-target-class", - target.getTargetClass()); - appendElement(sb, INDENT6, "injection-target-name", - target.getTargetName()); + appendElement(sb, INDENT6, "injection-target-class", target.getTargetClass()); + appendElement(sb, INDENT6, "injection-target-name", target.getTargetName()); sb.append(" \n"); } appendElement(sb, INDENT4, "lookup-name", ejbRef.getLookupName()); @@ -1214,8 +1289,7 @@ if (getMajorVersion() > 2 || getMinorVersion() > 2) { for (ContextLocalEjb ejbLocalRef : ejbLocalRefs.values()) { sb.append(" \n"); - appendElement(sb, INDENT4, "description", - ejbLocalRef.getDescription()); + appendElement(sb, INDENT4, "description", ejbLocalRef.getDescription()); appendElement(sb, INDENT4, "ejb-ref-name", ejbLocalRef.getName()); appendElement(sb, INDENT4, "ejb-ref-type", ejbLocalRef.getType()); appendElement(sb, INDENT4, "local-home", ejbLocalRef.getHome()); @@ -1224,10 +1298,8 @@ appendElement(sb, INDENT4, "mapped-name", ejbLocalRef.getProperty("mappedName")); for (InjectionTarget target : ejbLocalRef.getInjectionTargets()) { sb.append(" \n"); - appendElement(sb, INDENT6, "injection-target-class", - target.getTargetClass()); - appendElement(sb, INDENT6, "injection-target-name", - target.getTargetName()); + appendElement(sb, INDENT6, "injection-target-class", target.getTargetClass()); + appendElement(sb, INDENT6, "injection-target-name", target.getTargetName()); sb.append(" \n"); } appendElement(sb, INDENT4, "lookup-name", ejbLocalRef.getLookupName()); @@ -1240,19 +1312,13 @@ if (getMajorVersion() > 2 || getMinorVersion() > 3) { for (ContextService serviceRef : serviceRefs.values()) { sb.append(" \n"); - appendElement(sb, INDENT4, "description", - serviceRef.getDescription()); - appendElement(sb, INDENT4, "display-name", - serviceRef.getDisplayname()); - appendElement(sb, INDENT4, "service-ref-name", - serviceRef.getName()); - appendElement(sb, INDENT4, "service-interface", - serviceRef.getInterface()); - appendElement(sb, INDENT4, "service-ref-type", - serviceRef.getType()); + appendElement(sb, INDENT4, "description", serviceRef.getDescription()); + appendElement(sb, INDENT4, "display-name", serviceRef.getDisplayname()); + appendElement(sb, INDENT4, "service-ref-name", serviceRef.getName()); + appendElement(sb, INDENT4, "service-interface", serviceRef.getInterface()); + appendElement(sb, INDENT4, "service-ref-type", serviceRef.getType()); appendElement(sb, INDENT4, "wsdl-file", serviceRef.getWsdlfile()); - appendElement(sb, INDENT4, "jaxrpc-mapping-file", - serviceRef.getJaxrpcmappingfile()); + appendElement(sb, INDENT4, "jaxrpc-mapping-file", serviceRef.getJaxrpcmappingfile()); String qname = serviceRef.getServiceqnameNamespaceURI(); if (qname != null) { qname = qname + ":"; @@ -1263,10 +1329,8 @@ while (endpointIter.hasNext()) { String endpoint = endpointIter.next(); sb.append(" \n"); - appendElement(sb, INDENT6, "service-endpoint-interface", - endpoint); - appendElement(sb, INDENT6, "port-component-link", - serviceRef.getProperty(endpoint)); + appendElement(sb, INDENT6, "service-endpoint-interface", endpoint); + appendElement(sb, INDENT6, "port-component-link", serviceRef.getProperty(endpoint)); sb.append(" \n"); } Iterator handlerIter = serviceRef.getHandlers(); @@ -1275,18 +1339,15 @@ sb.append(" \n"); ContextHandler ch = serviceRef.getHandler(handler); appendElement(sb, INDENT6, "handler-name", ch.getName()); - appendElement(sb, INDENT6, "handler-class", - ch.getHandlerclass()); + appendElement(sb, INDENT6, "handler-class", ch.getHandlerclass()); sb.append(" \n"); } // TODO handler-chains appendElement(sb, INDENT4, "mapped-name", serviceRef.getProperty("mappedName")); for (InjectionTarget target : serviceRef.getInjectionTargets()) { sb.append(" \n"); - appendElement(sb, INDENT6, "injection-target-class", - target.getTargetClass()); - appendElement(sb, INDENT6, "injection-target-name", - target.getTargetName()); + appendElement(sb, INDENT6, "injection-target-class", target.getTargetClass()); + appendElement(sb, INDENT6, "injection-target-name", target.getTargetName()); sb.append(" \n"); } appendElement(sb, INDENT4, "lookup-name", serviceRef.getLookupName()); @@ -1296,26 +1357,20 @@ } if (!postConstructMethods.isEmpty()) { - for (Entry entry : postConstructMethods - .entrySet()) { + for (Entry entry : postConstructMethods.entrySet()) { sb.append(" \n"); - appendElement(sb, INDENT4, "lifecycle-callback-class", - entry.getKey()); - appendElement(sb, INDENT4, "lifecycle-callback-method", - entry.getValue()); + appendElement(sb, INDENT4, "lifecycle-callback-class", entry.getKey()); + appendElement(sb, INDENT4, "lifecycle-callback-method", entry.getValue()); sb.append(" \n"); } sb.append('\n'); } if (!preDestroyMethods.isEmpty()) { - for (Entry entry : preDestroyMethods - .entrySet()) { + for (Entry entry : preDestroyMethods.entrySet()) { sb.append(" \n"); - appendElement(sb, INDENT4, "lifecycle-callback-class", - entry.getKey()); - appendElement(sb, INDENT4, "lifecycle-callback-method", - entry.getValue()); + appendElement(sb, INDENT4, "lifecycle-callback-class", entry.getKey()); + appendElement(sb, INDENT4, "lifecycle-callback-method", entry.getValue()); sb.append(" \n"); } sb.append('\n'); @@ -1327,21 +1382,15 @@ for (MessageDestinationRef mdr : messageDestinationRefs.values()) { sb.append(" \n"); appendElement(sb, INDENT4, "description", mdr.getDescription()); - appendElement(sb, INDENT4, "message-destination-ref-name", - mdr.getName()); - appendElement(sb, INDENT4, "message-destination-type", - mdr.getType()); - appendElement(sb, INDENT4, "message-destination-usage", - mdr.getUsage()); - appendElement(sb, INDENT4, "message-destination-link", - mdr.getLink()); + appendElement(sb, INDENT4, "message-destination-ref-name", mdr.getName()); + appendElement(sb, INDENT4, "message-destination-type", mdr.getType()); + appendElement(sb, INDENT4, "message-destination-usage", mdr.getUsage()); + appendElement(sb, INDENT4, "message-destination-link", mdr.getLink()); appendElement(sb, INDENT4, "mapped-name", mdr.getProperty("mappedName")); for (InjectionTarget target : mdr.getInjectionTargets()) { sb.append(" \n"); - appendElement(sb, INDENT6, "injection-target-class", - target.getTargetClass()); - appendElement(sb, INDENT6, "injection-target-name", - target.getTargetName()); + appendElement(sb, INDENT6, "injection-target-class", target.getTargetClass()); + appendElement(sb, INDENT6, "injection-target-name", target.getTargetName()); sb.append(" \n"); } appendElement(sb, INDENT4, "lookup-name", mdr.getLookupName()); @@ -1353,8 +1402,7 @@ sb.append(" \n"); appendElement(sb, INDENT4, "description", md.getDescription()); appendElement(sb, INDENT4, "display-name", md.getDisplayName()); - appendElement(sb, INDENT4, "message-destination-name", - md.getName()); + appendElement(sb, INDENT4, "message-destination-name", md.getName()); appendElement(sb, INDENT4, "mapped-name", md.getProperty("mappedName")); appendElement(sb, INDENT4, "lookup-name", md.getLookupName()); sb.append(" \n"); @@ -1366,8 +1414,7 @@ if (getMajorVersion() > 2 || getMinorVersion() > 3) { if (!localeEncodingMappings.isEmpty()) { sb.append(" \n"); - for (Map.Entry entry : - localeEncodingMappings.entrySet()) { + for (Map.Entry entry : localeEncodingMappings.entrySet()) { sb.append(" \n"); appendElement(sb, INDENT6, "locale", entry.getKey()); appendElement(sb, INDENT6, "encoding", entry.getValue()); @@ -1379,8 +1426,7 @@ } // deny-uncovered-http-methods was introduced in Servlet 3.1 - if (getMajorVersion() > 3 || - (getMajorVersion() == 3 && getMinorVersion() > 0)) { + if (getMajorVersion() > 3 || (getMajorVersion() == 3 && getMinorVersion() > 0)) { if (denyUncoveredHttpMethods) { sb.append(" "); sb.append("\n"); @@ -1402,8 +1448,7 @@ } - private static void appendElement(StringBuilder sb, String indent, - String elementName, String value) { + private static void appendElement(StringBuilder sb, String indent, String elementName, String value) { if (value == null) { return; } @@ -1424,8 +1469,7 @@ } } - private static void appendElement(StringBuilder sb, String indent, - String elementName, Object value) { + private static void appendElement(StringBuilder sb, String indent, String elementName, Object value) { if (value == null) { return; } @@ -1436,9 +1480,9 @@ /** * Merge the supplied web fragments into this main web.xml. * - * @param fragments The fragments to merge in - * @return true if merge is successful, else - * false + * @param fragments The fragments to merge in + * + * @return true if merge is successful, else false */ public boolean merge(Set fragments) { // As far as possible, process in alphabetical order so it is easy to @@ -1449,8 +1493,8 @@ WebXml temp = new WebXml(); for (WebXml fragment : fragments) { - if (!mergeMap(fragment.getContextParams(), contextParams, - temp.getContextParams(), fragment, "Context Parameter")) { + if (!mergeMap(fragment.getContextParams(), contextParams, temp.getContextParams(), fragment, + "Context Parameter")) { return false; } } @@ -1463,10 +1507,8 @@ if (temp.getDisplayName() == null) { temp.setDisplayName(value); } else { - log.error(sm.getString( - "webXml.mergeConflictDisplayName", - fragment.getName(), - fragment.getURL())); + log.error( + sm.getString("webXml.mergeConflictDisplayName", fragment.getName(), fragment.getURL())); return false; } } @@ -1475,7 +1517,7 @@ } // Note: Not permitted in fragments, but we also use fragments for - // per-Host and global defaults so they may appear there + // per-Host and global defaults so they may appear there if (!denyUncoveredHttpMethods) { for (WebXml fragment : fragments) { if (fragment.getDenyUncoveredHttpMethods()) { @@ -1509,32 +1551,28 @@ } for (WebXml fragment : fragments) { - if (!mergeResourceMap(fragment.getEjbLocalRefs(), ejbLocalRefs, - temp.getEjbLocalRefs(), fragment)) { + if (!mergeResourceMap(fragment.getEjbLocalRefs(), ejbLocalRefs, temp.getEjbLocalRefs(), fragment)) { return false; } } ejbLocalRefs.putAll(temp.getEjbLocalRefs()); for (WebXml fragment : fragments) { - if (!mergeResourceMap(fragment.getEjbRefs(), ejbRefs, - temp.getEjbRefs(), fragment)) { + if (!mergeResourceMap(fragment.getEjbRefs(), ejbRefs, temp.getEjbRefs(), fragment)) { return false; } } ejbRefs.putAll(temp.getEjbRefs()); for (WebXml fragment : fragments) { - if (!mergeResourceMap(fragment.getEnvEntries(), envEntries, - temp.getEnvEntries(), fragment)) { + if (!mergeResourceMap(fragment.getEnvEntries(), envEntries, temp.getEnvEntries(), fragment)) { return false; } } envEntries.putAll(temp.getEnvEntries()); for (WebXml fragment : fragments) { - if (!mergeMap(fragment.getErrorPages(), errorPages, - temp.getErrorPages(), fragment, "Error Page")) { + if (!mergeMap(fragment.getErrorPages(), errorPages, temp.getErrorPages(), fragment, "Error Page")) { return false; } } @@ -1557,19 +1595,13 @@ } for (WebXml fragment : fragments) { - for (Map.Entry entry : - fragment.getFilters().entrySet()) { + for (Map.Entry entry : fragment.getFilters().entrySet()) { if (filters.containsKey(entry.getKey())) { - mergeFilter(entry.getValue(), - filters.get(entry.getKey()), false); + mergeFilter(entry.getValue(), filters.get(entry.getKey()), false); } else { if (temp.getFilters().containsKey(entry.getKey())) { - if (!(mergeFilter(entry.getValue(), - temp.getFilters().get(entry.getKey()), true))) { - log.error(sm.getString( - "webXml.mergeConflictFilter", - entry.getKey(), - fragment.getName(), + if (!(mergeFilter(entry.getValue(), temp.getFilters().get(entry.getKey()), true))) { + log.error(sm.getString("webXml.mergeConflictFilter", entry.getKey(), fragment.getName(), fragment.getURL())); return false; @@ -1583,8 +1615,7 @@ filters.putAll(temp.getFilters()); for (WebXml fragment : fragments) { - for (JspPropertyGroup jspPropertyGroup : - fragment.getJspPropertyGroups()) { + for (JspPropertyGroup jspPropertyGroup : fragment.getJspPropertyGroups()) { // Always additive addJspPropertyGroup(jspPropertyGroup); } @@ -1598,9 +1629,8 @@ } for (WebXml fragment : fragments) { - if (!mergeMap(fragment.getLocaleEncodingMappings(), - localeEncodingMappings, temp.getLocaleEncodingMappings(), - fragment, "Locale Encoding Mapping")) { + if (!mergeMap(fragment.getLocaleEncodingMappings(), localeEncodingMappings, + temp.getLocaleEncodingMappings(), fragment, "Locale Encoding Mapping")) { return false; } } @@ -1611,14 +1641,11 @@ for (WebXml fragment : fragments) { LoginConfig fragmentLoginConfig = fragment.loginConfig; if (fragmentLoginConfig != null) { - if (tempLoginConfig == null || - fragmentLoginConfig.equals(tempLoginConfig)) { + if (tempLoginConfig == null || fragmentLoginConfig.equals(tempLoginConfig)) { tempLoginConfig = fragmentLoginConfig; } else { - log.error(sm.getString( - "webXml.mergeConflictLoginConfig", - fragment.getName(), - fragment.getURL())); + log.error( + sm.getString("webXml.mergeConflictLoginConfig", fragment.getName(), fragment.getURL())); } } } @@ -1634,32 +1661,30 @@ messageDestinationRefs.putAll(temp.getMessageDestinationRefs()); for (WebXml fragment : fragments) { - if (!mergeResourceMap(fragment.getMessageDestinations(), messageDestinations, - temp.getMessageDestinations(), fragment)) { + if (!mergeResourceMap(fragment.getMessageDestinations(), messageDestinations, temp.getMessageDestinations(), + fragment)) { return false; } } messageDestinations.putAll(temp.getMessageDestinations()); for (WebXml fragment : fragments) { - if (!mergeMap(fragment.getMimeMappings(), mimeMappings, - temp.getMimeMappings(), fragment, "Mime Mapping")) { + if (!mergeMap(fragment.getMimeMappings(), mimeMappings, temp.getMimeMappings(), fragment, "Mime Mapping")) { return false; } } mimeMappings.putAll(temp.getMimeMappings()); for (WebXml fragment : fragments) { - if (!mergeResourceMap(fragment.getResourceEnvRefs(), resourceEnvRefs, - temp.getResourceEnvRefs(), fragment)) { + if (!mergeResourceMap(fragment.getResourceEnvRefs(), resourceEnvRefs, temp.getResourceEnvRefs(), + fragment)) { return false; } } resourceEnvRefs.putAll(temp.getResourceEnvRefs()); for (WebXml fragment : fragments) { - if (!mergeResourceMap(fragment.getResourceRefs(), resourceRefs, - temp.getResourceRefs(), fragment)) { + if (!mergeResourceMap(fragment.getResourceRefs(), resourceRefs, temp.getResourceRefs(), fragment)) { return false; } } @@ -1680,8 +1705,7 @@ } for (WebXml fragment : fragments) { - if (!mergeResourceMap(fragment.getServiceRefs(), serviceRefs, - temp.getServiceRefs(), fragment)) { + if (!mergeResourceMap(fragment.getServiceRefs(), serviceRefs, temp.getServiceRefs(), fragment)) { return false; } } @@ -1694,8 +1718,7 @@ // defined in web.xml List> servletMappingsToAdd = new ArrayList<>(); for (WebXml fragment : fragments) { - for (Map.Entry servletMap : - fragment.getServletMappings().entrySet()) { + for (Map.Entry servletMap : fragment.getServletMappings().entrySet()) { if (!servletMappingNames.contains(servletMap.getValue()) && !servletMappings.containsKey(servletMap.getKey())) { servletMappingsToAdd.add(servletMap); @@ -1709,19 +1732,13 @@ } for (WebXml fragment : fragments) { - for (Map.Entry entry : - fragment.getServlets().entrySet()) { + for (Map.Entry entry : fragment.getServlets().entrySet()) { if (servlets.containsKey(entry.getKey())) { - mergeServlet(entry.getValue(), - servlets.get(entry.getKey()), false); + mergeServlet(entry.getValue(), servlets.get(entry.getKey()), false); } else { if (temp.getServlets().containsKey(entry.getKey())) { - if (!(mergeServlet(entry.getValue(), - temp.getServlets().get(entry.getKey()), true))) { - log.error(sm.getString( - "webXml.mergeConflictServlet", - entry.getKey(), - fragment.getName(), + if (!(mergeServlet(entry.getValue(), temp.getServlets().get(entry.getKey()), true))) { + log.error(sm.getString("webXml.mergeConflictServlet", entry.getKey(), fragment.getName(), fragment.getURL())); return false; @@ -1740,21 +1757,17 @@ if (value != null) { if (temp.getSessionConfig().getSessionTimeout() == null) { temp.getSessionConfig().setSessionTimeout(value.toString()); - } else if (value.equals( - temp.getSessionConfig().getSessionTimeout())) { + } else if (value.equals(temp.getSessionConfig().getSessionTimeout())) { // Fragments use same value - no conflict } else { - log.error(sm.getString( - "webXml.mergeConflictSessionTimeout", - fragment.getName(), + log.error(sm.getString("webXml.mergeConflictSessionTimeout", fragment.getName(), fragment.getURL())); return false; } } } if (temp.getSessionConfig().getSessionTimeout() != null) { - sessionConfig.setSessionTimeout( - temp.getSessionConfig().getSessionTimeout().toString()); + sessionConfig.setSessionTimeout(temp.getSessionConfig().getSessionTimeout().toString()); } } @@ -1764,20 +1777,16 @@ if (value != null) { if (temp.getSessionConfig().getCookieName() == null) { temp.getSessionConfig().setCookieName(value); - } else if (value.equals( - temp.getSessionConfig().getCookieName())) { + } else if (value.equals(temp.getSessionConfig().getCookieName())) { // Fragments use same value - no conflict } else { - log.error(sm.getString( - "webXml.mergeConflictSessionCookieName", - fragment.getName(), + log.error(sm.getString("webXml.mergeConflictSessionCookieName", fragment.getName(), fragment.getURL())); return false; } } } - sessionConfig.setCookieName( - temp.getSessionConfig().getCookieName()); + sessionConfig.setCookieName(temp.getSessionConfig().getCookieName()); } Map mainAttributes = getSessionConfig().getCookieAttributes(); @@ -1791,9 +1800,7 @@ // If values are the same, NO-OP. If they are different // trigger a merge error if (!mergedFragmentAttributes.get(attribute.getKey()).equals(attribute.getValue())) { - log.error(sm.getString( - "webXml.mergeConflictSessionCookieAttributes", - fragment.getName(), + log.error(sm.getString("webXml.mergeConflictSessionCookieAttributes", fragment.getName(), fragment.getURL())); return false; } @@ -1808,30 +1815,24 @@ if (sessionConfig.getSessionTrackingModes().isEmpty()) { for (WebXml fragment : fragments) { - EnumSet value = - fragment.getSessionConfig().getSessionTrackingModes(); + EnumSet value = fragment.getSessionConfig().getSessionTrackingModes(); if (!value.isEmpty()) { if (temp.getSessionConfig().getSessionTrackingModes().isEmpty()) { temp.getSessionConfig().getSessionTrackingModes().addAll(value); - } else if (value.equals( - temp.getSessionConfig().getSessionTrackingModes())) { + } else if (value.equals(temp.getSessionConfig().getSessionTrackingModes())) { // Fragments use same value - no conflict } else { - log.error(sm.getString( - "webXml.mergeConflictSessionTrackingMode", - fragment.getName(), + log.error(sm.getString("webXml.mergeConflictSessionTrackingMode", fragment.getName(), fragment.getURL())); return false; } } } - sessionConfig.getSessionTrackingModes().addAll( - temp.getSessionConfig().getSessionTrackingModes()); + sessionConfig.getSessionTrackingModes().addAll(temp.getSessionConfig().getSessionTrackingModes()); } for (WebXml fragment : fragments) { - if (!mergeMap(fragment.getTaglibs(), taglibs, - temp.getTaglibs(), fragment, "Taglibs")) { + if (!mergeMap(fragment.getTaglibs(), taglibs, temp.getTaglibs(), fragment, "Taglibs")) { return false; } } @@ -1847,9 +1848,8 @@ if (postConstructMethods.isEmpty()) { for (WebXml fragment : fragments) { - if (!mergeLifecycleCallback(fragment.getPostConstructMethods(), - temp.getPostConstructMethods(), fragment, - "Post Construct Methods")) { + if (!mergeLifecycleCallback(fragment.getPostConstructMethods(), temp.getPostConstructMethods(), + fragment, "Post Construct Methods")) { return false; } } @@ -1858,8 +1858,7 @@ if (preDestroyMethods.isEmpty()) { for (WebXml fragment : fragments) { - if (!mergeLifecycleCallback(fragment.getPreDestroyMethods(), - temp.getPreDestroyMethods(), fragment, + if (!mergeLifecycleCallback(fragment.getPreDestroyMethods(), temp.getPreDestroyMethods(), fragment, "Pre Destroy Methods")) { return false; } @@ -1870,23 +1869,18 @@ return true; } - private boolean mergeResourceMap( - Map fragmentResources, Map mainResources, - Map tempResources, WebXml fragment) { + private boolean mergeResourceMap(Map fragmentResources, + Map mainResources, Map tempResources, WebXml fragment) { for (T resource : fragmentResources.values()) { String resourceName = resource.getName(); if (mainResources.containsKey(resourceName)) { - mainResources.get(resourceName).getInjectionTargets().addAll( - resource.getInjectionTargets()); + mainResources.get(resourceName).getInjectionTargets().addAll(resource.getInjectionTargets()); } else { // Not defined in main web.xml T existingResource = tempResources.get(resourceName); if (existingResource != null) { if (!existingResource.equals(resource)) { - log.error(sm.getString( - "webXml.mergeConflictResource", - resourceName, - fragment.getName(), + log.error(sm.getString("webXml.mergeConflictResource", resourceName, fragment.getName(), fragment.getURL())); return false; } @@ -1898,22 +1892,16 @@ return true; } - private boolean mergeMap(Map fragmentMap, - Map mainMap, Map tempMap, WebXml fragment, - String mapName) { - for (Entry entry : fragmentMap.entrySet()) { + private boolean mergeMap(Map fragmentMap, Map mainMap, Map tempMap, + WebXml fragment, String mapName) { + for (Entry entry : fragmentMap.entrySet()) { final String key = entry.getKey(); if (!mainMap.containsKey(key)) { // Not defined in main web.xml T value = entry.getValue(); if (tempMap.containsKey(key)) { - if (value != null && !value.equals( - tempMap.get(key))) { - log.error(sm.getString( - "webXml.mergeConflictString", - mapName, - key, - fragment.getName(), + if (value != null && !value.equals(tempMap.get(key))) { + log.error(sm.getString("webXml.mergeConflictString", mapName, key, fragment.getName(), fragment.getURL())); return false; } @@ -1925,31 +1913,26 @@ return true; } - private static boolean mergeFilter(FilterDef src, FilterDef dest, - boolean failOnConflict) { + private static boolean mergeFilter(FilterDef src, FilterDef dest, boolean failOnConflict) { if (dest.getAsyncSupported() == null) { dest.setAsyncSupported(src.getAsyncSupported()); } else if (src.getAsyncSupported() != null) { - if (failOnConflict && - !src.getAsyncSupported().equals(dest.getAsyncSupported())) { + if (failOnConflict && !src.getAsyncSupported().equals(dest.getAsyncSupported())) { return false; } } - if (dest.getFilterClass() == null) { + if (dest.getFilterClass() == null) { dest.setFilterClass(src.getFilterClass()); } else if (src.getFilterClass() != null) { - if (failOnConflict && - !src.getFilterClass().equals(dest.getFilterClass())) { + if (failOnConflict && !src.getFilterClass().equals(dest.getFilterClass())) { return false; } } - for (Map.Entry srcEntry : - src.getParameterMap().entrySet()) { + for (Map.Entry srcEntry : src.getParameterMap().entrySet()) { if (dest.getParameterMap().containsKey(srcEntry.getKey())) { - if (failOnConflict && !dest.getParameterMap().get( - srcEntry.getKey()).equals(srcEntry.getValue())) { + if (failOnConflict && !dest.getParameterMap().get(srcEntry.getKey()).equals(srcEntry.getValue())) { return false; } } else { @@ -1959,8 +1942,7 @@ return true; } - private static boolean mergeServlet(ServletDef src, ServletDef dest, - boolean failOnConflict) { + private static boolean mergeServlet(ServletDef src, ServletDef dest, boolean failOnConflict) { // These tests should be unnecessary... if (dest.getServletClass() != null && dest.getJspFile() != null) { return false; @@ -1975,13 +1957,11 @@ dest.setJspFile(src.getJspFile()); } else if (failOnConflict) { if (src.getServletClass() != null && - (dest.getJspFile() != null || - !src.getServletClass().equals(dest.getServletClass()))) { + (dest.getJspFile() != null || !src.getServletClass().equals(dest.getServletClass()))) { return false; } if (src.getJspFile() != null && - (dest.getServletClass() != null || - !src.getJspFile().equals(dest.getJspFile()))) { + (dest.getServletClass() != null || !src.getJspFile().equals(dest.getJspFile()))) { return false; } } @@ -1996,8 +1976,7 @@ dest.setLoadOnStartup(src.getLoadOnStartup().toString()); } } else if (src.getLoadOnStartup() != null) { - if (failOnConflict && - !src.getLoadOnStartup().equals(dest.getLoadOnStartup())) { + if (failOnConflict && !src.getLoadOnStartup().equals(dest.getLoadOnStartup())) { return false; } } @@ -2007,17 +1986,14 @@ dest.setEnabled(src.getEnabled().toString()); } } else if (src.getEnabled() != null) { - if (failOnConflict && - !src.getEnabled().equals(dest.getEnabled())) { + if (failOnConflict && !src.getEnabled().equals(dest.getEnabled())) { return false; } } - for (Map.Entry srcEntry : - src.getParameterMap().entrySet()) { + for (Map.Entry srcEntry : src.getParameterMap().entrySet()) { if (dest.getParameterMap().containsKey(srcEntry.getKey())) { - if (failOnConflict && !dest.getParameterMap().get( - srcEntry.getKey()).equals(srcEntry.getValue())) { + if (failOnConflict && !dest.getParameterMap().get(srcEntry.getKey()).equals(srcEntry.getValue())) { return false; } } else { @@ -2028,8 +2004,7 @@ if (dest.getMultipartDef() == null) { dest.setMultipartDef(src.getMultipartDef()); } else if (src.getMultipartDef() != null) { - return mergeMultipartDef(src.getMultipartDef(), - dest.getMultipartDef(), failOnConflict); + return mergeMultipartDef(src.getMultipartDef(), dest.getMultipartDef(), failOnConflict); } if (dest.getAsyncSupported() == null) { @@ -2037,21 +2012,18 @@ dest.setAsyncSupported(src.getAsyncSupported().toString()); } } else if (src.getAsyncSupported() != null) { - return !failOnConflict || - src.getAsyncSupported().equals(dest.getAsyncSupported()); + return !failOnConflict || src.getAsyncSupported().equals(dest.getAsyncSupported()); } return true; } - private static boolean mergeMultipartDef(MultipartDef src, MultipartDef dest, - boolean failOnConflict) { + private static boolean mergeMultipartDef(MultipartDef src, MultipartDef dest, boolean failOnConflict) { if (dest.getLocation() == null) { dest.setLocation(src.getLocation()); } else if (src.getLocation() != null) { - if (failOnConflict && - !src.getLocation().equals(dest.getLocation())) { + if (failOnConflict && !src.getLocation().equals(dest.getLocation())) { return false; } } @@ -2059,9 +2031,7 @@ if (dest.getFileSizeThreshold() == null) { dest.setFileSizeThreshold(src.getFileSizeThreshold()); } else if (src.getFileSizeThreshold() != null) { - if (failOnConflict && - !src.getFileSizeThreshold().equals( - dest.getFileSizeThreshold())) { + if (failOnConflict && !src.getFileSizeThreshold().equals(dest.getFileSizeThreshold())) { return false; } } @@ -2069,8 +2039,7 @@ if (dest.getMaxFileSize() == null) { dest.setMaxFileSize(src.getMaxFileSize()); } else if (src.getMaxFileSize() != null) { - if (failOnConflict && - !src.getMaxFileSize().equals(dest.getMaxFileSize())) { + if (failOnConflict && !src.getMaxFileSize().equals(dest.getMaxFileSize())) { return false; } } @@ -2078,24 +2047,22 @@ if (dest.getMaxRequestSize() == null) { dest.setMaxRequestSize(src.getMaxRequestSize()); } else if (src.getMaxRequestSize() != null) { - return !failOnConflict || - src.getMaxRequestSize().equals(dest.getMaxRequestSize()); + return !failOnConflict || src.getMaxRequestSize().equals(dest.getMaxRequestSize()); } return true; } - private boolean mergeLifecycleCallback( - Map fragmentMap, Map tempMap, - WebXml fragment, String mapName) { - for (Entry entry : fragmentMap.entrySet()) { + private boolean mergeLifecycleCallback(Map fragmentMap, Map tempMap, WebXml fragment, + String mapName) { + for (Entry entry : fragmentMap.entrySet()) { final String key = entry.getKey(); final String value = entry.getValue(); if (tempMap.containsKey(key)) { if (value != null && !value.equals(tempMap.get(key))) { - log.error(sm.getString("webXml.mergeConflictString", - mapName, key, fragment.getName(), fragment.getURL())); + log.error(sm.getString("webXml.mergeConflictString", mapName, key, fragment.getName(), + fragment.getURL())); return false; } } else { @@ -2107,24 +2074,22 @@ /** - * Generates the sub-set of the web-fragment.xml files to be processed in - * the order that the fragments must be processed as per the rules in the - * Servlet spec. + * Generates the sub-set of the web-fragment.xml files to be processed in the order that the fragments must be + * processed as per the rules in the Servlet spec. * * @param application The application web.xml file * @param fragments The map of fragment names to web fragments - * @param servletContext The servlet context the fragments are associated - * with + * @param servletContext The servlet context the fragments are associated with + * * @return Ordered list of web-fragment.xml files to process */ - public static Set orderWebFragments(WebXml application, - Map fragments, ServletContext servletContext) { + public static Set orderWebFragments(WebXml application, Map fragments, + ServletContext servletContext) { return application.orderWebFragments(fragments, servletContext); } - private Set orderWebFragments(Map fragments, - ServletContext servletContext) { + private Set orderWebFragments(Map fragments, ServletContext servletContext) { Set orderedFragments = new LinkedHashSet<>(); @@ -2139,7 +2104,7 @@ for (String requestedName : requestedOrder) { if (ORDER_OTHERS.equals(requestedName)) { // Add all fragments not named explicitly at this point - for (Entry entry : fragments.entrySet()) { + for (Entry entry : fragments.entrySet()) { if (!requestedOrder.contains(entry.getKey())) { WebXml fragment = entry.getValue(); if (fragment != null) { @@ -2152,7 +2117,7 @@ if (fragment != null) { orderedFragments.add(fragment); } else { - log.warn(sm.getString("webXml.wrongFragmentName",requestedName)); + log.warn(sm.getString("webXml.wrongFragmentName", requestedName)); } } } @@ -2167,10 +2132,9 @@ } } // Stage 1. Make all dependencies bidirectional - this makes the - // next stage simpler. + // next stage simpler. for (WebXml fragment : fragments.values()) { - Iterator before = - fragment.getBeforeOrdering().iterator(); + Iterator before = fragment.getBeforeOrdering().iterator(); while (before.hasNext()) { orderingPresent = true; String beforeEntry = before.next(); @@ -2199,8 +2163,8 @@ } // Stage 2. Make all fragments that are implicitly before/after - // others explicitly so. This is iterative so the next - // stage doesn't have to be. + // others explicitly so. This is iterative so the next + // stage doesn't have to be. for (WebXml fragment : fragments.values()) { if (fragment.getBeforeOrdering().contains(ORDER_OTHERS)) { makeBeforeOthersExplicit(fragment.getAfterOrdering(), fragments); @@ -2228,18 +2192,18 @@ } // Stage 4. Decouple the groups so the ordering requirements for - // each fragment in the group only refer to other fragments - // in the group. Ordering requirements outside the group - // will be handled by processing the groups in order. - // Note: Only after ordering requirements are considered. - // This is OK because of the processing in stage 1. + // each fragment in the group only refer to other fragments + // in the group. Ordering requirements outside the group + // will be handled by processing the groups in order. + // Note: Only after ordering requirements are considered. + // This is OK because of the processing in stage 1. decoupleOtherGroups(beforeSet); decoupleOtherGroups(othersSet); decoupleOtherGroups(afterSet); // Stage 5. Order each group - // Note: Only after ordering requirements are considered. - // This is OK because of the processing in stage 1. + // Note: Only after ordering requirements are considered. + // This is OK because of the processing in stage 1. orderFragments(orderedFragments, beforeSet); orderFragments(orderedFragments, othersSet); orderFragments(orderedFragments, afterSet); @@ -2263,12 +2227,11 @@ List orderedJarFileNames = null; if (orderingPresent) { orderedJarFileNames = new ArrayList<>(); - for (WebXml fragment: orderedFragments) { + for (WebXml fragment : orderedFragments) { orderedJarFileNames.add(fragment.getJarName()); } } - servletContext.setAttribute(ServletContext.ORDERED_LIBS, - orderedJarFileNames); + servletContext.setAttribute(ServletContext.ORDERED_LIBS, orderedJarFileNames); } // The remainder of the processing needs to know about container @@ -2297,8 +2260,8 @@ fragment.getAfterOrdering().removeIf(entry -> !names.contains(entry)); } } - private static void orderFragments(Set orderedFragments, - Set unordered) { + + private static void orderFragments(Set orderedFragments, Set unordered) { Set addedThisRound = new HashSet<>(); Set addedLastRound = new HashSet<>(); while (!unordered.isEmpty()) { @@ -2316,8 +2279,7 @@ } if (addedThisRound.isEmpty()) { // Circular - throw new IllegalArgumentException( - sm.getString("webXml.mergeConflictOrder")); + throw new IllegalArgumentException(sm.getString("webXml.mergeConflictOrder")); } addedLastRound.clear(); addedLastRound.addAll(addedThisRound); @@ -2325,8 +2287,7 @@ } } - private static void makeBeforeOthersExplicit(Set beforeOrdering, - Map fragments) { + private static void makeBeforeOthersExplicit(Set beforeOrdering, Map fragments) { for (String before : beforeOrdering) { if (!before.equals(ORDER_OTHERS)) { WebXml webXml = fragments.get(before); @@ -2338,8 +2299,7 @@ } } - private static void makeAfterOthersExplicit(Set afterOrdering, - Map fragments) { + private static void makeAfterOthersExplicit(Set afterOrdering, Map fragments) { for (String after : afterOrdering) { if (!after.equals(ORDER_OTHERS)) { WebXml webXml = fragments.get(after); diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/descriptor/web/WebXmlParser.java tomcat10-10.1.52/java/org/apache/tomcat/util/descriptor/web/WebXmlParser.java --- tomcat10-10.1.40/java/org/apache/tomcat/util/descriptor/web/WebXmlParser.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/descriptor/web/WebXmlParser.java 2026-01-23 19:33:36.000000000 +0000 @@ -36,44 +36,41 @@ /** * The string resources for this package. */ - private static final StringManager sm = - StringManager.getManager(Constants.PACKAGE_NAME); + private static final StringManager sm = StringManager.getManager(Constants.PACKAGE_NAME); /** - * The Digester we will use to process web application - * deployment descriptor files. + * The Digester we will use to process web application deployment descriptor files. */ private final Digester webDigester; private final WebRuleSet webRuleSet; /** - * The Digester we will use to process web fragment - * deployment descriptor files. + * The Digester we will use to process web fragment deployment descriptor files. */ private final Digester webFragmentDigester; private final WebRuleSet webFragmentRuleSet; - public WebXmlParser(boolean namespaceAware, boolean validation, - boolean blockExternal) { + public WebXmlParser(boolean namespaceAware, boolean validation, boolean blockExternal) { webRuleSet = new WebRuleSet(false); - webDigester = DigesterFactory.newDigester(validation, - namespaceAware, webRuleSet, blockExternal); + webDigester = DigesterFactory.newDigester(validation, namespaceAware, webRuleSet, blockExternal); webDigester.getParser(); webFragmentRuleSet = new WebRuleSet(true); - webFragmentDigester = DigesterFactory.newDigester(validation, - namespaceAware, webFragmentRuleSet, blockExternal); + webFragmentDigester = + DigesterFactory.newDigester(validation, namespaceAware, webFragmentRuleSet, blockExternal); webFragmentDigester.getParser(); } /** * Parse a web descriptor at a location. * - * @param url the location; if null no load will be attempted - * @param dest the instance to be populated by the parse operation + * @param url the location; if null no load will be attempted + * @param dest the instance to be populated by the parse operation * @param fragment indicate if the descriptor is a web-app or web-fragment + * * @return true if the descriptor was successfully parsed + * * @throws IOException if there was a problem reading from the URL */ public boolean parseWebXml(URL url, WebXml dest, boolean fragment) throws IOException { @@ -86,8 +83,7 @@ } - public boolean parseWebXml(InputSource source, WebXml dest, - boolean fragment) { + public boolean parseWebXml(InputSource source, WebXml dest, boolean fragment) { if (source == null) { return true; @@ -109,8 +105,7 @@ digester.setErrorHandler(handler); if (log.isDebugEnabled()) { - log.debug(sm.getString("webXmlParser.applicationStart", - source.getSystemId())); + log.debug(sm.getString("webXmlParser.applicationStart", source.getSystemId())); } boolean ok = true; @@ -118,21 +113,17 @@ try { digester.parse(source); - if (!handler.getWarnings().isEmpty() || - !handler.getErrors().isEmpty()) { + if (!handler.getWarnings().isEmpty() || !handler.getErrors().isEmpty()) { ok = false; handler.logFindings(log, source.getSystemId()); } } catch (SAXParseException e) { - log.error(sm.getString("webXmlParser.applicationParse", - source.getSystemId()), e); - log.error(sm.getString("webXmlParser.applicationPosition", - "" + e.getLineNumber(), - "" + e.getColumnNumber())); + log.error(sm.getString("webXmlParser.applicationParse", source.getSystemId()), e); + log.error( + sm.getString("webXmlParser.applicationPosition", "" + e.getLineNumber(), "" + e.getColumnNumber())); ok = false; } catch (Exception e) { - log.error(sm.getString("webXmlParser.applicationParse", - source.getSystemId()), e); + log.error(sm.getString("webXmlParser.applicationParse", source.getSystemId()), e); ok = false; } finally { InputSourceUtil.close(source); @@ -146,6 +137,7 @@ /** * Sets the ClassLoader to be used for creating descriptor objects. + * * @param classLoader the ClassLoader to be used for creating descriptor objects */ public void setClassLoader(ClassLoader classLoader) { diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/descriptor/web/XmlEncodingBase.java tomcat10-10.1.52/java/org/apache/tomcat/util/descriptor/web/XmlEncodingBase.java --- tomcat10-10.1.40/java/org/apache/tomcat/util/descriptor/web/XmlEncodingBase.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/descriptor/web/XmlEncodingBase.java 2026-01-23 19:33:36.000000000 +0000 @@ -20,8 +20,7 @@ import java.nio.charset.StandardCharsets; /** - * Base class for those elements that need to track the encoding used in the - * source XML. + * Base class for those elements that need to track the encoding used in the source XML. */ public abstract class XmlEncodingBase { @@ -34,11 +33,10 @@ /** - * Obtain the character encoding of the XML source that was used to - * populate this object. + * Obtain the character encoding of the XML source that was used to populate this object. * - * @return The character encoding of the associated XML source or - * UTF-8 if the encoding could not be determined + * @return The character encoding of the associated XML source or UTF-8 if the encoding could not be + * determined */ public Charset getCharset() { return charset; diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/digester/AbstractObjectCreationFactory.java tomcat10-10.1.52/java/org/apache/tomcat/util/digester/AbstractObjectCreationFactory.java --- tomcat10-10.1.40/java/org/apache/tomcat/util/digester/AbstractObjectCreationFactory.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/digester/AbstractObjectCreationFactory.java 2026-01-23 19:33:36.000000000 +0000 @@ -21,19 +21,18 @@ /** - *

      Abstract base class for ObjectCreationFactory - * implementations.

      + *

      + * Abstract base class for ObjectCreationFactory implementations. + *

      */ -public abstract class AbstractObjectCreationFactory - implements ObjectCreationFactory { +public abstract class AbstractObjectCreationFactory implements ObjectCreationFactory { // ----------------------------------------------------- Instance Variables /** - * The associated Digester instance that was set up by - * {@link FactoryCreateRule} upon initialization. + * The associated Digester instance that was set up by {@link FactoryCreateRule} upon initialization. */ private Digester digester = null; @@ -42,8 +41,8 @@ /** - *

      Factory method called by {@link FactoryCreateRule} to supply an - * object based on the element's attributes. + *

      + * Factory method called by {@link FactoryCreateRule} to supply an object based on the element's attributes. * * @param attributes the element's attributes * @@ -54,8 +53,8 @@ /** - *

      Returns the {@link Digester} that was set by the - * {@link FactoryCreateRule} upon initialization. + *

      + * Returns the {@link Digester} that was set by the {@link FactoryCreateRule} upon initialization. */ @Override public Digester getDigester() { @@ -64,8 +63,9 @@ /** - *

      Set the {@link Digester} to allow the implementation to do logging, - * classloading based on the digester's classloader, etc. + *

      + * Set the {@link Digester} to allow the implementation to do logging, classloading based on the digester's + * classloader, etc. * * @param digester parent Digester object */ diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/digester/ArrayStack.java tomcat10-10.1.52/java/org/apache/tomcat/util/digester/ArrayStack.java --- tomcat10-10.1.40/java/org/apache/tomcat/util/digester/ArrayStack.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/digester/ArrayStack.java 2026-01-23 19:33:36.000000000 +0000 @@ -20,27 +20,28 @@ import java.util.EmptyStackException; /** - *

      Imported copy of the ArrayStack class from - * Commons Collections, which was the only direct dependency from Digester.

      - * - *

      WARNING - This class is public solely to allow it to be - * used from subpackages of org.apache.commons.digester. - * It should not be considered part of the public API of Commons Digester. - * If you want to use such a class yourself, you should use the one from - * Commons Collections directly.

      - * - *

      An implementation of the {@link java.util.Stack} API that is based on an - * ArrayList instead of a Vector, so it is not - * synchronized to protect against multi-threaded access. The implementation - * is therefore operates faster in environments where you do not need to - * worry about multiple thread contention.

      - * - *

      Unlike Stack, ArrayStack accepts null entries. + *

      + * Imported copy of the ArrayStack class from Commons Collections, which was the only direct dependency + * from Digester. + *

      + *

      + * WARNING - This class is public solely to allow it to be used from subpackages of + * org.apache.commons.digester. It should not be considered part of the public API of Commons Digester. If + * you want to use such a class yourself, you should use the one from Commons Collections directly. + *

      + *

      + * An implementation of the {@link java.util.Stack} API that is based on an ArrayList instead of a + * Vector, so it is not synchronized to protect against multi-threaded access. The implementation is + * therefore operates faster in environments where you do not need to worry about multiple thread contention. + *

      + *

      + * Unlike Stack, ArrayStack accepts null entries. *

      * * @param Type of object in this stack * * @see java.util.Stack + * * @since Digester 1.6 (from Commons Collections 1.0) */ public class ArrayStack extends ArrayList { @@ -49,8 +50,8 @@ private static final long serialVersionUID = 2130079159931574599L; /** - * Constructs a new empty ArrayStack. The initial size - * is controlled by ArrayList and is currently 10. + * Constructs a new empty ArrayStack. The initial size is controlled by ArrayList and is + * currently 10. */ public ArrayStack() { super(); @@ -59,9 +60,9 @@ /** * Constructs a new empty ArrayStack with an initial size. * - * @param initialSize the initial size to use - * @throws IllegalArgumentException if the specified initial size - * is negative + * @param initialSize the initial size to use + * + * @throws IllegalArgumentException if the specified initial size is negative */ public ArrayStack(int initialSize) { super(initialSize); @@ -70,8 +71,8 @@ /** * Return true if this stack is currently empty. *

      - * This method exists for compatibility with java.util.Stack. - * New users of this class should use isEmpty instead. + * This method exists for compatibility with java.util.Stack. New users of this class should use + * isEmpty instead. * * @return true if the stack is currently empty */ @@ -83,7 +84,8 @@ * Returns the top item off of this stack without removing it. * * @return the top item on the stack - * @throws EmptyStackException if the stack is empty + * + * @throws EmptyStackException if the stack is empty */ public E peek() throws EmptyStackException { int n = size(); @@ -95,13 +97,13 @@ } /** - * Returns the n'th item down (zero-relative) from the top of this - * stack without removing it. + * Returns the n'th item down (zero-relative) from the top of this stack without removing it. + * + * @param n the number of items down to go * - * @param n the number of items down to go * @return the n'th item on the stack, zero relative - * @throws EmptyStackException if there are not enough items on the - * stack to satisfy this request + * + * @throws EmptyStackException if there are not enough items on the stack to satisfy this request */ public E peek(int n) throws EmptyStackException { int m = (size() - n) - 1; @@ -116,7 +118,8 @@ * Pops the top item off of this stack and return it. * * @return the top item on the stack - * @throws EmptyStackException if the stack is empty + * + * @throws EmptyStackException if the stack is empty */ public E pop() throws EmptyStackException { int n = size(); @@ -128,10 +131,11 @@ } /** - * Pushes a new item onto the top of this stack. The pushed item is also - * returned. This is equivalent to calling add. + * Pushes a new item onto the top of this stack. The pushed item is also returned. This is equivalent to calling + * add. + * + * @param item the item to be added * - * @param item the item to be added * @return the item just pushed */ public E push(E item) { diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/digester/CallMethodRule.java tomcat10-10.1.52/java/org/apache/tomcat/util/digester/CallMethodRule.java --- tomcat10-10.1.40/java/org/apache/tomcat/util/digester/CallMethodRule.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/digester/CallMethodRule.java 2026-01-23 19:33:36.000000000 +0000 @@ -22,56 +22,48 @@ import org.xml.sax.Attributes; /** - *

      Rule implementation that calls a method on an object on the stack - * (normally the top/parent object), passing arguments collected from - * subsequent CallParamRule rules or from the body of this - * element.

      - * - *

      By using {@link #CallMethodRule(String methodName)} - * a method call can be made to a method which accepts no - * arguments.

      - * - *

      Incompatible method parameter types are converted - * using org.apache.commons.beanutils.ConvertUtils. + *

      + * Rule implementation that calls a method on an object on the stack (normally the top/parent object), passing arguments + * collected from subsequent CallParamRule rules or from the body of this element. *

      - * - *

      This rule now uses + *

      + * By using {@link #CallMethodRule(String methodName)} a method call can be made to a method which accepts no arguments. + *

      + *

      + * Incompatible method parameter types are converted using org.apache.commons.beanutils.ConvertUtils. + *

      + *

      + * This rule now uses * - * org.apache.commons.beanutils.MethodUtils#invokeMethod - * by default. - * This increases the kinds of methods successfully and allows primitives - * to be matched by passing in wrapper classes. - * There are rare cases when org.apache.commons.beanutils.MethodUtils#invokeExactMethod - * (the old default) is required. - * This method is much stricter in its reflection. - * Setting the UseExactMatch to true reverts to the use of this - * method.

      - * - *

      Note that the target method is invoked when the end of - * the tag the CallMethodRule fired on is encountered, not when the - * last parameter becomes available. This implies that rules which fire on - * tags nested within the one associated with the CallMethodRule will - * fire before the CallMethodRule invokes the target method. This behaviour is - * not configurable.

      - * - *

      Note also that if a CallMethodRule is expecting exactly one parameter - * and that parameter is not available (e.g. CallParamRule is used with an - * attribute name but the attribute does not exist) then the method will - * not be invoked. If a CallMethodRule is expecting more than one parameter, - * then it is always invoked, regardless of whether the parameters were - * available or not (missing parameters are passed as null values).

      + * org.apache.commons.beanutils.MethodUtils#invokeMethod by default. This increases the kinds of methods + * successfully and allows primitives to be matched by passing in wrapper classes. There are rare cases when + * org.apache.commons.beanutils.MethodUtils#invokeExactMethod (the old default) is required. This method is much + * stricter in its reflection. Setting the UseExactMatch to true reverts to the use of this method. + *

      + *

      + * Note that the target method is invoked when the end of the tag the CallMethodRule fired on is encountered, + * not when the last parameter becomes available. This implies that rules which fire on tags nested within the + * one associated with the CallMethodRule will fire before the CallMethodRule invokes the target method. This behaviour + * is not configurable. + *

      + *

      + * Note also that if a CallMethodRule is expecting exactly one parameter and that parameter is not available (e.g. + * CallParamRule is used with an attribute name but the attribute does not exist) then the method will not be invoked. + * If a CallMethodRule is expecting more than one parameter, then it is always invoked, regardless of whether the + * parameters were available or not (missing parameters are passed as null values). + *

      */ public class CallMethodRule extends Rule { // ----------------------------------------------------------- Constructors /** - * Construct a "call method" rule with the specified method name. The - * parameter types (if any) default to java.lang.String. + * Construct a "call method" rule with the specified method name. The parameter types (if any) default to + * java.lang.String. * * @param methodName Method name of the parent method to call - * @param paramCount The number of parameters to collect, or - * zero for a single argument from the body of this element. + * @param paramCount The number of parameters to collect, or zero for a single argument from the body of this + * element. */ public CallMethodRule(String methodName, int paramCount) { this(0, methodName, paramCount); @@ -79,16 +71,15 @@ /** - * Construct a "call method" rule with the specified method name. The - * parameter types (if any) default to java.lang.String. + * Construct a "call method" rule with the specified method name. The parameter types (if any) default to + * java.lang.String. * - * @param targetOffset location of the target object. Positive numbers are - * relative to the top of the digester object stack. Negative numbers - * are relative to the bottom of the stack. Zero implies the top - * object on the stack. - * @param methodName Method name of the parent method to call - * @param paramCount The number of parameters to collect, or - * zero for a single argument from the body of this element. + * @param targetOffset location of the target object. Positive numbers are relative to the top of the digester + * object stack. Negative numbers are relative to the bottom of the stack. Zero implies the + * top object on the stack. + * @param methodName Method name of the parent method to call + * @param paramCount The number of parameters to collect, or zero for a single argument from the body of this + * element. */ public CallMethodRule(int targetOffset, String methodName, int paramCount) { this.targetOffset = targetOffset; @@ -104,8 +95,7 @@ /** - * Construct a "call method" rule with the specified method name. - * The method should accept no parameters. + * Construct a "call method" rule with the specified method name. The method should accept no parameters. * * @param methodName Method name of the parent method to call */ @@ -115,27 +105,21 @@ /** - * Construct a "call method" rule with the specified method name and - * parameter types. If paramCount is set to zero the rule - * will use the body of this element as the single argument of the - * method, unless paramTypes is null or empty, in this - * case the rule will call the specified method with no arguments. + * Construct a "call method" rule with the specified method name and parameter types. If paramCount is + * set to zero the rule will use the body of this element as the single argument of the method, unless + * paramTypes is null or empty, in this case the rule will call the specified method with no arguments. * - * @param targetOffset location of the target object. Positive numbers are - * relative to the top of the digester object stack. Negative numbers - * are relative to the bottom of the stack. Zero implies the top - * object on the stack. - * @param methodName Method name of the parent method to call - * @param paramCount The number of parameters to collect, or - * zero for a single argument from the body of this element - * @param paramTypes The Java classes that represent the - * parameter types of the method arguments - * (if you wish to use a primitive type, specify the corresponding - * Java wrapper class instead, such as java.lang.Boolean.TYPE - * for a boolean parameter) + * @param targetOffset location of the target object. Positive numbers are relative to the top of the digester + * object stack. Negative numbers are relative to the bottom of the stack. Zero implies the + * top object on the stack. + * @param methodName Method name of the parent method to call + * @param paramCount The number of parameters to collect, or zero for a single argument from the body of this + * element + * @param paramTypes The Java classes that represent the parameter types of the method arguments (if you wish to + * use a primitive type, specify the corresponding Java wrapper class instead, such as + * java.lang.Boolean.TYPE for a boolean parameter) */ - public CallMethodRule(int targetOffset, String methodName, int paramCount, - Class[] paramTypes) { + public CallMethodRule(int targetOffset, String methodName, int paramCount, Class[] paramTypes) { this.targetOffset = targetOffset; this.methodName = methodName; @@ -159,9 +143,8 @@ /** - * location of the target object for the call, relative to the - * top of the digester object stack. The default value of zero - * means the target object is the one on top of the stack. + * location of the target object for the call, relative to the top of the digester object stack. The default value + * of zero means the target object is the one on top of the stack. */ protected final int targetOffset; @@ -173,9 +156,8 @@ /** - * The number of parameters to collect from MethodParam rules. - * If this value is zero, a single parameter will be collected from the - * body of this element. + * The number of parameters to collect from MethodParam rules. If this value is zero, a single + * parameter will be collected from the body of this element. */ protected final int paramCount; @@ -195,8 +177,8 @@ // --------------------------------------------------------- Public Methods /** - * Should MethodUtils.invokeExactMethod - * be used for the reflection. + * Should MethodUtils.invokeExactMethod be used for the reflection. + * * @return true if invokeExactMethod is used */ public boolean getUseExactMatch() { @@ -205,8 +187,8 @@ /** - * Set whether MethodUtils.invokeExactMethod - * should be used for the reflection. + * Set whether MethodUtils.invokeExactMethod should be used for the reflection. + * * @param useExactMatch The flag value */ public void setUseExactMatch(boolean useExactMatch) { @@ -217,16 +199,13 @@ /** * Process the start of this element. * - * @param namespace the namespace URI of the matching element, or an - * empty string if the parser is not namespace aware or the element has - * no namespace - * @param name the local name if the parser is namespace aware, or just - * the element name otherwise + * @param namespace the namespace URI of the matching element, or an empty string if the parser is not namespace + * aware or the element has no namespace + * @param name the local name if the parser is namespace aware, or just the element name otherwise * @param attributes The attribute list for this element */ @Override - public void begin(String namespace, String name, Attributes attributes) - throws Exception { + public void begin(String namespace, String name, Attributes attributes) throws Exception { // Push an array to capture the parameter values if necessary if (paramCount > 0) { @@ -240,16 +219,13 @@ /** * Process the body text of this element. * - * @param namespace the namespace URI of the matching element, or an - * empty string if the parser is not namespace aware or the element has - * no namespace - * @param name the local name if the parser is namespace aware, or just - * the element name otherwise - * @param bodyText The body text of this element + * @param namespace the namespace URI of the matching element, or an empty string if the parser is not namespace + * aware or the element has no namespace + * @param name the local name if the parser is namespace aware, or just the element name otherwise + * @param bodyText The body text of this element */ @Override - public void body(String namespace, String name, String bodyText) - throws Exception { + public void body(String namespace, String name, String bodyText) throws Exception { if (paramCount == 0) { this.bodyText = bodyText.trim().intern(); @@ -261,11 +237,9 @@ /** * Process the end of this element. * - * @param namespace the namespace URI of the matching element, or an - * empty string if the parser is not namespace aware or the element has - * no namespace - * @param name the local name if the parser is namespace aware, or just - * the element name otherwise + * @param namespace the namespace URI of the matching element, or an empty string if the parser is not namespace + * aware or the element has no namespace + * @param name the local name if the parser is namespace aware, or just the element name otherwise */ @SuppressWarnings("null") // parameters can't trigger NPE @Override @@ -278,8 +252,8 @@ parameters = (Object[]) digester.popParams(); if (digester.log.isTraceEnabled()) { - for (int i=0,size=parameters.length;i= 0) { target = digester.peek(targetOffset); } else { - target = digester.peek( digester.getCount() + targetOffset ); + target = digester.peek(digester.getCount() + targetOffset); } if (target == null) { - String sb = "[CallMethodRule]{" + digester.match + "} Call target is null (" + - "targetOffset=" + targetOffset + ",stackdepth=" + digester.getCount() + ')'; + String sb = "[CallMethodRule]{" + digester.match + "} Call target is null (" + "targetOffset=" + + targetOffset + ",stackdepth=" + digester.getCount() + ')'; throw new org.xml.sax.SAXException(sb); } @@ -368,8 +340,7 @@ sb.append(')'); digester.log.trace(sb.toString()); } - Object result = IntrospectionUtils.callMethodN(target, methodName, - paramValues, paramTypes); + Object result = IntrospectionUtils.callMethodN(target, methodName, paramValues, paramTypes); processMethodCallResult(result); StringBuilder code = digester.getGeneratedCode(); @@ -404,8 +375,7 @@ /** - * Subclasses may override this method to perform additional processing of the - * invoked method's result. + * Subclasses may override this method to perform additional processing of the invoked method's result. * * @param result the Object returned by the method invoked, possibly null */ diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/digester/CallParamRule.java tomcat10-10.1.52/java/org/apache/tomcat/util/digester/CallParamRule.java --- tomcat10-10.1.40/java/org/apache/tomcat/util/digester/CallParamRule.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/digester/CallParamRule.java 2026-01-23 19:33:36.000000000 +0000 @@ -19,15 +19,15 @@ import org.xml.sax.Attributes; /** - *

      Rule implementation that saves a parameter for use by a surrounding - * CallMethodRule.

      - * - *

      This parameter may be:

      + *

      + * Rule implementation that saves a parameter for use by a surrounding CallMethodRule. + *

      + *

      + * This parameter may be: + *

      *
        - *
      • from an attribute of the current element - * See {@link #CallParamRule(int paramIndex, String attributeName)} - *
      • from current the element body - * See {@link #CallParamRule(int paramIndex)} + *
      • from an attribute of the current element See {@link #CallParamRule(int paramIndex, String attributeName)} + *
      • from current the element body See {@link #CallParamRule(int paramIndex)} *
      */ public class CallParamRule extends Rule { @@ -35,8 +35,7 @@ // ----------------------------------------------------------- Constructors /** - * Construct a "call parameter" rule that will save the body text of this - * element as the parameter value. + * Construct a "call parameter" rule that will save the body text of this element as the parameter value. * * @param paramIndex The zero-relative parameter number */ @@ -46,20 +45,17 @@ /** - * Construct a "call parameter" rule that will save the value of the - * specified attribute as the parameter value. + * Construct a "call parameter" rule that will save the value of the specified attribute as the parameter value. * - * @param paramIndex The zero-relative parameter number + * @param paramIndex The zero-relative parameter number * @param attributeName The name of the attribute to save */ - public CallParamRule(int paramIndex, - String attributeName) { + public CallParamRule(int paramIndex, String attributeName) { this(attributeName, paramIndex, 0, false); } - private CallParamRule(String attributeName, int paramIndex, int stackIndex, - boolean fromStack) { + private CallParamRule(String attributeName, int paramIndex, int stackIndex, boolean fromStack) { this.attributeName = attributeName; this.paramIndex = paramIndex; this.stackIndex = stackIndex; @@ -93,8 +89,7 @@ protected final int stackIndex; /** - * Stack is used to allow nested body text to be processed. - * Lazy creation. + * Stack is used to allow nested body text to be processed. Lazy creation. */ protected ArrayStack bodyTextStack; @@ -104,16 +99,13 @@ /** * Process the start of this element. * - * @param namespace the namespace URI of the matching element, or an - * empty string if the parser is not namespace aware or the element has - * no namespace - * @param name the local name if the parser is namespace aware, or just - * the element name otherwise + * @param namespace the namespace URI of the matching element, or an empty string if the parser is not namespace + * aware or the element has no namespace + * @param name the local name if the parser is namespace aware, or just the element name otherwise * @param attributes The attribute list for this element */ @Override - public void begin(String namespace, String name, Attributes attributes) - throws Exception { + public void begin(String namespace, String name, Attributes attributes) throws Exception { Object param = null; @@ -126,8 +118,7 @@ param = digester.peek(stackIndex); if (digester.log.isTraceEnabled()) { - String sb = "[CallParamRule]{" + digester.match + - "} Save from stack; from stack? " + true + + String sb = "[CallParamRule]{" + digester.match + "} Save from stack; from stack? " + true + "; object=" + param; digester.log.trace(sb); } @@ -139,7 +130,7 @@ // the instance variables will be overwritten // if this CallParamRule is reused in subsequent nesting. - if(param != null) { + if (param != null) { Object[] parameters = (Object[]) digester.peekParams(); parameters[paramIndex] = param; } @@ -149,16 +140,13 @@ /** * Process the body text of this element. * - * @param namespace the namespace URI of the matching element, or an - * empty string if the parser is not namespace aware or the element has - * no namespace - * @param name the local name if the parser is namespace aware, or just - * the element name otherwise - * @param bodyText The body text of this element + * @param namespace the namespace URI of the matching element, or an empty string if the parser is not namespace + * aware or the element has no namespace + * @param name the local name if the parser is namespace aware, or just the element name otherwise + * @param bodyText The body text of this element */ @Override - public void body(String namespace, String name, String bodyText) - throws Exception { + public void body(String namespace, String name, String bodyText) throws Exception { if (attributeName == null && !fromStack) { // We must wait to set the parameter until end @@ -189,8 +177,8 @@ */ @Override public String toString() { - return "CallParamRule[" + "paramIndex=" + paramIndex + ", attributeName=" + attributeName + - ", from stack=" + fromStack + ']'; + return "CallParamRule[" + "paramIndex=" + paramIndex + ", attributeName=" + attributeName + ", from stack=" + + fromStack + ']'; } diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/digester/Digester.java tomcat10-10.1.52/java/org/apache/tomcat/util/digester/Digester.java --- tomcat10-10.1.40/java/org/apache/tomcat/util/digester/Digester.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/digester/Digester.java 2026-01-23 19:33:36.000000000 +0000 @@ -63,23 +63,23 @@ /** - *

      A Digester processes an XML input stream by matching a - * series of element nesting patterns to execute Rules that have been added - * prior to the start of parsing. This package was inspired by the - * XmlMapper class that was part of Tomcat 3.0 and 3.1, - * but is organized somewhat differently.

      - * - *

      See the Digester - * Developer Guide for more information.

      - * - *

      IMPLEMENTATION NOTE - A single Digester instance may - * only be used within the context of a single thread at a time, and a call - * to parse() must be completed before another can be initiated - * even from the same thread.

      - * - *

      IMPLEMENTATION NOTE - A bug in Xerces 2.0.2 prevents - * the support of XML schema. You need Xerces 2.1/2.3 and up to make - * this class working with XML schema

      + *

      + * A Digester processes an XML input stream by matching a series of element nesting patterns to execute + * Rules that have been added prior to the start of parsing. This package was inspired by the XmlMapper + * class that was part of Tomcat 3.0 and 3.1, but is organized somewhat differently. + *

      + *

      + * See the Digester Developer Guide for more information. + *

      + *

      + * IMPLEMENTATION NOTE - A single Digester instance may only be used within the context of a single + * thread at a time, and a call to parse() must be completed before another can be initiated even from the + * same thread. + *

      + *

      + * IMPLEMENTATION NOTE - A bug in Xerces 2.0.2 prevents the support of XML schema. You need Xerces + * 2.1/2.3 and up to make this class working with XML schema + *

      */ public class Digester extends DefaultHandler2 { @@ -106,7 +106,8 @@ break; } catch (Throwable t) { ExceptionUtils.handleThrowable(t); - LogFactory.getLog(Digester.class).error(sm.getString("digester.propertySourceLoadError", className), t); + LogFactory.getLog(Digester.class) + .error(sm.getString("digester.propertySourceLoadError", className), t); } } } @@ -188,11 +189,9 @@ /** - * Stack whose elements are List objects, each containing a list of - * Rule objects as returned from Rules.getMatch(). As each xml element - * in the input is entered, the matching rules are pushed onto this - * stack. After the end tag is reached, the matches are popped again. - * The depth of is stack is therefore exactly the same as the current + * Stack whose elements are List objects, each containing a list of Rule objects as returned from Rules.getMatch(). + * As each xml element in the input is entered, the matching rules are pushed onto this stack. After the end tag is + * reached, the matches are popped again. The depth of is stack is therefore exactly the same as the current * "nesting" level of the input xml. * * @since 1.6 @@ -200,10 +199,9 @@ protected ArrayStack> matches = new ArrayStack<>(10); /** - * The class loader to use for instantiating application objects. - * If not specified, the context class loader, or the class loader - * used to load Digester itself, is used, based on the value of the - * useContextClassLoader variable. + * The class loader to use for instantiating application objects. If not specified, the context class loader, or the + * class loader used to load Digester itself, is used, based on the value of the useContextClassLoader + * variable. */ protected ClassLoader classLoader = null; @@ -220,15 +218,13 @@ protected EntityResolver entityResolver; /** - * The URLs of entityValidator that have been registered, keyed by the public - * identifier that corresponds. + * The URLs of entityValidator that have been registered, keyed by the public identifier that corresponds. */ - protected HashMap entityValidator = new HashMap<>(); + protected HashMap entityValidator = new HashMap<>(); /** - * The application-supplied error handler that is notified when parsing - * warnings, errors, or fatal errors occur. + * The application-supplied error handler that is notified when parsing warnings, errors, or fatal errors occur. */ protected ErrorHandler errorHandler = null; @@ -257,19 +253,16 @@ /** - * Registered namespaces we are currently processing. The key is the - * namespace prefix that was declared in the document. The value is an - * ArrayStack of the namespace URIs this prefix has been mapped to -- - * the top Stack element is the most current one. (This architecture - * is required because documents can declare nested uses of the same - * prefix for different Namespace URIs). + * Registered namespaces we are currently processing. The key is the namespace prefix that was declared in the + * document. The value is an ArrayStack of the namespace URIs this prefix has been mapped to -- the top Stack + * element is the most current one. (This architecture is required because documents can declare nested uses of the + * same prefix for different Namespace URIs). */ - protected HashMap> namespaces = new HashMap<>(); + protected HashMap> namespaces = new HashMap<>(); /** - * The parameters stack being utilized by CallMethodRule and - * CallParamRule rules. + * The parameters stack being utilized by CallMethodRule and CallParamRule rules. */ protected ArrayStack params = new ArrayStack<>(); @@ -281,8 +274,7 @@ /** - * The public identifier of the DTD we are currently parsing under - * (if any). + * The public identifier of the DTD we are currently parsing under (if any). */ protected String publicId = null; @@ -294,17 +286,14 @@ /** - * The "root" element of the stack (in other words, the last object - * that was popped). + * The "root" element of the stack (in other words, the last object that was popped). */ protected Object root = null; /** - * The Rules implementation containing our collection of - * Rule instances and associated matching policy. If not - * established before the first rule is added, a default implementation - * will be provided. + * The Rules implementation containing our collection of Rule instances and associated + * matching policy. If not established before the first rule is added, a default implementation will be provided. */ protected Rules rules = null; @@ -315,8 +304,8 @@ /** - * Do we want to use the Context ClassLoader when loading classes - * for instantiating new objects. Default is false. + * Do we want to use the Context ClassLoader when loading classes for instantiating new objects. Default is + * false. */ protected boolean useContextClassLoader = false; @@ -336,7 +325,7 @@ /** * Fake attributes map (attributes are often used for object creation). */ - protected Map, List> fakeAttributes = null; + protected Map,List> fakeAttributes = null; /** @@ -409,9 +398,11 @@ } protected ArrayList known = new ArrayList<>(); + public void setKnown(Object object) { known.add(object); } + public String toVariableName(Object object) { boolean found = false; int pos = 0; @@ -434,11 +425,11 @@ // ------------------------------------------------------------- Properties /** - * Return the currently mapped namespace URI for the specified prefix, - * if any; otherwise return null. These mappings come and - * go dynamically as the document is parsed. + * Return the currently mapped namespace URI for the specified prefix, if any; otherwise return null. + * These mappings come and go dynamically as the document is parsed. * * @param prefix Prefix to look up + * * @return the namespace URI */ public String findNamespaceURI(String prefix) { @@ -455,14 +446,15 @@ /** - * Return the class loader to be used for instantiating application objects - * when required. This is determined based upon the following rules: + * Return the class loader to be used for instantiating application objects when required. This is determined based + * upon the following rules: *
        *
      • The class loader set by setClassLoader(), if any
      • - *
      • The thread context class loader, if it exists and the - * useContextClassLoader property is set to true
      • + *
      • The thread context class loader, if it exists and the useContextClassLoader property is set to + * true
      • *
      • The class loader used to load the Digester class itself. *
      + * * @return the classloader */ public ClassLoader getClassLoader() { @@ -480,11 +472,9 @@ /** - * Set the class loader to be used for instantiating application objects - * when required. + * Set the class loader to be used for instantiating application objects when required. * - * @param classLoader The new class loader to use, or null - * to revert to the standard rules + * @param classLoader The new class loader to use, or null to revert to the standard rules */ public void setClassLoader(ClassLoader classLoader) { this.classLoader = classLoader; @@ -532,13 +522,15 @@ /** * SAX parser factory method. + * * @return the SAXParserFactory we will use, creating one if necessary. + * * @throws ParserConfigurationException Error creating parser - * @throws SAXNotSupportedException Error creating parser - * @throws SAXNotRecognizedException Error creating parser + * @throws SAXNotSupportedException Error creating parser + * @throws SAXNotRecognizedException Error creating parser */ - public SAXParserFactory getFactory() throws SAXNotRecognizedException, SAXNotSupportedException, - ParserConfigurationException { + public SAXParserFactory getFactory() + throws SAXNotRecognizedException, SAXNotSupportedException, ParserConfigurationException { if (factory == null) { factory = SAXParserFactory.newInstance(); @@ -562,27 +554,22 @@ /** - * Sets a flag indicating whether the requested feature is supported - * by the underlying implementation of org.xml.sax.XMLReader. - * See - * http://www.saxproject.org/apidoc/xml/sax/package-summary.html#package-description - * for information about the standard SAX2 feature flags. In order to be - * effective, this method must be called before the - * getParser() method is called for the first time, either - * directly or indirectly. + * Sets a flag indicating whether the requested feature is supported by the underlying implementation of + * org.xml.sax.XMLReader. See + * + * http://www.saxproject.org/apidoc/xml/sax/package-summary.html#package-description for information about the + * standard SAX2 feature flags. In order to be effective, this method must be called before the + * getParser() method is called for the first time, either directly or indirectly. * * @param feature Name of the feature to set the status for - * @param value The new value for this feature + * @param value The new value for this feature * - * @exception ParserConfigurationException if a parser configuration error - * occurs - * @exception SAXNotRecognizedException if the property name is - * not recognized - * @exception SAXNotSupportedException if the property name is - * recognized but not supported + * @exception ParserConfigurationException if a parser configuration error occurs + * @exception SAXNotRecognizedException if the property name is not recognized + * @exception SAXNotSupportedException if the property name is recognized but not supported */ - public void setFeature(String feature, boolean value) throws ParserConfigurationException, - SAXNotRecognizedException, SAXNotSupportedException { + public void setFeature(String feature, boolean value) + throws ParserConfigurationException, SAXNotRecognizedException, SAXNotSupportedException { getFactory().setFeature(feature, value); @@ -601,6 +588,7 @@ /** * Set the current logger for this Digester. + * * @param log The logger that will be used */ public void setLogger(Log log) { @@ -610,10 +598,10 @@ } /** - * Gets the logger used for logging SAX-related information. - * Note the output is finely grained. + * Gets the logger used for logging SAX-related information. Note the output is finely grained. * * @since 1.6 + * * @return the SAX logger */ public Log getSAXLogger() { @@ -623,8 +611,8 @@ /** - * Sets the logger used for logging SAX-related information. - * Note the output is finely grained. + * Sets the logger used for logging SAX-related information. Note the output is finely grained. + * * @param saxLog Log, not null * * @since 1.6 @@ -664,6 +652,7 @@ /** * Set the public id of the current file being parsed. + * * @param publicId the DTD/Schema public's id. */ public void setPublicId(String publicId) { @@ -672,8 +661,7 @@ /** - * @return the public identifier of the DTD we are currently - * parsing under, if any. + * @return the public identifier of the DTD we are currently parsing under, if any. */ public String getPublicId() { return this.publicId; @@ -681,8 +669,8 @@ /** - * @return the SAXParser we will use to parse the input stream. If there - * is a problem creating the parser, return null. + * @return the SAXParser we will use to parse the input stream. If there is a problem creating the parser, return + * null. */ public SAXParser getParser() { @@ -704,30 +692,28 @@ /** - * Return the current value of the specified property for the underlying - * XMLReader implementation. - * See - * http://www.saxproject.org/apidoc/xml/sax/package-summary.html#package-description - * for information about the standard SAX2 properties. + * Return the current value of the specified property for the underlying XMLReader implementation. See + * + * http://www.saxproject.org/apidoc/xml/sax/package-summary.html#package-description for information about the + * standard SAX2 properties. * * @param property Property name to be retrieved + * * @return the property value - * @exception SAXNotRecognizedException if the property name is - * not recognized - * @exception SAXNotSupportedException if the property name is - * recognized but not supported + * + * @exception SAXNotRecognizedException if the property name is not recognized + * @exception SAXNotSupportedException if the property name is recognized but not supported */ - public Object getProperty(String property) - throws SAXNotRecognizedException, SAXNotSupportedException { + public Object getProperty(String property) throws SAXNotRecognizedException, SAXNotSupportedException { return getParser().getProperty(property); } /** - * Return the Rules implementation object containing our - * rules collection and associated matching policy. If none has been - * established, a default implementation will be created and returned. + * Return the Rules implementation object containing our rules collection and associated matching + * policy. If none has been established, a default implementation will be created and returned. + * * @return the rules */ public Rules getRules() { @@ -740,8 +726,7 @@ /** - * Set the Rules implementation object containing our - * rules collection and associated matching policy. + * Set the Rules implementation object containing our rules collection and associated matching policy. * * @param rules New Rules implementation */ @@ -760,11 +745,9 @@ /** - * Determine whether to use the Context ClassLoader (the one found by - * calling Thread.currentThread().getContextClassLoader()) - * to resolve/load classes that are defined in various rules. If not - * using Context ClassLoader, then the class-loading defaults to - * using the calling class' ClassLoader. + * Determine whether to use the Context ClassLoader (the one found by calling + * Thread.currentThread().getContextClassLoader()) to resolve/load classes that are defined in various + * rules. If not using Context ClassLoader, then the class-loading defaults to using the calling class' ClassLoader. * * @param use determines whether to use Context ClassLoader. */ @@ -784,8 +767,7 @@ /** - * Set the validating parser flag. This must be called before - * parse() is called the first time. + * Set the validating parser flag. This must be called before parse() is called the first time. * * @param validating The new validating parser flag. */ @@ -803,8 +785,7 @@ /** - * Set the rules validation flag. This must be called before - * parse() is called the first time. + * Set the rules validation flag. This must be called before parse() is called the first time. * * @param rulesValidation The new rules validation flag. */ @@ -816,15 +797,17 @@ /** * @return the fake attributes list. */ - public Map, List> getFakeAttributes() { + public Map,List> getFakeAttributes() { return this.fakeAttributes; } /** * Determine if an attribute is a fake attribute. + * * @param object The object - * @param name The attribute name + * @param name The attribute name + * * @return true if this is a fake attribute */ public boolean isFakeAttribute(Object object, String name) { @@ -848,7 +831,7 @@ * * @param fakeAttributes The new fake attributes. */ - public void setFakeAttributes(Map, List> fakeAttributes) { + public void setFakeAttributes(Map,List> fakeAttributes) { this.fakeAttributes = fakeAttributes; @@ -856,10 +839,11 @@ /** - * Return the XMLReader to be used for parsing the input document. - * FIX ME: there is a bug in JAXP/XERCES that prevent the use of a - * parser that contains a schema with a DTD. + * Return the XMLReader to be used for parsing the input document. FIX ME: there is a bug in JAXP/XERCES that + * prevent the use of a parser that contains a schema with a DTD. + * * @return the XML reader + * * @exception SAXException if no XMLReader can be instantiated */ public XMLReader getXMLReader() throws SAXException { @@ -894,11 +878,10 @@ /** - * Process notification of character data received from the body of - * an XML element. + * Process notification of character data received from the body of an XML element. * * @param buffer The characters from the XML document - * @param start Starting offset into the buffer + * @param start Starting offset into the buffer * @param length Number of characters from the buffer * * @exception SAXException if a parsing error is to be reported @@ -957,18 +940,17 @@ /** * Process notification of the end of an XML element being reached. * - * @param namespaceURI - The Namespace URI, or the empty string if the - * element has no Namespace URI or if Namespace processing is not - * being performed. - * @param localName - The local name (without prefix), or the empty - * string if Namespace processing is not being performed. - * @param qName - The qualified XML 1.0 name (with prefix), or the - * empty string if qualified names are not available. + * @param namespaceURI - The Namespace URI, or the empty string if the element has no Namespace URI or if Namespace + * processing is not being performed. + * @param localName - The local name (without prefix), or the empty string if Namespace processing is not being + * performed. + * @param qName - The qualified XML 1.0 name (with prefix), or the empty string if qualified names are not + * available. + * * @exception SAXException if a parsing error is to be reported */ @Override - public void endElement(String namespaceURI, String localName, String qName) - throws SAXException { + public void endElement(String namespaceURI, String localName, String qName) throws SAXException { boolean debug = log.isTraceEnabled(); @@ -1083,12 +1065,11 @@ /** - * Process notification of ignorable whitespace received from the body of - * an XML element. + * Process notification of ignorable whitespace received from the body of an XML element. * * @param buffer The characters from the XML document - * @param start Starting offset into the buffer - * @param len Number of characters from the buffer + * @param start Starting offset into the buffer + * @param len Number of characters from the buffer * * @exception SAXException if a parsing error is to be reported */ @@ -1108,7 +1089,7 @@ * Process notification of a processing instruction that was encountered. * * @param target The processing instruction target - * @param data The processing instruction data (if any) + * @param data The processing instruction data (if any) * * @exception SAXException if a parsing error is to be reported */ @@ -1206,19 +1187,18 @@ /** * Process notification of the start of an XML element being reached. * - * @param namespaceURI The Namespace URI, or the empty string if the element - * has no Namespace URI or if Namespace processing is not being performed. - * @param localName The local name (without prefix), or the empty - * string if Namespace processing is not being performed. - * @param qName The qualified name (with prefix), or the empty - * string if qualified names are not available.\ - * @param list The attributes attached to the element. If there are - * no attributes, it shall be an empty Attributes object. + * @param namespaceURI The Namespace URI, or the empty string if the element has no Namespace URI or if Namespace + * processing is not being performed. + * @param localName The local name (without prefix), or the empty string if Namespace processing is not being + * performed. + * @param qName The qualified name (with prefix), or the empty string if qualified names are not available.\ + * @param list The attributes attached to the element. If there are no attributes, it shall be an empty + * Attributes object. + * * @exception SAXException if a parsing error is to be reported */ @Override - public void startElement(String namespaceURI, String localName, String qName, Attributes list) - throws SAXException { + public void startElement(String namespaceURI, String localName, String qName, Attributes list) throws SAXException { boolean debug = log.isTraceEnabled(); if (saxLog.isTraceEnabled()) { @@ -1286,7 +1266,7 @@ /** * Process notification that a namespace prefix is coming in to scope. * - * @param prefix Prefix that is being declared + * @param prefix Prefix that is being declared * @param namespaceURI Corresponding namespace URI being mapped to * * @exception SAXException if a parsing error is to be reported @@ -1315,7 +1295,7 @@ /** * Receive notification of a notation declaration event. * - * @param name The notation name + * @param name The notation name * @param publicId The public identifier (if any) * @param systemId The system identifier (if any) */ @@ -1332,7 +1312,7 @@ /** * Receive notification of an unparsed entity declaration event. * - * @param name The unparsed entity name + * @param name The unparsed entity name * @param publicId The public identifier (if any) * @param systemId The system identifier (if any) * @param notation The name of the associated notation @@ -1341,8 +1321,7 @@ public void unparsedEntityDecl(String name, String publicId, String systemId, String notation) { if (saxLog.isTraceEnabled()) { - saxLog.trace("unparsedEntityDecl(" + name + "," + publicId + "," + systemId + "," - + notation + ")"); + saxLog.trace("unparsedEntityDecl(" + name + "," + publicId + "," + systemId + "," + notation + ")"); } } @@ -1351,9 +1330,9 @@ // ----------------------------------------------- EntityResolver Methods /** - * Set the EntityResolver used by SAX when resolving - * public id and system id. - * This must be called before the first call to parse(). + * Set the EntityResolver used by SAX when resolving public id and system id. This must be called + * before the first call to parse(). + * * @param entityResolver a class that implement the EntityResolver interface. */ public void setEntityResolver(EntityResolver entityResolver) { @@ -1363,6 +1342,7 @@ /** * Return the Entity Resolver used by the SAX parser. + * * @return Return the Entity Resolver used by the SAX parser. */ public EntityResolver getEntityResolver() { @@ -1374,8 +1354,7 @@ throws SAXException, IOException { if (saxLog.isTraceEnabled()) { - saxLog.trace( - "resolveEntity('" + publicId + "', '" + systemId + "', '" + baseURI + "')"); + saxLog.trace("resolveEntity('" + publicId + "', '" + systemId + "', '" + baseURI + "')"); } // Has this system identifier been registered? @@ -1407,7 +1386,7 @@ } } catch (URISyntaxException e) { if (log.isDebugEnabled()) { - log.debug(sm.getString("digester.invalidURI", baseURI, systemId)); + log.debug(sm.getString("digester.invalidURI", baseURI, systemId), e); } } } @@ -1438,8 +1417,7 @@ // ------------------------------------------------- ErrorHandler Methods /** - * Forward notification of a parsing error to the application supplied - * error handler (if any). + * Forward notification of a parsing error to the application supplied error handler (if any). * * @param exception The error information * @@ -1456,8 +1434,7 @@ /** - * Forward notification of a fatal parsing error to the application - * supplied error handler (if any). + * Forward notification of a fatal parsing error to the application supplied error handler (if any). * * @param exception The fatal error information * @@ -1474,8 +1451,7 @@ /** - * Forward notification of a parse warning to the application supplied - * error handler (if any). + * Forward notification of a parse warning to the application supplied error handler (if any). * * @param exception The warning information * @@ -1495,12 +1471,14 @@ // ------------------------------------------------------- Public Methods /** - * Parse the content of the specified file using this Digester. Returns - * the root element from the object stack (if any). + * Parse the content of the specified file using this Digester. Returns the root element from the object stack (if + * any). * * @param file File containing the XML data to be parsed + * * @return the root object - * @exception IOException if an input/output error occurs + * + * @exception IOException if an input/output error occurs * @exception SAXException if a parsing exception occurs */ public Object parse(File file) throws IOException, SAXException { @@ -1513,12 +1491,14 @@ /** - * Parse the content of the specified input source using this Digester. - * Returns the root element from the object stack (if any). + * Parse the content of the specified input source using this Digester. Returns the root element from the object + * stack (if any). * * @param input Input source containing the XML data to be parsed + * * @return the root object - * @exception IOException if an input/output error occurs + * + * @exception IOException if an input/output error occurs * @exception SAXException if a parsing exception occurs */ public Object parse(InputSource input) throws IOException, SAXException { @@ -1529,12 +1509,14 @@ /** - * Parse the content of the specified input stream using this Digester. - * Returns the root element from the object stack (if any). + * Parse the content of the specified input stream using this Digester. Returns the root element from the object + * stack (if any). * * @param input Input stream containing the XML data to be parsed + * * @return the root object - * @exception IOException if an input/output error occurs + * + * @exception IOException if an input/output error occurs * @exception SAXException if a parsing exception occurs */ public Object parse(InputStream input) throws IOException, SAXException { @@ -1546,24 +1528,24 @@ /** - *

      Register the specified DTD URL for the specified public identifier. - * This must be called before the first call to parse(). - *

      - * Digester contains an internal EntityResolver - * implementation. This maps PUBLICID's to URLs - * (from which the resource will be loaded). A common use case for this - * method is to register local URLs (possibly computed at runtime by a - * classloader) for DTDs. This allows the performance advantage of using - * a local version without having to ensure every SYSTEM - * URI on every processed xml document is local. This implementation provides - * only basic functionality. If more sophisticated features are required, - * using {@link #setEntityResolver} to set a custom resolver is recommended. - *

      - * Note: This method will have no effect when a custom - * EntityResolver has been set. (Setting a custom - * EntityResolver overrides the internal implementation.) + *

      + * Register the specified DTD URL for the specified public identifier. This must be called before the first call to + * parse(). + *

      + *

      + * Digester contains an internal EntityResolver implementation. This maps + * PUBLICID's to URLs (from which the resource will be loaded). A common use case for this method is to + * register local URLs (possibly computed at runtime by a classloader) for DTDs. This allows the performance + * advantage of using a local version without having to ensure every SYSTEM URI on every processed xml + * document is local. This implementation provides only basic functionality. If more sophisticated features are + * required, using {@link #setEntityResolver} to set a custom resolver is recommended. *

      - * @param publicId Public identifier of the DTD to be resolved + *

      + * Note: This method will have no effect when a custom EntityResolver has been set. + * (Setting a custom EntityResolver overrides the internal implementation.) + *

      + * + * @param publicId Public identifier of the DTD to be resolved * @param entityURL The URL to use for reading this DTD */ public void register(String publicId, String entityURL) { @@ -1580,11 +1562,13 @@ /** - *

      Register a new Rule matching the specified pattern. - * This method sets the Digester property on the rule.

      + *

      + * Register a new Rule matching the specified pattern. This method sets the Digester property on the + * rule. + *

      * * @param pattern Element matching pattern - * @param rule Rule to be registered + * @param rule Rule to be registered */ public void addRule(String pattern, Rule rule) { @@ -1607,8 +1591,9 @@ /** * Add a "call method" rule for a method which accepts no arguments. * - * @param pattern Element matching pattern + * @param pattern Element matching pattern * @param methodName Method name to be called + * * @see CallMethodRule */ public void addCallMethod(String pattern, String methodName) { @@ -1620,10 +1605,10 @@ /** * Add a "call method" rule for the specified parameters. * - * @param pattern Element matching pattern + * @param pattern Element matching pattern * @param methodName Method name to be called - * @param paramCount Number of expected parameters (or zero - * for a single parameter from the body of this element) + * @param paramCount Number of expected parameters (or zero for a single parameter from the body of this element) + * * @see CallMethodRule */ public void addCallMethod(String pattern, String methodName, int paramCount) { @@ -1636,9 +1621,9 @@ /** * Add a "call parameter" rule for the specified parameters. * - * @param pattern Element matching pattern - * @param paramIndex Zero-relative parameter index to set - * (from the body of this element) + * @param pattern Element matching pattern + * @param paramIndex Zero-relative parameter index to set (from the body of this element) + * * @see CallParamRule */ public void addCallParam(String pattern, int paramIndex) { @@ -1651,11 +1636,11 @@ /** * Add a "factory create" rule for the specified parameters. * - * @param pattern Element matching pattern - * @param creationFactory Previously instantiated ObjectCreationFactory - * to be utilized - * @param ignoreCreateExceptions when true any exceptions thrown during - * object creation will be ignored. + * @param pattern Element matching pattern + * @param creationFactory Previously instantiated ObjectCreationFactory to be utilized + * @param ignoreCreateExceptions when true any exceptions thrown during object creation will be + * ignored. + * * @see FactoryCreateRule */ public void addFactoryCreate(String pattern, ObjectCreationFactory creationFactory, @@ -1669,8 +1654,9 @@ /** * Add an "object create" rule for the specified parameters. * - * @param pattern Element matching pattern + * @param pattern Element matching pattern * @param className Java class name to be created + * * @see ObjectCreateRule */ public void addObjectCreate(String pattern, String className) { @@ -1683,10 +1669,10 @@ /** * Add an "object create" rule for the specified parameters. * - * @param pattern Element matching pattern - * @param className Default Java class name to be created - * @param attributeName Attribute name that optionally overrides - * the default Java class name to be created + * @param pattern Element matching pattern + * @param className Default Java class name to be created + * @param attributeName Attribute name that optionally overrides the default Java class name to be created + * * @see ObjectCreateRule */ public void addObjectCreate(String pattern, String className, String attributeName) { @@ -1699,12 +1685,12 @@ /** * Add a "set next" rule for the specified parameters. * - * @param pattern Element matching pattern + * @param pattern Element matching pattern * @param methodName Method name to call on the parent element - * @param paramType Java class name of the expected parameter type - * (if you wish to use a primitive type, specify the corresponding - * Java wrapper class instead, such as java.lang.Boolean - * for a boolean parameter) + * @param paramType Java class name of the expected parameter type (if you wish to use a primitive type, specify + * the corresponding Java wrapper class instead, such as java.lang.Boolean for a + * boolean parameter) + * * @see SetNextRule */ public void addSetNext(String pattern, String methodName, String paramType) { @@ -1718,6 +1704,7 @@ * Add a "set properties" rule for the specified parameters. * * @param pattern Element matching pattern + * * @see SetPropertiesRule */ public void addSetProperties(String pattern) { @@ -1740,10 +1727,9 @@ /** * Clear the current contents of the object stack. *

      - * Calling this method might allow another document of the same type - * to be correctly parsed. However, this method was not intended for this - * purpose. In general, a separate Digester object should be created for - * each document to be parsed. + * Calling this method might allow another document of the same type to be correctly parsed. However, this + * method was not intended for this purpose. In general, a separate Digester object should be created for each + * document to be parsed. */ public void clear() { @@ -1767,8 +1753,9 @@ /** - * Return the top object on the stack without removing it. If there are - * no objects on the stack, return null. + * Return the top object on the stack without removing it. If there are no objects on the stack, return + * null. + * * @return the top object */ public Object peek() { @@ -1782,12 +1769,11 @@ /** - * Return the n'th object down the stack, where 0 is the top element - * and [getCount()-1] is the bottom element. If the specified index - * is out of range, return null. + * Return the n'th object down the stack, where 0 is the top element and [getCount()-1] is the bottom element. If + * the specified index is out of range, return null. + * + * @param n Index of the desired element, where 0 is the top of the stack, 1 is the next element down, and so on. * - * @param n Index of the desired element, where 0 is the top of the stack, - * 1 is the next element down, and so on. * @return the specified object */ public Object peek(int n) { @@ -1801,8 +1787,9 @@ /** - * Pop the top object off of the stack, and return it. If there are - * no objects on the stack, return null. + * Pop the top object off of the stack, and return it. If there are no objects on the stack, return + * null. + * * @return the top object */ public Object pop() { @@ -1830,12 +1817,10 @@ } /** - * When the Digester is being used as a SAXContentHandler, - * this method allows you to access the root object that has been - * created after parsing. + * When the Digester is being used as a SAXContentHandler, this method allows you to access the root object that has + * been created after parsing. * - * @return the root object that has been created after parsing - * or null if the digester has not parsed any XML yet. + * @return the root object that has been created after parsing or null if the digester has not parsed any XML yet. */ public Object getRoot() { return root; @@ -1850,11 +1835,9 @@ /** *

      - * Provide a hook for lazy configuration of this Digester - * instance. The default implementation does nothing, but subclasses - * can override as needed. + * Provide a hook for lazy configuration of this Digester instance. The default implementation does + * nothing, but subclasses can override as needed. *

      - * *

      * Note This method may be called more than once. *

      @@ -1875,11 +1858,14 @@ /** - *

      Return the top object on the parameters stack without removing it. If there are - * no objects on the stack, return null.

      + *

      + * Return the top object on the parameters stack without removing it. If there are no objects on the stack, return + * null. + *

      + *

      + * The parameters stack is used to store CallMethodRule parameters. See {@link #params}. + *

      * - *

      The parameters stack is used to store CallMethodRule parameters. - * See {@link #params}.

      * @return the top object on the parameters stack */ public Object peekParams() { @@ -1893,11 +1879,14 @@ /** - *

      Pop the top object off of the parameters stack, and return it. If there are - * no objects on the stack, return null.

      + *

      + * Pop the top object off of the parameters stack, and return it. If there are no objects on the stack, return + * null. + *

      + *

      + * The parameters stack is used to store CallMethodRule parameters. See {@link #params}. + *

      * - *

      The parameters stack is used to store CallMethodRule parameters. - * See {@link #params}.

      * @return the top object on the parameters stack */ public Object popParams() { @@ -1914,10 +1903,12 @@ /** - *

      Push a new object onto the top of the parameters stack.

      - * - *

      The parameters stack is used to store CallMethodRule parameters. - * See {@link #params}.

      + *

      + * Push a new object onto the top of the parameters stack. + *

      + *

      + * The parameters stack is used to store CallMethodRule parameters. See {@link #params}. + *

      * * @param object The new object */ @@ -1930,10 +1921,11 @@ } /** - * Create a SAX exception which also understands about the location in - * the digester file where the exception occurs + * Create a SAX exception which also understands about the location in the digester file where the exception occurs + * * @param message The error message - * @param e The root cause + * @param e The root cause + * * @return the new exception */ public SAXException createSAXException(String message, Exception e) { @@ -1950,8 +1942,7 @@ } } if (locator != null) { - String error = sm.getString("digester.errorLocation", - Integer.valueOf(locator.getLineNumber()), + String error = sm.getString("digester.errorLocation", Integer.valueOf(locator.getLineNumber()), Integer.valueOf(locator.getColumnNumber()), message); if (e != null) { return new SAXParseException(error, locator, e); @@ -1968,9 +1959,10 @@ } /** - * Create a SAX exception which also understands about the location in - * the digester file where the exception occurs + * Create a SAX exception which also understands about the location in the digester file where the exception occurs + * * @param e The root cause + * * @return the new exception */ public SAXException createSAXException(Exception e) { @@ -1990,9 +1982,10 @@ } /** - * Create a SAX exception which also understands about the location in - * the digester file where the exception occurs + * Create a SAX exception which also understands about the location in the digester file where the exception occurs + * * @param message The error message + * * @return the new exception */ public SAXException createSAXException(String message) { @@ -2003,10 +1996,9 @@ // ------------------------------------------------------- Private Methods - /** - * Returns an attributes list which contains all the attributes - * passed in, with any text of form "${xxx}" in an attribute value - * replaced by the appropriate value from the system property. + /** + * Returns an attributes list which contains all the attributes passed in, with any text of form "${xxx}" in an + * attribute value replaced by the appropriate value from the system property. */ private Attributes updateAttributes(Attributes list) { @@ -2019,7 +2011,8 @@ for (int i = 0; i < nAttributes; ++i) { String value = newAttrs.getValue(i); try { - newAttrs.setValue(i, IntrospectionUtils.replaceProperties(value, null, source, getClassLoader()).intern()); + newAttrs.setValue(i, + IntrospectionUtils.replaceProperties(value, null, source, getClassLoader()).intern()); } catch (Exception e) { log.warn(sm.getString("digester.failedToUpdateAttributes", newAttrs.getLocalName(i), value), e); } @@ -2030,9 +2023,8 @@ /** - * Return a new StringBuilder containing the same contents as the - * input buffer, except that data of form ${varname} have been - * replaced by the value of that var as defined in the system property. + * Return a new StringBuilder containing the same contents as the input buffer, except that data of form ${varname} + * have been replaced by the value of that var as defined in the system property. */ private StringBuilder updateBodyText(StringBuilder bodyText) { String in = bodyText.toString(); @@ -2066,8 +2058,7 @@ } @Override - public InputSource resolveEntity(String publicId, String systemId) - throws SAXException, IOException { + public InputSource resolveEntity(String publicId, String systemId) throws SAXException, IOException { publicId = replace(publicId); systemId = replace(systemId); return entityResolver.resolveEntity(publicId, systemId); @@ -2087,23 +2078,21 @@ private final EntityResolver2 entityResolver2; - EntityResolver2Wrapper(EntityResolver2 entityResolver, PropertySource[] source, - ClassLoader classLoader) { + EntityResolver2Wrapper(EntityResolver2 entityResolver, PropertySource[] source, ClassLoader classLoader) { super(entityResolver, source, classLoader); this.entityResolver2 = entityResolver; } @Override - public InputSource getExternalSubset(String name, String baseURI) - throws SAXException, IOException { + public InputSource getExternalSubset(String name, String baseURI) throws SAXException, IOException { name = replace(name); baseURI = replace(baseURI); return entityResolver2.getExternalSubset(name, baseURI); } @Override - public InputSource resolveEntity(String name, String publicId, String baseURI, - String systemId) throws SAXException, IOException { + public InputSource resolveEntity(String name, String publicId, String baseURI, String systemId) + throws SAXException, IOException { name = replace(name); publicId = replace(publicId); baseURI = replace(baseURI); diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/digester/DocumentProperties.java tomcat10-10.1.52/java/org/apache/tomcat/util/digester/DocumentProperties.java --- tomcat10-10.1.40/java/org/apache/tomcat/util/digester/DocumentProperties.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/digester/DocumentProperties.java 2026-01-23 19:33:36.000000000 +0000 @@ -17,10 +17,8 @@ package org.apache.tomcat.util.digester; /** - * A collection of interfaces, one per property, that enables the object being - * populated by the digester to signal to the digester that it supports the - * given property and that the digester should populate that property if - * available. + * A collection of interfaces, one per property, that enables the object being populated by the digester to signal to + * the digester that it supports the given property and that the digester should populate that property if available. */ public interface DocumentProperties { diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/digester/EnvironmentPropertySource.java tomcat10-10.1.52/java/org/apache/tomcat/util/digester/EnvironmentPropertySource.java --- tomcat10-10.1.40/java/org/apache/tomcat/util/digester/EnvironmentPropertySource.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/digester/EnvironmentPropertySource.java 2026-01-23 19:33:36.000000000 +0000 @@ -22,11 +22,11 @@ import org.apache.tomcat.util.security.PermissionCheck; /** - * A {@link org.apache.tomcat.util.IntrospectionUtils.SecurePropertySource} - * that uses environment variables to resolve expressions. - * - *

      Usage example:

      - * + * A {@link org.apache.tomcat.util.IntrospectionUtils.SecurePropertySource} that uses environment variables to resolve + * expressions. + *

      + * Usage example: + *

      * Configure the certificate with environment variables. * *
      @@ -40,10 +40,12 @@
        * 
      * * How to configure: + * *
        * {@code
        *   echo "org.apache.tomcat.util.digester.PROPERTY_SOURCE=org.apache.tomcat.util.digester.EnvironmentPropertySource" >> conf/catalina.properties}
        * 
      + * * or add this to {@code CATALINA_OPTS} * *
      @@ -51,12 +53,11 @@
        *   -Dorg.apache.tomcat.util.digester.PROPERTY_SOURCE=org.apache.tomcat.util.digester.EnvironmentPropertySource}
        * 
      * - * NOTE: When configured the PropertySource for resolving expressions - * from system properties is still active. + * NOTE: When configured the PropertySource for resolving expressions from system properties is still active. * * @see Digester - * - * @see Tomcat Configuration Reference System Properties + * @see Tomcat + * Configuration Reference System Properties */ public class EnvironmentPropertySource implements IntrospectionUtils.SecurePropertySource { diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/digester/FactoryCreateRule.java tomcat10-10.1.52/java/org/apache/tomcat/util/digester/FactoryCreateRule.java --- tomcat10-10.1.40/java/org/apache/tomcat/util/digester/FactoryCreateRule.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/digester/FactoryCreateRule.java 2026-01-23 19:33:36.000000000 +0000 @@ -20,14 +20,14 @@ /** - *

      Rule implementation that uses an {@link ObjectCreationFactory} to create - * a new object which it pushes onto the object stack. When the element is - * complete, the object will be popped.

      - * - *

      This rule is intended in situations where the element's attributes are - * needed before the object can be created. A common scenario is for the - * ObjectCreationFactory implementation to use the attributes as parameters - * in a call to either a factory method or to a non-empty constructor. + *

      + * Rule implementation that uses an {@link ObjectCreationFactory} to create a new object which it pushes onto the object + * stack. When the element is complete, the object will be popped. + *

      + *

      + * This rule is intended in situations where the element's attributes are needed before the object can be created. A + * common scenario is for the ObjectCreationFactory implementation to use the attributes as parameters in a call to + * either a factory method or to a non-empty constructor. */ public class FactoryCreateRule extends Rule { @@ -43,16 +43,12 @@ // ----------------------------------------------------------- Constructors /** - * Construct a factory create rule using the given, already instantiated, - * {@link ObjectCreationFactory}. + * Construct a factory create rule using the given, already instantiated, {@link ObjectCreationFactory}. * - * @param creationFactory called on to create the object. - * @param ignoreCreateExceptions if true, exceptions thrown by the object - * creation factory will be ignored. + * @param creationFactory called on to create the object. + * @param ignoreCreateExceptions if true, exceptions thrown by the object creation factory will be ignored. */ - public FactoryCreateRule( - ObjectCreationFactory creationFactory, - boolean ignoreCreateExceptions) { + public FactoryCreateRule(ObjectCreationFactory creationFactory, boolean ignoreCreateExceptions) { this.creationFactory = creationFactory; this.ignoreCreateExceptions = ignoreCreateExceptions; @@ -62,9 +58,8 @@ // ----------------------------------------------------- Instance Variables /** - * The object creation factory we will use to instantiate objects - * as required based on the attributes specified in the matched XML - * element. + * The object creation factory we will use to instantiate objects as required based on the attributes specified in + * the matched XML element. */ protected ObjectCreationFactory creationFactory; @@ -90,8 +85,8 @@ Object instance = creationFactory.createObject(attributes); if (digester.log.isTraceEnabled()) { - digester.log.trace("[FactoryCreateRule]{" + digester.match + - "} New " + instance.getClass().getName()); + digester.log + .trace("[FactoryCreateRule]{" + digester.match + "} New " + instance.getClass().getName()); } digester.push(instance); exceptionIgnoredStack.push(Boolean.FALSE); @@ -103,7 +98,7 @@ ((e.getMessage() == null) ? e.getClass().getName() : e.getMessage())), e); } else if (digester.log.isInfoEnabled()) { digester.log.info(sm.getString("rule.createError", - ((e.getMessage() == null) ? e.getClass().getName() : e.getMessage()))); + ((e.getMessage() == null) ? e.getClass().getName() : e.getMessage()))); } exceptionIgnoredStack.push(Boolean.TRUE); } @@ -112,8 +107,7 @@ Object instance = creationFactory.createObject(attributes); if (digester.log.isTraceEnabled()) { - digester.log.trace("[FactoryCreateRule]{" + digester.match + - "} New " + instance.getClass().getName()); + digester.log.trace("[FactoryCreateRule]{" + digester.match + "} New " + instance.getClass().getName()); } digester.push(instance); } @@ -128,10 +122,7 @@ // check if object was created // this only happens if an exception was thrown, and we're ignoring them - if ( - ignoreCreateExceptions && - exceptionIgnoredStack != null && - !(exceptionIgnoredStack.empty())) { + if (ignoreCreateExceptions && exceptionIgnoredStack != null && !(exceptionIgnoredStack.empty())) { if ((exceptionIgnoredStack.pop()).booleanValue()) { // creation exception was ignored @@ -145,8 +136,7 @@ Object top = digester.pop(); if (digester.log.isTraceEnabled()) { - digester.log.trace("[FactoryCreateRule]{" + digester.match + - "} Pop " + top.getClass().getName()); + digester.log.trace("[FactoryCreateRule]{" + digester.match + "} Pop " + top.getClass().getName()); } } diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/digester/ObjectCreateRule.java tomcat10-10.1.52/java/org/apache/tomcat/util/digester/ObjectCreateRule.java --- tomcat10-10.1.40/java/org/apache/tomcat/util/digester/ObjectCreateRule.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/digester/ObjectCreateRule.java 2026-01-23 19:33:36.000000000 +0000 @@ -21,8 +21,7 @@ /** - * Rule implementation that creates a new object and pushes it - * onto the object stack. When the element is complete, the + * Rule implementation that creates a new object and pushes it onto the object stack. When the element is complete, the * object will be popped */ @@ -45,15 +44,13 @@ /** - * Construct an object create rule with the specified class name and an - * optional attribute name containing an override. + * Construct an object create rule with the specified class name and an optional attribute name containing an + * override. * - * @param className Java class name of the object to be created - * @param attributeName Attribute name which, if present, contains an - * override of the class name to create + * @param className Java class name of the object to be created + * @param attributeName Attribute name which, if present, contains an override of the class name to create */ - public ObjectCreateRule(String className, - String attributeName) { + public ObjectCreateRule(String className, String attributeName) { this.className = className; this.attributeName = attributeName; @@ -81,16 +78,13 @@ /** * Process the beginning of this element. * - * @param namespace the namespace URI of the matching element, or an - * empty string if the parser is not namespace aware or the element has - * no namespace - * @param name the local name if the parser is namespace aware, or just - * the element name otherwise + * @param namespace the namespace URI of the matching element, or an empty string if the parser is not namespace + * aware or the element has no namespace + * @param name the local name if the parser is namespace aware, or just the element name otherwise * @param attributes The attribute list for this element */ @Override - public void begin(String namespace, String name, Attributes attributes) - throws Exception { + public void begin(String namespace, String name, Attributes attributes) throws Exception { String realClassName = getRealClassName(attributes); @@ -115,7 +109,9 @@ /** * Return the actual class name of the class to be instantiated. + * * @param attributes The attribute list for this element + * * @return the class name */ protected String getRealClassName(Attributes attributes) { @@ -134,19 +130,16 @@ /** * Process the end of this element. * - * @param namespace the namespace URI of the matching element, or an - * empty string if the parser is not namespace aware or the element has - * no namespace - * @param name the local name if the parser is namespace aware, or just - * the element name otherwise + * @param namespace the namespace URI of the matching element, or an empty string if the parser is not namespace + * aware or the element has no namespace + * @param name the local name if the parser is namespace aware, or just the element name otherwise */ @Override public void end(String namespace, String name) throws Exception { Object top = digester.pop(); if (digester.log.isTraceEnabled()) { - digester.log.trace("[ObjectCreateRule]{" + digester.match + - "} Pop " + top.getClass().getName()); + digester.log.trace("[ObjectCreateRule]{" + digester.match + "} Pop " + top.getClass().getName()); } } diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/digester/ObjectCreationFactory.java tomcat10-10.1.52/java/org/apache/tomcat/util/digester/ObjectCreationFactory.java --- tomcat10-10.1.40/java/org/apache/tomcat/util/digester/ObjectCreationFactory.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/digester/ObjectCreationFactory.java 2026-01-23 19:33:36.000000000 +0000 @@ -20,36 +20,35 @@ import org.xml.sax.Attributes; /** - *

      Interface for use with {@link FactoryCreateRule}. - * The rule calls {@link #createObject} to create an object - * to be pushed onto the Digester stack - * whenever it is matched.

      - * - *

      {@link AbstractObjectCreationFactory} is an abstract - * implementation suitable for creating anonymous + *

      + * Interface for use with {@link FactoryCreateRule}. The rule calls {@link #createObject} to create an object to be + * pushed onto the Digester stack whenever it is matched. + *

      + *

      + * {@link AbstractObjectCreationFactory} is an abstract implementation suitable for creating anonymous * ObjectCreationFactory implementations. */ public interface ObjectCreationFactory { /** - * Factory method called by {@link FactoryCreateRule} to supply an - * object based on the element's attributes. + * Factory method called by {@link FactoryCreateRule} to supply an object based on the element's attributes. * * @param attributes the element's attributes + * * @return the created object + * * @throws Exception any exception thrown will be propagated upwards */ Object createObject(Attributes attributes) throws Exception; /** - * @return the {@link Digester} that was set by the - * {@link FactoryCreateRule} upon initialization. + * @return the {@link Digester} that was set by the {@link FactoryCreateRule} upon initialization. */ Digester getDigester(); /** - * Set the {@link Digester} to allow the implementation to do logging, - * classloading based on the digester's classloader, etc. + * Set the {@link Digester} to allow the implementation to do logging, classloading based on the digester's + * classloader, etc. * * @param digester parent Digester object */ diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/digester/Rule.java tomcat10-10.1.52/java/org/apache/tomcat/util/digester/Rule.java --- tomcat10-10.1.40/java/org/apache/tomcat/util/digester/Rule.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/digester/Rule.java 2026-01-23 19:33:36.000000000 +0000 @@ -20,8 +20,8 @@ import org.xml.sax.Attributes; /** - * Concrete implementations of this class implement actions to be taken when - * a corresponding nested pattern of XML elements has been matched. + * Concrete implementations of this class implement actions to be taken when a corresponding nested pattern of XML + * elements has been matched. */ public abstract class Rule { @@ -30,10 +30,12 @@ // ----------------------------------------------------------- Constructors /** - *

      Base constructor. - * Now the digester will be set when the rule is added.

      + *

      + * Base constructor. Now the digester will be set when the rule is added. + *

      */ - public Rule() {} + public Rule() { + } // ----------------------------------------------------- Instance Variables @@ -64,8 +66,7 @@ /** - * Set the Digester with which this Rule is - * associated. + * Set the Digester with which this Rule is associated. * * @param digester The digester with which to associate this rule */ @@ -77,8 +78,7 @@ /** * Return the namespace URI for which this Rule is relevant, if any. * - * @return The namespace URI for which this rule is relevant or - * null if none. + * @return The namespace URI for which this rule is relevant or null if none. */ public String getNamespaceURI() { return namespaceURI; @@ -88,8 +88,8 @@ /** * Set the namespace URI for which this Rule is relevant, if any. * - * @param namespaceURI Namespace URI for which this Rule is relevant, - * or null to match independent of namespace. + * @param namespaceURI Namespace URI for which this Rule is relevant, or null to match independent of + * namespace. */ public void setNamespaceURI(String namespaceURI) { this.namespaceURI = namespaceURI; @@ -99,14 +99,12 @@ // --------------------------------------------------------- Public Methods /** - * This method is called when the beginning of a matching XML element - * is encountered. The default implementation is a NO-OP. + * This method is called when the beginning of a matching XML element is encountered. The default implementation is + * a NO-OP. * - * @param namespace the namespace URI of the matching element, or an - * empty string if the parser is not namespace aware or the - * element has no namespace - * @param name the local name if the parser is namespace aware, or just - * the element name otherwise + * @param namespace the namespace URI of the matching element, or an empty string if the parser is not namespace + * aware or the element has no namespace + * @param name the local name if the parser is namespace aware, or just the element name otherwise * @param attributes The attribute list of this element * * @throws Exception if an error occurs while processing the event @@ -117,16 +115,13 @@ /** - * This method is called when the body of a matching XML element is - * encountered. If the element has no body, this method is not called at - * all. The default implementation is a NO-OP. - * - * @param namespace the namespace URI of the matching element, or an empty - * string if the parser is not namespace aware or the - * element has no namespace - * @param name the local name if the parser is namespace aware, or just the - * element name otherwise - * @param text The text of the body of this element + * This method is called when the body of a matching XML element is encountered. If the element has no body, this + * method is not called at all. The default implementation is a NO-OP. + * + * @param namespace the namespace URI of the matching element, or an empty string if the parser is not namespace + * aware or the element has no namespace + * @param name the local name if the parser is namespace aware, or just the element name otherwise + * @param text The text of the body of this element * * @throws Exception if an error occurs while processing the event */ @@ -136,14 +131,12 @@ /** - * This method is called when the end of a matching XML element - * is encountered. The default implementation is a NO-OP. + * This method is called when the end of a matching XML element is encountered. The default implementation is a + * NO-OP. * - * @param namespace the namespace URI of the matching element, or an empty - * string if the parser is not namespace aware or the - * element has no namespace - * @param name the local name if the parser is namespace aware, or just the - * element name otherwise + * @param namespace the namespace URI of the matching element, or an empty string if the parser is not namespace + * aware or the element has no namespace + * @param name the local name if the parser is namespace aware, or just the element name otherwise * * @throws Exception if an error occurs while processing the event */ @@ -153,8 +146,7 @@ /** - * This method is called after all parsing methods have been - * called, to allow Rules to remove temporary data. + * This method is called after all parsing methods have been called, to allow Rules to remove temporary data. * * @throws Exception if an error occurs while processing the event */ diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/digester/RuleSet.java tomcat10-10.1.52/java/org/apache/tomcat/util/digester/RuleSet.java --- tomcat10-10.1.40/java/org/apache/tomcat/util/digester/RuleSet.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/digester/RuleSet.java 2026-01-23 19:33:36.000000000 +0000 @@ -17,31 +17,28 @@ package org.apache.tomcat.util.digester; /** - *

      Public interface defining a shorthand means of configuring a complete - * set of related Rule definitions, possibly associated with - * a particular namespace URI, in one operation. To use an instance of a - * class that implements this interface:

      + *

      + * Public interface defining a shorthand means of configuring a complete set of related Rule definitions, + * possibly associated with a particular namespace URI, in one operation. To use an instance of a class that implements + * this interface: + *

      *
        *
      • Create a concrete implementation of this interface.
      • - *
      • Optionally, you can configure a RuleSet to be relevant - * only for a particular namespace URI by configuring the value to be - * returned by getNamespaceURI().
      • - *
      • As you are configuring your Digester instance, call - * digester.addRuleSet() and pass the RuleSet instance.
      • - *
      • Digester will call the addRuleInstances() method of - * your RuleSet to configure the necessary rules.
      • + *
      • Optionally, you can configure a RuleSet to be relevant only for a particular namespace URI by + * configuring the value to be returned by getNamespaceURI().
      • + *
      • As you are configuring your Digester instance, call digester.addRuleSet() and pass the RuleSet + * instance.
      • + *
      • Digester will call the addRuleInstances() method of your RuleSet to configure the necessary + * rules.
      • *
      */ public interface RuleSet { /** - * Add the set of Rule instances defined in this RuleSet to the - * specified Digester instance, associating them with - * our namespace URI (if any). This method should only be called - * by a Digester instance. + * Add the set of Rule instances defined in this RuleSet to the specified Digester instance, + * associating them with our namespace URI (if any). This method should only be called by a Digester instance. * - * @param digester Digester instance to which the new Rule instances - * should be added. + * @param digester Digester instance to which the new Rule instances should be added. */ void addRuleInstances(Digester digester); } diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/digester/Rules.java tomcat10-10.1.52/java/org/apache/tomcat/util/digester/Rules.java --- tomcat10-10.1.40/java/org/apache/tomcat/util/digester/Rules.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/digester/Rules.java 2026-01-23 19:33:36.000000000 +0000 @@ -19,18 +19,16 @@ import java.util.List; /** - * Public interface defining a collection of Rule instances (and corresponding - * matching patterns) plus an implementation of a matching policy that selects - * the rules that match a particular pattern of nested elements discovered - * during parsing. + * Public interface defining a collection of Rule instances (and corresponding matching patterns) plus an implementation + * of a matching policy that selects the rules that match a particular pattern of nested elements discovered during + * parsing. */ public interface Rules { // ------------------------------------------------------------- Properties /** - * @return the Digester instance with which this Rules instance is - * associated. + * @return the Digester instance with which this Rules instance is associated. */ Digester getDigester(); @@ -49,7 +47,7 @@ * Register a new Rule instance matching the specified pattern. * * @param pattern Nesting pattern to be matched for this Rule - * @param rule Rule instance to be registered + * @param rule Rule instance to be registered */ void add(String pattern, Rule rule); @@ -61,26 +59,24 @@ /** - * Return a List of all registered Rule instances that match the specified - * nesting pattern, or a zero-length List if there are no matches. If more - * than one Rule instance matches, they must be returned - * in the order originally registered through the add() - * method. + * Return a List of all registered Rule instances that match the specified nesting pattern, or a zero-length List if + * there are no matches. If more than one Rule instance matches, they must be returned in the order + * originally registered through the add() method. + * + * @param namespaceURI Namespace URI for which to select matching rules, or null to match regardless of + * namespace URI + * @param pattern Nesting pattern to be matched * - * @param namespaceURI Namespace URI for which to select matching rules, - * or null to match regardless of namespace URI - * @param pattern Nesting pattern to be matched * @return a rules list */ List match(String namespaceURI, String pattern); /** - * Return a List of all registered Rule instances, or a zero-length List - * if there are no registered Rule instances. If more than one Rule - * instance has been registered, they must be returned - * in the order originally registered through the add() - * method. + * Return a List of all registered Rule instances, or a zero-length List if there are no registered Rule instances. + * If more than one Rule instance has been registered, they must be returned in the order + * originally registered through the add() method. + * * @return a rules list */ List rules(); diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/digester/RulesBase.java tomcat10-10.1.52/java/org/apache/tomcat/util/digester/RulesBase.java --- tomcat10-10.1.40/java/org/apache/tomcat/util/digester/RulesBase.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/digester/RulesBase.java 2026-01-23 19:33:36.000000000 +0000 @@ -21,19 +21,18 @@ import java.util.List; /** - *

      Default implementation of the Rules interface that supports - * the standard rule matching behavior. This class can also be used as a - * base class for specialized Rules implementations.

      - * - *

      The matching policies implemented by this class support two different - * types of pattern matching rules:

      + *

      + * Default implementation of the Rules interface that supports the standard rule matching behavior. This + * class can also be used as a base class for specialized Rules implementations. + *

      + *

      + * The matching policies implemented by this class support two different types of pattern matching rules: + *

      *
        - *
      • Exact Match - A pattern "a/b/c" exactly matches a - * <c> element, nested inside a <b> - * element, which is nested inside an <a> element.
      • - *
      • Tail Match - A pattern "*/a/b" matches a - * <b> element, nested inside an <a> - * element, no matter how deeply the pair is nested.
      • + *
      • Exact Match - A pattern "a/b/c" exactly matches a <c> element, nested inside a + * <b> element, which is nested inside an <a> element.
      • + *
      • Tail Match - A pattern "*/a/b" matches a <b> element, nested inside an + * <a> element, no matter how deeply the pair is nested.
      • *
      */ public class RulesBase implements Rules { @@ -41,9 +40,8 @@ // ----------------------------------------------------- Instance Variables /** - * The set of registered Rule instances, keyed by the matching pattern. - * Each value is a List containing the Rules for that pattern, in the - * order that they were originally registered. + * The set of registered Rule instances, keyed by the matching pattern. Each value is a List containing the Rules + * for that pattern, in the order that they were originally registered. */ protected HashMap> cache = new HashMap<>(); @@ -55,8 +53,7 @@ /** - * The set of registered Rule instances, in the order that they were - * originally registered. + * The set of registered Rule instances, in the order that they were originally registered. */ protected ArrayList rules = new ArrayList<>(); @@ -64,8 +61,7 @@ // ------------------------------------------------------------- Properties /** - * Return the Digester instance with which this Rules instance is - * associated. + * Return the Digester instance with which this Rules instance is associated. */ @Override public Digester getDigester() { @@ -93,14 +89,14 @@ * Register a new Rule instance matching the specified pattern. * * @param pattern Nesting pattern to be matched for this Rule - * @param rule Rule instance to be registered + * @param rule Rule instance to be registered */ @Override public void add(String pattern, Rule rule) { // to help users who accidentally add '/' to the end of their patterns int patternLength = pattern.length(); - if (patternLength>1 && pattern.endsWith("/")) { - pattern = pattern.substring(0, patternLength-1); + if (patternLength > 1 && pattern.endsWith("/")) { + pattern = pattern.substring(0, patternLength - 1); } cache.computeIfAbsent(pattern, k -> new ArrayList<>()).add(rule); @@ -122,15 +118,13 @@ /** - * Return a List of all registered Rule instances that match the specified - * nesting pattern, or a zero-length List if there are no matches. If more - * than one Rule instance matches, they must be returned - * in the order originally registered through the add() - * method. + * Return a List of all registered Rule instances that match the specified nesting pattern, or a zero-length List if + * there are no matches. If more than one Rule instance matches, they must be returned in the order + * originally registered through the add() method. * - * @param namespaceURI Namespace URI for which to select matching rules, - * or null to match regardless of namespace URI - * @param pattern Nesting pattern to be matched + * @param namespaceURI Namespace URI for which to select matching rules, or null to match regardless of + * namespace URI + * @param pattern Nesting pattern to be matched */ @Override public List match(String namespaceURI, String pattern) { @@ -142,8 +136,7 @@ String longKey = ""; for (String key : this.cache.keySet()) { if (key.startsWith("*/")) { - if (pattern.equals(key.substring(2)) || - pattern.endsWith(key.substring(1))) { + if (pattern.equals(key.substring(2)) || pattern.endsWith(key.substring(1))) { if (key.length() > longKey.length()) { // rulesList = (List) this.cache.get(key); rulesList = lookup(namespaceURI, key); @@ -161,11 +154,9 @@ /** - * Return a List of all registered Rule instances, or a zero-length List - * if there are no registered Rule instances. If more than one Rule - * instance has been registered, they must be returned - * in the order originally registered through the add() - * method. + * Return a List of all registered Rule instances, or a zero-length List if there are no registered Rule instances. + * If more than one Rule instance has been registered, they must be returned in the order + * originally registered through the add() method. */ @Override public List rules() { @@ -176,13 +167,13 @@ // ------------------------------------------------------ Protected Methods /** - * Return a List of Rule instances for the specified pattern that also - * match the specified namespace URI (if any). If there are no such - * rules, return null. + * Return a List of Rule instances for the specified pattern that also match the specified namespace URI (if any). + * If there are no such rules, return null. + * + * @param namespaceURI Namespace URI to match, or null to select matching rules regardless of namespace + * URI + * @param pattern Pattern to be matched * - * @param namespaceURI Namespace URI to match, or null to - * select matching rules regardless of namespace URI - * @param pattern Pattern to be matched * @return a rules list */ protected List lookup(String namespaceURI, String pattern) { @@ -198,8 +189,7 @@ // Select only Rules that match on the specified namespace URI List results = new ArrayList<>(); for (Rule item : list) { - if ((namespaceURI.equals(item.getNamespaceURI())) || - (item.getNamespaceURI() == null)) { + if ((namespaceURI.equals(item.getNamespaceURI())) || (item.getNamespaceURI() == null)) { results.add(item); } } diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/digester/ServiceBindingPropertySource.java tomcat10-10.1.52/java/org/apache/tomcat/util/digester/ServiceBindingPropertySource.java --- tomcat10-10.1.40/java/org/apache/tomcat/util/digester/ServiceBindingPropertySource.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/digester/ServiceBindingPropertySource.java 2026-01-23 19:33:36.000000000 +0000 @@ -27,16 +27,15 @@ import org.apache.tomcat.util.security.PermissionCheck; /** - * A {@link org.apache.tomcat.util.IntrospectionUtils.SecurePropertySource} - * that uses Kubernetes service bindings to resolve expressions. - * + * A {@link org.apache.tomcat.util.IntrospectionUtils.SecurePropertySource} that uses Kubernetes service bindings to + * resolve expressions. *

      - * The Kubernetes service binding specification can be found at - * https://servicebinding.io/. + * The Kubernetes service binding specification can be found at + * https://servicebinding.io/. + *

      + *

      + * Usage example: *

      - * - *

      Usage example:

      - * * Configure the certificate with a service binding. *

      * When the service binding is constructed as follows: @@ -49,6 +48,7 @@ * /chainFile * /keyPassword * + * *

        *   {@code
        *     
      @@ -59,20 +59,19 @@
        *                        type="RSA" />
        *      }
        * 
      - * *

      - * The optional chomp: prefix will cause the ServiceBindingPropertySource - * to trim a single newline (\r\n, \r, or \n) - * from the end of the file, if it exists. This is a convenience for hand-edited - * files/values where removing a trailing newline is difficult, and trailing - * whitespace changes the meaning of the value. + * The optional chomp: prefix will cause the ServiceBindingPropertySource to trim a single newline + * (\r\n, \r, or \n) from the end of the file, if it exists. This is a + * convenience for hand-edited files/values where removing a trailing newline is difficult, and trailing whitespace + * changes the meaning of the value. *

      - * * How to configure: + * *
        * {@code
        *   echo "org.apache.tomcat.util.digester.PROPERTY_SOURCE=org.apache.tomcat.util.digester.ServiceBindingPropertySource" >> conf/catalina.properties}
        * 
      + * * or add this to {@code CATALINA_OPTS} * *
      @@ -80,13 +79,11 @@
        *   -Dorg.apache.tomcat.util.digester.PROPERTY_SOURCE=org.apache.tomcat.util.digester.ServiceBindingPropertySource}
        * 
      * - * NOTE: When configured the PropertySource for resolving expressions - * from system properties is still active. + * NOTE: When configured the PropertySource for resolving expressions from system properties is still active. * * @see Digester - * * @see Tomcat - * Configuration Reference System Properties + * Configuration Reference System Properties */ public class ServiceBindingPropertySource implements IntrospectionUtils.SecurePropertySource { @@ -144,7 +141,7 @@ int length = bytes.length; if (chomp) { - if(length > 1 && bytes[length - 2] == '\r' && bytes[length - 1] == '\n') { + if (length > 1 && bytes[length - 2] == '\r' && bytes[length - 1] == '\n') { length -= 2; } else if (length > 0) { byte c = bytes[length - 1]; @@ -155,7 +152,8 @@ } return new String(bytes, 0, length); - } catch (IOException e) { + } catch (IOException ioe) { + // Treat as not found return null; } } diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/digester/SetNextRule.java tomcat10-10.1.52/java/org/apache/tomcat/util/digester/SetNextRule.java --- tomcat10-10.1.40/java/org/apache/tomcat/util/digester/SetNextRule.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/digester/SetNextRule.java 2026-01-23 19:33:36.000000000 +0000 @@ -20,14 +20,14 @@ /** - *

      Rule implementation that calls a method on the (top-1) (parent) - * object, passing the top object (child) as an argument. It is - * commonly used to establish parent-child relationships.

      - * - *

      This rule now supports more flexible method matching by default. - * It is possible that this may break (some) code - * written against release 1.1.1 or earlier. - * See {@link #isExactMatch()} for more details.

      + *

      + * Rule implementation that calls a method on the (top-1) (parent) object, passing the top object (child) as an + * argument. It is commonly used to establish parent-child relationships. + *

      + *

      + * This rule now supports more flexible method matching by default. It is possible that this may break (some) code + * written against release 1.1.1 or earlier. See {@link #isExactMatch()} for more details. + *

      */ public class SetNextRule extends Rule { @@ -38,13 +38,11 @@ * Construct a "set next" rule with the specified method name. * * @param methodName Method name of the parent method to call - * @param paramType Java class of the parent method's argument - * (if you wish to use a primitive type, specify the corresponding - * Java wrapper class instead, such as java.lang.Boolean - * for a boolean parameter) + * @param paramType Java class of the parent method's argument (if you wish to use a primitive type, specify the + * corresponding Java wrapper class instead, such as java.lang.Boolean for a + * boolean parameter) */ - public SetNextRule(String methodName, - String paramType) { + public SetNextRule(String methodName, String paramType) { this.methodName = methodName; this.paramType = paramType; @@ -75,23 +73,26 @@ /** - *

      Is exact matching being used.

      - * - *

      This rule uses org.apache.commons.beanutils.MethodUtils - * to introspect the relevant objects so that the right method can be called. - * Originally, MethodUtils.invokeExactMethod was used. - * This matches methods very strictly - * and so may not find a matching method when one exists. - * This is still the behaviour when exact matching is enabled.

      - * - *

      When exact matching is disabled, MethodUtils.invokeMethod is used. - * This method finds more methods but is less precise when there are several methods - * with correct signatures. - * So, if you want to choose an exact signature you might need to enable this property.

      - * - *

      The default setting is to disable exact matches.

      + *

      + * Is exact matching being used. + *

      + *

      + * This rule uses org.apache.commons.beanutils.MethodUtils to introspect the relevant objects so that + * the right method can be called. Originally, MethodUtils.invokeExactMethod was used. This matches + * methods very strictly and so may not find a matching method when one exists. This is still the behaviour when + * exact matching is enabled. + *

      + *

      + * When exact matching is disabled, MethodUtils.invokeMethod is used. This method finds more methods + * but is less precise when there are several methods with correct signatures. So, if you want to choose an exact + * signature you might need to enable this property. + *

      + *

      + * The default setting is to disable exact matches. + *

      * * @return true iff exact matching is enabled + * * @since Digester Release 1.1.1 */ public boolean isExactMatch() { @@ -100,11 +101,15 @@ } /** - *

      Set whether exact matching is enabled.

      - * - *

      See {@link #isExactMatch()}.

      + *

      + * Set whether exact matching is enabled. + *

      + *

      + * See {@link #isExactMatch()}. + *

      * * @param useExactMatch should this rule use exact method matching + * * @since Digester Release 1.1.1 */ public void setExactMatch(boolean useExactMatch) { @@ -115,11 +120,9 @@ /** * Process the end of this element. * - * @param namespace the namespace URI of the matching element, or an - * empty string if the parser is not namespace aware or the element has - * no namespace - * @param name the local name if the parser is namespace aware, or just - * the element name otherwise + * @param namespace the namespace URI of the matching element, or an empty string if the parser is not namespace + * aware or the element has no namespace + * @param name the local name if the parser is namespace aware, or just the element name otherwise */ @Override public void end(String namespace, String name) throws Exception { @@ -129,19 +132,16 @@ Object parent = digester.peek(1); if (digester.log.isTraceEnabled()) { if (parent == null) { - digester.log.trace("[SetNextRule]{" + digester.match + - "} Call [NULL PARENT]." + - methodName + "(" + child + ")"); + digester.log.trace( + "[SetNextRule]{" + digester.match + "} Call [NULL PARENT]." + methodName + "(" + child + ")"); } else { - digester.log.trace("[SetNextRule]{" + digester.match + - "} Call " + parent.getClass().getName() + "." + + digester.log.trace("[SetNextRule]{" + digester.match + "} Call " + parent.getClass().getName() + "." + methodName + "(" + child + ")"); } } // Call the specified method - IntrospectionUtils.callMethod1(parent, methodName, - child, paramType, digester.getClassLoader()); + IntrospectionUtils.callMethod1(parent, methodName, child, paramType, digester.getClassLoader()); StringBuilder code = digester.getGeneratedCode(); if (code != null) { diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/digester/SetPropertiesRule.java tomcat10-10.1.52/java/org/apache/tomcat/util/digester/SetPropertiesRule.java --- tomcat10-10.1.40/java/org/apache/tomcat/util/digester/SetPropertiesRule.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/digester/SetPropertiesRule.java 2026-01-23 19:33:36.000000000 +0000 @@ -24,8 +24,10 @@ /** - *

      Rule implementation that sets properties on the object at the top of the - * stack, based on attributes with corresponding names.

      + *

      + * Rule implementation that sets properties on the object at the top of the stack, based on attributes with + * corresponding names. + *

      */ public class SetPropertiesRule extends Rule { @@ -52,23 +54,19 @@ /** * Process the beginning of this element. * - * @param namespace the namespace URI of the matching element, or an - * empty string if the parser is not namespace aware or the element has - * no namespace - * @param theName the local name if the parser is namespace aware, or just - * the element name otherwise + * @param namespace the namespace URI of the matching element, or an empty string if the parser is not namespace + * aware or the element has no namespace + * @param theName the local name if the parser is namespace aware, or just the element name otherwise * @param attributes The attribute list for this element */ @Override - public void begin(String namespace, String theName, Attributes attributes) - throws Exception { + public void begin(String namespace, String theName, Attributes attributes) throws Exception { // Populate the corresponding properties of the top object Object top = digester.peek(); if (digester.log.isTraceEnabled()) { - digester.log.trace("[SetPropertiesRule]{" + digester.match + - "} Set " + top.getClass().getName() + - " properties"); + digester.log.trace( + "[SetPropertiesRule]{" + digester.match + "} Set " + top.getClass().getName() + " properties"); } StringBuilder code = digester.getGeneratedCode(); String variableName = null; @@ -84,8 +82,7 @@ String value = attributes.getValue(i); if (digester.log.isTraceEnabled()) { - digester.log.trace("[SetPropertiesRule]{" + digester.match + - "} Setting property '" + name + "' to '" + + digester.log.trace("[SetPropertiesRule]{" + digester.match + "} Setting property '" + name + "' to '" + value + "'"); } if (!digester.isFakeAttribute(top, name) && (excludes == null || !excludes.containsKey(name))) { diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/digester/SystemPropertySource.java tomcat10-10.1.52/java/org/apache/tomcat/util/digester/SystemPropertySource.java --- tomcat10-10.1.40/java/org/apache/tomcat/util/digester/SystemPropertySource.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/digester/SystemPropertySource.java 2026-01-23 19:33:36.000000000 +0000 @@ -23,9 +23,8 @@ import org.apache.tomcat.util.security.PermissionCheck; /** - * A {@link org.apache.tomcat.util.IntrospectionUtils.SecurePropertySource} - * that uses system properties to resolve expressions. - * This property source is always active by default. + * A {@link org.apache.tomcat.util.IntrospectionUtils.SecurePropertySource} that uses system properties to resolve + * expressions. This property source is always active by default. * * @see Digester */ diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/file/ConfigFileLoader.java tomcat10-10.1.52/java/org/apache/tomcat/util/file/ConfigFileLoader.java --- tomcat10-10.1.40/java/org/apache/tomcat/util/file/ConfigFileLoader.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/file/ConfigFileLoader.java 2026-01-23 19:33:36.000000000 +0000 @@ -20,17 +20,17 @@ import java.io.InputStream; /** - * This class is used to obtain {@link InputStream}s for configuration files - * from a given location String. This allows greater flexibility than these - * files having to be loaded directly from a file system. + * This class is used to obtain {@link InputStream}s for configuration files from a given location String. This allows + * greater flexibility than these files having to be loaded directly from a file system. */ public class ConfigFileLoader { private static ConfigurationSource source; /** - * Get the configured configuration source. If none has been configured, - * a default source based on the calling directory will be used. + * Get the configured configuration source. If none has been configured, a default source based on the calling + * directory will be used. + * * @return the configuration source in use */ public static ConfigurationSource getSource() { @@ -41,8 +41,8 @@ } /** - * Set the configuration source used by Tomcat to locate various - * configuration resources. + * Set the configuration source used by Tomcat to locate various configuration resources. + * * @param source The source */ public static void setSource(ConfigurationSource source) { diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/file/ConfigurationSource.java tomcat10-10.1.52/java/org/apache/tomcat/util/file/ConfigurationSource.java --- tomcat10-10.1.40/java/org/apache/tomcat/util/file/ConfigurationSource.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/file/ConfigurationSource.java 2026-01-23 19:33:36.000000000 +0000 @@ -29,17 +29,16 @@ import org.apache.tomcat.util.buf.UriUtil; /** - * Abstracts configuration file storage. Allows Tomcat embedding using the regular - * configuration style. - * This abstraction aims to be very simple and does not cover resource listing, - * which is usually used for dynamic deployments that are usually not used when - * embedding, as well as resource writing. + * Abstracts configuration file storage. Allows Tomcat embedding using the regular configuration style. This abstraction + * aims to be very simple and does not cover resource listing, which is usually used for dynamic deployments that are + * usually not used when embedding, as well as resource writing. */ public interface ConfigurationSource { ConfigurationSource DEFAULT = new ConfigurationSource() { private final File userDir = new File(System.getProperty("user.dir")); private final URI userDirUri = userDir.toURI(); + @Override public Resource getResource(String name) throws IOException { if (!UriUtil.isAbsoluteURI(name)) { @@ -65,6 +64,7 @@ throw new FileNotFoundException(name); } } + @Override public URI getURI(String name) { if (!UriUtil.isAbsoluteURI(name)) { @@ -81,24 +81,26 @@ }; /** - * Represents a resource: a stream to the resource associated with - * its URI. + * Represents a resource: a stream to the resource associated with its URI. */ class Resource implements AutoCloseable { private final InputStream inputStream; private final URI uri; + public Resource(InputStream inputStream, URI uri) { this.inputStream = inputStream; this.uri = uri; } + public InputStream getInputStream() { return inputStream; } + public URI getURI() { return uri; } - public long getLastModified() - throws MalformedURLException, IOException { + + public long getLastModified() throws MalformedURLException, IOException { URLConnection connection = null; try { connection = uri.toURL().openConnection(); @@ -109,6 +111,7 @@ } } } + @Override public void close() throws IOException { if (inputStream != null) { @@ -119,50 +122,58 @@ /** * Returns the contents of the main conf/server.xml file. + * * @return the server.xml as an InputStream + * * @throws IOException if an error occurs or if the resource does not exist */ - default Resource getServerXml() - throws IOException { + default Resource getServerXml() throws IOException { return getConfResource("server.xml"); } /** - * Returns the contents of the shared conf/web.xml file. This usually - * contains the declaration of the default and JSP servlets. + * Returns the contents of the shared conf/web.xml file. This usually contains the declaration of the default and + * JSP servlets. + * * @return the web.xml as an InputStream + * * @throws IOException if an error occurs or if the resource does not exist */ - default Resource getSharedWebXml() - throws IOException { + default Resource getSharedWebXml() throws IOException { return getConfResource("web.xml"); } /** * Get a resource, based on the conf path. + * * @param name The resource name + * * @return the resource as an InputStream + * * @throws IOException if an error occurs or if the resource does not exist */ - default Resource getConfResource(String name) - throws IOException { + default Resource getConfResource(String name) throws IOException { String fullName = "conf/" + name; return getResource(fullName); } /** * Get a resource, not based on the conf path. + * * @param name The resource name + * * @return the resource + * * @throws IOException if an error occurs or if the resource does not exist */ - Resource getResource(String name) - throws IOException; + Resource getResource(String name) throws IOException; /** - * Get a URI to the given resource. Unlike getResource, this will also - * return URIs to locations where no resource exists. + * Get a URI to the given resource. Unlike getResource, this will also return URIs to locations where no resource + * exists. + * * @param name The resource name + * * @return a URI representing the resource location */ URI getURI(String name); diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/file/Matcher.java tomcat10-10.1.52/java/org/apache/tomcat/util/file/Matcher.java --- tomcat10-10.1.40/java/org/apache/tomcat/util/file/Matcher.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/file/Matcher.java 2026-01-23 19:33:36.000000000 +0000 @@ -20,32 +20,32 @@ import java.util.Set; /** - *

      This is a utility class to match file globs. - * The class has been derived from + *

      + * This is a utility class to match file globs. The class has been derived from * org.apache.tools.ant.types.selectors.SelectorUtils. *

      - *

      All methods are static.

      + *

      + * All methods are static. + *

      */ public final class Matcher { /** - * Tests whether or not a given file name matches any file name pattern in - * the given set. The match is performed case-sensitively. + * Tests whether or not a given file name matches any file name pattern in the given set. The match is performed + * case-sensitively. * * @see #match(String, String, boolean) * - * @param patternSet The pattern set to match against. Must not be - * null. - * @param fileName The file name to match, as a String. Must not be - * null. It must be just a file name, without - * a path. + * @param patternSet The pattern set to match against. Must not be null. + * @param fileName The file name to match, as a String. Must not be null. It must be just a file + * name, without a path. * - * @return true if any pattern in the set matches against the - * file name, or false otherwise. + * @return true if any pattern in the set matches against the file name, or false + * otherwise. */ public static boolean matchName(Set patternSet, String fileName) { char[] fileNameArray = fileName.toCharArray(); - for (String pattern: patternSet) { + for (String pattern : patternSet) { if (match(pattern, fileNameArray, true)) { return true; } @@ -55,48 +55,35 @@ /** - * Tests whether or not a string matches against a pattern. - * The pattern may contain two special characters:
      + * Tests whether or not a string matches against a pattern. The pattern may contain two special characters:
      * '*' means zero or more characters
      * '?' means one and only one character * - * @param pattern The pattern to match against. - * Must not be null. - * @param str The string which must be matched against the - * pattern. Must not be null. - * @param caseSensitive Whether or not matching should be performed - * case sensitively. - * + * @param pattern The pattern to match against. Must not be null. + * @param str The string which must be matched against the pattern. Must not be null. + * @param caseSensitive Whether or not matching should be performed case sensitively. * - * @return true if the string matches against the pattern, - * or false otherwise. + * @return true if the string matches against the pattern, or false otherwise. */ - public static boolean match(String pattern, String str, - boolean caseSensitive) { + public static boolean match(String pattern, String str, boolean caseSensitive) { return match(pattern, str.toCharArray(), caseSensitive); } /** - * Tests whether or not a string matches against a pattern. - * The pattern may contain two special characters:
      + * Tests whether or not a string matches against a pattern. The pattern may contain two special characters:
      * '*' means zero or more characters
      * '?' means one and only one character * - * @param pattern The pattern to match against. - * Must not be null. - * @param strArr The character array which must be matched against the - * pattern. Must not be null. - * @param caseSensitive Whether or not matching should be performed - * case sensitively. - * + * @param pattern The pattern to match against. Must not be null. + * @param strArr The character array which must be matched against the pattern. Must not be + * null. + * @param caseSensitive Whether or not matching should be performed case sensitively. * - * @return true if the string matches against the pattern, - * or false otherwise. + * @return true if the string matches against the pattern, or false otherwise. */ - private static boolean match(String pattern, char[] strArr, - boolean caseSensitive) { + private static boolean match(String pattern, char[] strArr, boolean caseSensitive) { char[] patArr = pattern.toCharArray(); int patIdxStart = 0; int patIdxEnd = patArr.length - 1; @@ -197,8 +184,7 @@ for (int j = 0; j < patLength; j++) { ch = patArr[patIdxStart + j + 1]; if (ch != '?') { - if (different(caseSensitive, ch, - strArr[strIdxStart + i + j])) { + if (different(caseSensitive, ch, strArr[strIdxStart + i + j])) { continue strLoop; } } @@ -230,11 +216,8 @@ return true; } - private static boolean different( - boolean caseSensitive, char ch, char other) { - return caseSensitive - ? ch != other - : Character.toUpperCase(ch) != Character.toUpperCase(other); + private static boolean different(boolean caseSensitive, char ch, char other) { + return caseSensitive ? ch != other : Character.toUpperCase(ch) != Character.toUpperCase(other); } } diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/http/CookiesWithoutEquals.java tomcat10-10.1.52/java/org/apache/tomcat/util/http/CookiesWithoutEquals.java --- tomcat10-10.1.40/java/org/apache/tomcat/util/http/CookiesWithoutEquals.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/http/CookiesWithoutEquals.java 2026-01-23 19:33:36.000000000 +0000 @@ -24,13 +24,49 @@ IGNORE("ignore"), NAME("name"); /* + * @formatter:off * There is no VALUE option since the Servlet specification does not permit the creation of a Cookie with a name * that is either null or the zero length string. * - * The historical intention (from the user agent perspective) of using a name-value-pair without an equals sign has - * been to indicate a cookie with a name but no value. Tomcat has done the opposite. The current RFC6265bis text - * treats a name-value-pair without an equals sign as a cookie with a value but no name. Supporting this will - * require changes to the Servlet specification. + * In RFC 2019, cookie name and value were defined as follows: + * cookie = NAME "=" VALUE *(";" cookie-av) + * NAME = attr + * VALUE = value + * attr = token + * value = word + * And from RFC 2068 + * token = 1* + * word = *TEXT + * Set-Cookie and Cookie used the same definition. + * Name had to be at least one character, equals sign was required, value could be the empty string. + * + * In RFC 2965, the definition of value changed to: + * value = token | quoted-string + * Set-Cookie2 and Cookie use the same definition. + * Name had to be at least one character, equals sign was required, value could not be the empty string (it could + * be ""). + * + * In RFC6265, which aimed to document actual usage, cookie name and value are defined as follows: + * cookie-pair = cookie-name "=" cookie-value + * cookie-name = token + * cookie-value = *cookie-octet / ( DQUOTE *cookie-octet DQUOTE ) + * For the user agent, the equals sign was required and cookies with no name were ignored. + * + * In RFC6265bis, the definitions are unchanged. + * For the user agent: + * - a name-value-pair without an equals sign is treated as the value of a cookie with an empty name. + * - both empty name and empty value are allowed but if both are empty the cookie will be ignored. + * @formatter:on + * + * To see how RFC6265 arrived at his behaviour, see https://github.com/httpwg/http-extensions/issues/159 + * + * Historically, the users agents settled on using a name-value-pair without an equals sign to indicate a cookie + * with a value but no name. Tomcat did the opposite. That arose from addressing this bug: + * https://bz.apache.org/bugzilla/show_bug.cgi?id=49000 which was based on observed but not understood client + * behaviour. + * + * The current RFC6265bis text explicitly treats a name-value-pair without an equals sign as a cookie with a value + * but no name. There are currently no plans for the Servlet specification to support nameless cookies. */ diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/http/FastHttpDateFormat.java tomcat10-10.1.52/java/org/apache/tomcat/util/http/FastHttpDateFormat.java --- tomcat10-10.1.40/java/org/apache/tomcat/util/http/FastHttpDateFormat.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/http/FastHttpDateFormat.java 2026-01-23 19:33:36.000000000 +0000 @@ -25,8 +25,6 @@ /** * Utility class to generate HTTP dates. - * - * @author Remy Maucherat */ public final class FastHttpDateFormat { @@ -75,8 +73,10 @@ /** * Formatter cache. + *

      + * Note: This needs to be a ConcurrentHashMap for correct operation so declare it as such (rather than as Map). */ - private static final Map formatCache = new ConcurrentHashMap<>(CACHE_SIZE); + private static final ConcurrentHashMap formatCache = new ConcurrentHashMap<>(CACHE_SIZE); /** diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/http/HeaderUtil.java tomcat10-10.1.52/java/org/apache/tomcat/util/http/HeaderUtil.java --- tomcat10-10.1.40/java/org/apache/tomcat/util/http/HeaderUtil.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/http/HeaderUtil.java 2026-01-23 19:33:36.000000000 +0000 @@ -20,7 +20,7 @@ /** * Converts an HTTP header line in byte form to a printable String. Bytes corresponding to visible ASCII characters - * will be converted to those characters. All other bytes (0x00 to 0x1F, 0x7F to OxFF) will be represented in 0xNN + * will be converted to those characters. All other bytes (0x00 to 0x1F, 0x7F to 0xFF) will be represented in 0xNN * form. * * @param bytes Contains an HTTP header line diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/http/Method.java tomcat10-10.1.52/java/org/apache/tomcat/util/http/Method.java --- tomcat10-10.1.40/java/org/apache/tomcat/util/http/Method.java 1970-01-01 00:00:00.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/http/Method.java 2026-01-23 19:33:36.000000000 +0000 @@ -0,0 +1,164 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.tomcat.util.http; + +public class Method { + + /* + * This class was originally created to hold the bytes to String conversion method. It turns out that these + * constants are just as much of a benefit to performance - if used consistently. + * + * If the String constants for the methods are used throughout the code-base, that allows String.equals() to use the + * 'same object shortcut' when checking if a request is (or is not) using a particular method. That is faster than a + * character by character comparison. That results in a further performance improvement that is as big - or possibly + * slightly bigger - than the improvement obtained by using the optimised conversion. + */ + + // Standard HTTP methods supported by HttpServlet + public static final String GET = "GET"; + public static final String POST = "POST"; + public static final String PUT = "PUT"; + public static final String PATCH = "PATCH"; + public static final String HEAD = "HEAD"; + public static final String OPTIONS = "OPTIONS"; + public static final String DELETE = "DELETE"; + public static final String TRACE = "TRACE"; + // Additional WebDAV methods + public static final String PROPFIND = "PROPFIND"; + public static final String PROPPATCH = "PROPPATCH"; + public static final String MKCOL = "MKCOL"; + public static final String COPY = "COPY"; + public static final String MOVE = "MOVE"; + public static final String LOCK = "LOCK"; + public static final String UNLOCK = "UNLOCK"; + // Other methods recognised by Tomcat + public static final String CONNECT = "CONNECT"; + + + /** + * Provides optimised conversion from bytes to Strings for known HTTP methods. The bytes are assumed to be an + * ISO-8859-1 encoded representation of an HTTP method. The method is not validated as being a token, but only valid + * HTTP method names will be returned. + *

      + * Doing it this way is ~10x faster than using MessageBytes.toStringType() saving ~40ns per request which is ~1% of + * the processing time for a minimal "Hello World" type servlet. For non-standard methods there is an additional + * overhead of ~2.5ns per request. + *

      + * Pretty much every request ends up converting the method to a String so it is more efficient to do this straight + * away and always use Strings. + * + * @param buf The byte buffer containing the HTTP method to convert + * @param start The first byte of the HTTP method + * @param len The number of bytes to convert + * + * @return The HTTP method as a String or {@code null} if the method is not recognised. + */ + public static String bytesToString(byte[] buf, int start, int len) { + switch (buf[start]) { + case 'G': { + if (len == 3 && buf[start + 1] == 'E' && buf[start + 2] == 'T') { + return GET; + } + break; + } + case 'P': { + if (len == 4 && buf[start + 1] == 'O' && buf[start + 2] == 'S' && buf[start + 3] == 'T') { + return POST; + } else if (len == 3 && buf[start + 1] == 'U' && buf[start + 2] == 'T') { + return PUT; + } else if (len == 5 && buf[start + 1] == 'A' && buf[start + 2] == 'T' && buf[start + 3] == 'C' && + buf[start + 4] == 'H') { + return PATCH; + } else if (len == 8 && buf[start + 1] == 'R' && buf[start + 2] == 'O' && buf[start + 3] == 'P' && + buf[start + 4] == 'F' && buf[start + 5] == 'I' && buf[start + 6] == 'N' && + buf[start + 7] == 'D') { + return PROPFIND; + } else if (len == 9 && buf[start + 1] == 'R' && buf[start + 2] == 'O' && buf[start + 3] == 'P' && + buf[start + 4] == 'P' && buf[start + 5] == 'A' && buf[start + 6] == 'T' && + buf[start + 7] == 'C' && buf[start + 8] == 'H') { + return PROPPATCH; + } + break; + } + case 'H': { + if (len == 4 && buf[start + 1] == 'E' && buf[start + 2] == 'A' && buf[start + 3] == 'D') { + return HEAD; + } + break; + } + case 'O': { + if (len == 7 && buf[start + 1] == 'P' && buf[start + 2] == 'T' && buf[start + 3] == 'I' && + buf[start + 4] == 'O' && buf[start + 5] == 'N' && buf[start + 6] == 'S') { + return OPTIONS; + } + break; + } + case 'D': { + if (len == 6 && buf[start + 1] == 'E' && buf[start + 2] == 'L' && buf[start + 3] == 'E' && + buf[start + 4] == 'T' && buf[start + 5] == 'E') { + return DELETE; + } + break; + } + case 'T': { + if (len == 5 && buf[start + 1] == 'R' && buf[start + 2] == 'A' && buf[start + 3] == 'C' && + buf[start + 4] == 'E') { + return TRACE; + } + break; + } + case 'M': { + if (len == 5 && buf[start + 1] == 'K' && buf[start + 2] == 'C' && buf[start + 3] == 'O' && + buf[start + 4] == 'L') { + return MKCOL; + } else if (len == 4 && buf[start + 1] == 'O' && buf[start + 2] == 'V' && buf[start + 3] == 'E') { + return MOVE; + } + break; + } + case 'C': { + if (len == 4 && buf[start + 1] == 'O' && buf[start + 2] == 'P' && buf[start + 3] == 'Y') { + return COPY; + } else if (len == 7 && buf[start + 1] == 'O' && buf[start + 2] == 'N' && buf[start + 3] == 'N' && + buf[start + 4] == 'E' && buf[start + 5] == 'C' && buf[start + 6] == 'T') { + return CONNECT; + } + break; + } + case 'L': { + if (len == 4 && buf[start + 1] == 'O' && buf[start + 2] == 'C' && buf[start + 3] == 'K') { + return LOCK; + } + break; + } + case 'U': { + if (len == 6 && buf[start + 1] == 'N' && buf[start + 2] == 'L' && buf[start + 3] == 'O' && + buf[start + 4] == 'C' && buf[start + 5] == 'K') { + return UNLOCK; + } + break; + } + } + + return null; + } + + + private Method() { + // Utility class - hide default constructor + } +} diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/http/MimeHeaders.java tomcat10-10.1.52/java/org/apache/tomcat/util/http/MimeHeaders.java --- tomcat10-10.1.40/java/org/apache/tomcat/util/http/MimeHeaders.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/http/MimeHeaders.java 2026-01-23 19:33:36.000000000 +0000 @@ -22,6 +22,7 @@ import java.util.Collections; import java.util.Enumeration; import java.util.HashMap; +import java.util.Locale; import java.util.Map; import java.util.Set; @@ -39,39 +40,26 @@ * calls header methods, but is easy to avoid inside tomcat. The goal is to use _only_ MessageByte-based Fields, and * reduce to 0 the memory overhead of tomcat. *

      - * This class is used to contain standard internet message headers, - * used for SMTP (RFC822) and HTTP (RFC2068) messages as well as for - * MIME (RFC 2045) applications such as transferring typed data and - * grouping related items in multipart message bodies. - *

      - * Message headers, as specified in RFC822, include a field name - * and a field body. Order has no semantic significance, and several - * fields with the same name may exist. However, most fields do not - * (and should not) exist more than once in a header. - *

      - * Many kinds of field body must conform to a specified syntax, - * including the standard parenthesized comment syntax. This class - * supports only two simple syntaxes, for dates and integers. - *

      - * When processing headers, care must be taken to handle the case of - * multiple same-name fields correctly. The values of such fields are - * only available as strings. They may be accessed by index (treating - * the header as an array of fields), or by name (returning an array - * of string values). - *

      - * Headers are first parsed and stored in the order they are - * received. This is based on the fact that most servlets will not - * directly access all headers, and most headers are single-valued. - * (the alternative - a hash or similar data structure - will add - * an overhead that is not needed in most cases) - *

      - * Apache seems to be using a similar method for storing and manipulating - * headers. - * - * @author dac@eng.sun.com - * @author James Todd [gonzo@eng.sun.com] - * @author Costin Manolache - * @author kevin seguin + * This class is used to contain standard internet message headers, used for SMTP (RFC822) and HTTP (RFC2068) messages + * as well as for MIME (RFC 2045) applications such as transferring typed data and grouping related items in multipart + * message bodies. + *

      + * Message headers, as specified in RFC822, include a field name and a field body. Order has no semantic significance, + * and several fields with the same name may exist. However, most fields do not (and should not) exist more than once in + * a header. + *

      + * Many kinds of field body must conform to a specified syntax, including the standard parenthesized comment syntax. + * This class supports only two simple syntaxes, for dates and integers. + *

      + * When processing headers, care must be taken to handle the case of multiple same-name fields correctly. The values of + * such fields are only available as strings. They may be accessed by index (treating the header as an array of fields), + * or by name (returning an array of string values). + *

      + * Headers are first parsed and stored in the order they are received. This is based on the fact that most servlets will + * not directly access all headers, and most headers are single-valued. (the alternative - a hash or similar data + * structure - will add an overhead that is not needed in most cases) + *

      + * Apache seems to be using a similar method for storing and manipulating headers. */ public class MimeHeaders { @@ -172,7 +160,7 @@ int j = -1; for (int i = 0; i < count; i++) { String name = headers[i].getName().toStringType(); - if (allowedHeaders.contains(name)) { + if (allowedHeaders.contains(name.trim().toLowerCase(Locale.ENGLISH))) { ++j; if (j != i) { headers[j] = headers[i]; diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/http/Parameters.java tomcat10-10.1.52/java/org/apache/tomcat/util/http/Parameters.java --- tomcat10-10.1.40/java/org/apache/tomcat/util/http/Parameters.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/http/Parameters.java 2026-01-23 19:33:36.000000000 +0000 @@ -187,9 +187,9 @@ try { decodedQuery.duplicate(queryMB); - } catch (IOException e) { + } catch (IOException ioe) { // Can't happen, as decodedQuery can't overflow - log.error(sm.getString("parameters.copyFail"), e); + log.error(sm.getString("parameters.copyFail"), ioe); } processParameters(decodedQuery, queryStringCharset); } @@ -407,14 +407,14 @@ } break; } - } catch (IOException e) { + } catch (IOException ioe) { setParseFailedReason(FailReason.URL_DECODING); decodeFailCount++; if (decodeFailCount == 1 || log.isDebugEnabled()) { if (log.isDebugEnabled()) { log.debug( sm.getString("parameters.decodeFail.debug", origName.toString(), origValue.toString()), - e); + ioe); } else if (log.isInfoEnabled()) { UserDataHelper.Mode logMode = userDataLog.getNextMode(); if (logMode != null) { diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/http/ResponseUtil.java tomcat10-10.1.52/java/org/apache/tomcat/util/http/ResponseUtil.java --- tomcat10-10.1.40/java/org/apache/tomcat/util/http/ResponseUtil.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/http/ResponseUtil.java 2026-01-23 19:33:36.000000000 +0000 @@ -82,8 +82,8 @@ StringReader input = new StringReader(varyHeader); try { TokenList.parseTokenList(input, fieldNames); - } catch (IOException ioe) { - // Should never happen + } catch (IOException ignore) { + // Should never happen because a StringReader is used. } } diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/http/Rfc6265CookieProcessor.java tomcat10-10.1.52/java/org/apache/tomcat/util/http/Rfc6265CookieProcessor.java --- tomcat10-10.1.40/java/org/apache/tomcat/util/http/Rfc6265CookieProcessor.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/http/Rfc6265CookieProcessor.java 2026-01-23 19:33:36.000000000 +0000 @@ -80,9 +80,8 @@ if (cookieValue != null && !cookieValue.isNull()) { if (cookieValue.getType() != MessageBytes.T_BYTES) { if (log.isDebugEnabled()) { - Exception e = new Exception(); // TODO: Review this in light of HTTP/2 - log.debug(sm.getString("rfc6265CookieProcessor.expectedBytes"), e); + log.debug(sm.getString("rfc6265CookieProcessor.expectedBytes"), new Exception()); } cookieValue.toBytes(); } diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/http/WebdavIfHeader.java tomcat10-10.1.52/java/org/apache/tomcat/util/http/WebdavIfHeader.java --- tomcat10-10.1.40/java/org/apache/tomcat/util/http/WebdavIfHeader.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/http/WebdavIfHeader.java 2026-01-23 19:33:36.000000000 +0000 @@ -30,9 +30,9 @@ import org.apache.tomcat.util.res.StringManager; /** - * The IfHeader class represents the state lists defined - * through the HTTP If header, which is specified in RFC 2518 as - * follows : + * The IfHeader class represents the state lists defined through the HTTP If header, which is + * specified in RFC 2518 as follows : + * *

        *    If = "If" ":" ( 1*No-tag-list | 1*Tagged-list)
        *    No-tag-list = List
      @@ -43,10 +43,10 @@
        *    Coded-URL = "<" absoluteURI ">"
        * 
      *

      - * Reformulating this specification into proper EBNF as specified by N. Wirth - * we get the following productions, which map to the parse METHODS of this - * class. Any whitespace is ignored except for white space surrounding and - * within words which is considered significant. + * Reformulating this specification into proper EBNF as specified by N. Wirth we get the following productions, which + * map to the parse METHODS of this class. Any whitespace is ignored except for white space surrounding and within words + * which is considered significant. + * *

        *    If = "If:" ( Tagged | Untagged ).
        *    Tagged = { "<" Word ">" Untagged } .
      @@ -55,34 +55,25 @@
        *    Word = characters .
        * 
      *

      - * An If header either contains untagged IfList entries or - * tagged IfList entries but not a mixture of both. An If - * header containing tagged entries is said to be of tagged type while - * an If header containing untagged entries is said to be of - * untagged type. + * An If header either contains untagged IfList entries or tagged IfList entries but not a + * mixture of both. An If header containing tagged entries is said to be of tagged type while an + * If header containing untagged entries is said to be of untagged type. *

      - * An IfList is a list of tokens - words enclosed in < > - * - and etags - words enclosed in [ ]. An IfList matches a - * (token, etag) tuple if all entries in the list match. If an entry in the list - * is prefixed with the word Not (parsed case insensitively) the entry - * must not match the concrete token or etag. + * An IfList is a list of tokens - words enclosed in < > - and etags - words enclosed in [ + * ]. An IfList matches a (token, etag) tuple if all entries in the list match. If an entry in the list is + * prefixed with the word Not (parsed case insensitively) the entry must not match the concrete token or etag. *

      - * Example: The ifList (<token> [etag]) only matches - * if the concrete token has the value token and the concrete etag - * has the value etag. On the other hand, the ifList - * (Not <notoken>) matches any token which is not - * notoken (in this case the concrete value of the etag is - * not taken into consideration). + * Example: The ifList (<token> [etag]) only matches if the concrete token has the value + * token and the concrete etag has the value etag. On the other hand, the ifList + * (Not <notoken>) matches any token which is not notoken (in this case the concrete + * value of the etag is not taken into consideration). *

      * This class was contributed by Apache Jackrabbit - * - * @author Felix Meschberger */ public class WebdavIfHeader { private static final Log log = LogFactory.getLog(WebdavIfHeader.class); - private static final StringManager sm = - StringManager.getManager(WebdavIfHeader.class.getPackage().getName()); + private static final StringManager sm = StringManager.getManager(WebdavIfHeader.class.getPackage().getName()); /** * The string representation of the header value @@ -131,10 +122,9 @@ } /** - * Parses the If header and creates and internal representation - * which is easy to query. + * Parses the If header and creates and internal representation which is easy to query. * - * @param uriPrefix The uri prefix to use for the absolute href + * @param uriPrefix The uri prefix to use for the absolute href * @param ifHeaderValue the if header * * @throws IOException If the parsing of the IfHeader fails @@ -153,8 +143,7 @@ } /** - * Return the String representation of the If header present on - * the given request or null. + * Return the String representation of the If header present on the given request or null. * * @return If header value as String or null. */ @@ -165,32 +154,28 @@ /** * Returns true if an If header was present in the given request. False otherwise. * - * @return true if an If header was present. + * @return true if an If header was present. */ public boolean hasValue() { return ifHeader != null; } /** - * Tries to match the contents of the If header with the given - * token and etag values with the restriction to only check for the tag. + * Tries to match the contents of the If header with the given token and etag values with the restriction + * to only check for the tag. *

      - * If the If header is of untagged type, the untagged IfList - * is matched against the token and etag given: A match of the token and - * etag is found if at least one of the IfList entries match the - * token and etag tuple. + * If the If header is of untagged type, the untagged IfList is matched against the token and etag + * given: A match of the token and etag is found if at least one of the IfList entries match the token and + * etag tuple. * - * @param tag The tag to identify the IfList to match the token - * and etag against. + * @param tag The tag to identify the IfList to match the token and etag against. * @param tokens The tokens to compare. - * @param etag The ETag value to compare. + * @param etag The ETag value to compare. * - * @return If the If header is of untagged type the result is - * true if any of the IfList entries matches - * the token and etag values. For tagged type If header the - * result is true if either no entry for the given tag - * exists in the If header or if the IfList for the - * given tag matches the token and etag given. + * @return If the If header is of untagged type the result is true if any of the + * IfList entries matches the token and etag values. For tagged type If header the + * result is true if either no entry for the given tag exists in the If header or + * if the IfList for the given tag matches the token and etag given. */ public boolean matches(String tag, List tokens, String etag) { if (ifHeader == null) { @@ -211,27 +196,23 @@ } /** - * @return an iterator over all tokens present in the if header, that were - * not denied by a leading NOT statement. + * @return an iterator over all tokens present in the if header, that were not denied by a leading NOT statement. */ public Iterator getAllTokens() { return allTokens.iterator(); } /** - * @return an iterator over all NOT tokens present in the if header, that - * were explicitly denied. + * @return an iterator over all NOT tokens present in the if header, that were explicitly denied. */ public Iterator getAllNotTokens() { return allNotTokens.iterator(); } /** - * Parse the original header value and build the internal IfHeaderInterface - * object that is easy to query. + * Parse the original header value and build the internal IfHeaderInterface object that is easy to query. */ - private IfHeaderInterface parse() - throws IOException { + private IfHeaderInterface parse() throws IOException { IfHeaderInterface ifHeader; if (headerValue != null && !headerValue.isEmpty()) { @@ -243,8 +224,10 @@ firstChar = readWhiteSpace(reader); reader.reset(); } catch (IOException ignore) { - // may be thrown according to API but is only thrown by the - // StringReader class if the reader is already closed. + /* + * May be thrown according to API but is only thrown by the StringReader class if the reader is + * already closed. + */ } if (firstChar == '(') { @@ -266,19 +249,20 @@ return ifHeader; } - //---------- internal IF header parser ------------------------------------- + // ---------- internal IF header parser ------------------------------------- /** - * Parses a tagged type If header. This method implements the - * Tagged production given in the class comment : + * Parses a tagged type If header. This method implements the Tagged production given in the class + * comment : + * *

            *    Tagged = { "<" Word ">" Untagged } .
            * 
      * * @param reader the reader + * * @return the parsed map */ - private IfHeaderMap parseTagged(StringReader reader) - throws IOException { + private IfHeaderMap parseTagged(StringReader reader) throws IOException { IfHeaderMap map = new IfHeaderMap(); while (true) { // read next non-white space @@ -307,8 +291,9 @@ } /** - * Parses an untagged type If header. This method implements the - * Untagged production given in the class comment : + * Parses an untagged type If header. This method implements the Untagged production given in the + * class comment : + * *
            *    Untagged = { "(" IfList ")" } .
            * 
      @@ -317,8 +302,7 @@ * * @return An ArrayList of {@link IfList} entries. */ - private IfHeaderList parseUntagged(StringReader reader) - throws IOException { + private IfHeaderList parseUntagged(StringReader reader) throws IOException { IfHeaderList list = new IfHeaderList(); while (true) { // read next non whitespace @@ -347,8 +331,9 @@ } /** - * Parses an IfList in the If header. This method - * implements the Tagged production given in the class comment : + * Parses an IfList in the If header. This method implements the Tagged production given + * in the class comment : + * *
            *    IfList = { [ "Not" ] ( ("<" Word ">" ) | ( "[" Word "]" ) ) } .
            * 
      @@ -381,7 +366,7 @@ // check whether t or T not = reader.read(); - if (not !='t' && not != 'T') { + if (not != 't' && not != 'T') { logIllegalState("IfList-Not", not, "t", null); break; } @@ -438,8 +423,7 @@ } /** - * Returns the first non-whitespace character from the reader or -1 if - * the end of the reader is encountered. + * Returns the first non-whitespace character from the reader or -1 if the end of the reader is encountered. * * @param reader The Reader to read from * @@ -450,25 +434,22 @@ private int readWhiteSpace(Reader reader) throws IOException { int c = reader.read(); while (c >= 0 && Character.isWhitespace((char) c)) { - c = reader.read(); + c = reader.read(); } return c; } /** - * Reads from the input until the end character is encountered and returns - * the string up to but not including this end character. If the end of input - * is reached before reading the end character null is - * returned. + * Reads from the input until the end character is encountered and returns the string up to but not including this + * end character. If the end of input is reached before reading the end character null is returned. *

      * Note that this method does not support any escaping. * * @param reader The Reader to read from - * @param end The ending character limiting the word. + * @param end The ending character limiting the word. * - * @return The string read up to but not including the ending character or - * null if the end of input is reached before the ending - * character has been read. + * @return The string read up to but not including the ending character or null if the end of input is + * reached before the ending character has been read. * * @throws IOException if a problem occurs during reading. */ @@ -477,7 +458,7 @@ // read the word value int c = reader.read(); - for (; c >= 0 && c != end; c=reader.read()) { + for (; c >= 0 && c != end; c = reader.read()) { buf.append((char) c); } @@ -492,22 +473,18 @@ } /** - * Logs an unexpected character with the corresponding state and list of - * expected characters. If the reader parameter is not null, characters - * are read until either the end of the input is reached or any of the - * characters in the expChar string is read. - * - * @param state The name of the current parse state. This method logs this - * name in the message. The intended value would probably be the - * name of the EBNF production during which the error occurs. + * Logs an unexpected character with the corresponding state and list of expected characters. If the reader + * parameter is not null, characters are read until either the end of the input is reached or any of the characters + * in the expChar string is read. + * + * @param state The name of the current parse state. This method logs this name in the message. The intended value + * would probably be the name of the EBNF production during which the error occurs. * @param effChar The effective character read. * @param expChar The list of characters acceptable in the current state. - * @param reader The reader to be caught up to any of the expected - * characters. If null the input is not caught up to - * any of the expected characters (of course ;-). + * @param reader The reader to be caught up to any of the expected characters. If null the input is + * not caught up to any of the expected characters (of course ;-). */ - private void logIllegalState(String state, int effChar, String expChar, - StringReader reader) { + private void logIllegalState(String state, int effChar, String expChar, StringReader reader) { // format the effective character to be logged String effString = (effChar < 0) ? "" : String.valueOf((char) effChar); @@ -519,7 +496,7 @@ if (reader != null && effChar >= 0) { try { if (log.isTraceEnabled()) { - log.trace("logIllegalState: Catch up to any of "+expChar); + log.trace("logIllegalState: Catch up to any of " + expChar); } do { reader.mark(1); @@ -534,20 +511,17 @@ } } - //---------- internal If header structure ---------------------------------- + // ---------- internal If header structure ---------------------------------- /** - * The IfListEntry abstract class is the base class for - * entries in an IfList production. This abstract base class - * provides common functionality to both types of entries, namely tokens - * enclosed in angle brackets (< >) and etags enclosed - * in square brackets ([ ]). + * The IfListEntry abstract class is the base class for entries in an IfList production. This + * abstract base class provides common functionality to both types of entries, namely tokens enclosed in angle + * brackets (< >) and etags enclosed in square brackets ([ ]). */ private abstract static class IfListEntry { /** - * The entry string value - the semantics of this value depends on the - * implementing class. + * The entry string value - the semantics of this value depends on the implementing class. */ protected final String value; @@ -558,11 +532,10 @@ protected String stringValue; /** - * Sets up the final fields of this abstract class. The meaning of - * value parameter depends solely on the implementing class. From the - * point of view of this abstract class, it is simply a string value. + * Sets up the final fields of this abstract class. The meaning of value parameter depends solely on the + * implementing class. From the point of view of this abstract class, it is simply a string value. * - * @param value The string value of this instance + * @param value The string value of this instance * @param positive true if matches are positive */ protected IfListEntry(String value, boolean positive) { @@ -571,47 +544,39 @@ } /** - * Matches the value from the parameter to the internal string value. - * If the parameter and the {@link #value} field match, the method - * returns true for positive matches and false - * for negative matches. + * Matches the value from the parameter to the internal string value. If the parameter and the {@link #value} + * field match, the method returns true for positive matches and false for negative + * matches. *

      - * This helper method can be called by implementations to evaluate the - * concrete match on the correct value parameter. See - * {@link #match(String, String)} for the external API method. - * - * @param value The string value to compare to the {@link #value} - * field. - * - * @return true if the value parameter and the - * {@link #value} field match and the {@link #positive} field is - * true or if the values do not match and the - * {@link #positive} field is false. + * This helper method can be called by implementations to evaluate the concrete match on the correct value + * parameter. See {@link #match(String, String)} for the external API method. + * + * @param value The string value to compare to the {@link #value} field. + * + * @return true if the value parameter and the {@link #value} field match and the {@link #positive} + * field is true or if the values do not match and the {@link #positive} field is + * false. */ protected boolean match(String value) { return positive == this.value.equals(value); } /** - * Matches the entry's value to the token or etag. Depending on the - * concrete implementation, only one of the parameters may be evaluated - * while the other may be ignored. + * Matches the entry's value to the token or etag. Depending on the concrete implementation, only one of the + * parameters may be evaluated while the other may be ignored. *

      - * Implementing METHODS may call the helper method {@link #match(String)} - * for the actual matching. + * Implementing METHODS may call the helper method {@link #match(String)} for the actual matching. * * @param token The token value to compare - * @param etag The etag value to compare + * @param etag The etag value to compare * - * @return true if the token/etag matches the IfList - * entry. + * @return true if the token/etag matches the IfList entry. */ public abstract boolean match(String token, String etag); /** - * Returns a short type name for the implementation. This method is - * used by the {@link #toString} method to build the string representation - * if the instance. + * Returns a short type name for the implementation. This method is used by the {@link #toString} method to + * build the string representation if the instance. * * @return The type name of the implementation. */ @@ -625,8 +590,8 @@ } /** - * Returns the String representation of this entry. This method uses the - * {@link #getType} to build the string representation. + * Returns the String representation of this entry. This method uses the {@link #getType} to build the string + * representation. * * @return the String representation of this entry. */ @@ -640,15 +605,15 @@ } /** - * The IfListEntryToken extends the {@link IfListEntry} - * abstract class to represent an entry for token matching. + * The IfListEntryToken extends the {@link IfListEntry} abstract class to represent an entry for token + * matching. */ private static class IfListEntryToken extends IfListEntry { /** * Creates a token matching entry. * - * @param token The token value pertinent to this instance. + * @param token The token value pertinent to this instance. * @param positive true if this is a positive match entry. */ IfListEntryToken(String token, boolean positive) { @@ -656,17 +621,13 @@ } /** - * Matches the token parameter to the stored token value and returns - * true if the values match and if the match is positive. - * true is also returned for negative matches if the values - * do not match. + * Matches the token parameter to the stored token value and returns true if the values match and + * if the match is positive. true is also returned for negative matches if the values do not match. * * @param token The token value to compare - * @param etag The etag value to compare, which is ignored in this - * implementation. + * @param etag The etag value to compare, which is ignored in this implementation. * - * @return true if the token matches the IfList - * entry's token value. + * @return true if the token matches the IfList entry's token value. */ @Override public boolean match(String token, String etag) { @@ -674,8 +635,7 @@ } /** - * Returns the type name of this implementation, which is fixed to - * be Token. + * Returns the type name of this implementation, which is fixed to be Token. * * @return The fixed string Token as the type name. */ @@ -686,15 +646,15 @@ } /** - * The IfListEntryToken extends the {@link IfListEntry} - * abstract class to represent an entry for etag matching. + * The IfListEntryToken extends the {@link IfListEntry} abstract class to represent an entry for etag + * matching. */ private static class IfListEntryEtag extends IfListEntry { /** * Creates an etag matching entry. * - * @param etag The etag value pertinent to this instance. + * @param etag The etag value pertinent to this instance. * @param positive true if this is a positive match entry. */ IfListEntryEtag(String etag, boolean positive) { @@ -702,17 +662,13 @@ } /** - * Matches the etag parameter to the stored etag value and returns - * true if the values match and if the match is positive. - * true is also returned for negative matches if the values - * do not match. - * - * @param token The token value to compare, which is ignored in this - * implementation. - * @param etag The etag value to compare + * Matches the etag parameter to the stored etag value and returns true if the values match and if + * the match is positive. true is also returned for negative matches if the values do not match. * - * @return true if the etag matches the IfList - * entry's etag value. + * @param token The token value to compare, which is ignored in this implementation. + * @param etag The etag value to compare + * + * @return true if the etag matches the IfList entry's etag value. */ @Override public boolean match(String token, String etag) { @@ -720,8 +676,7 @@ } /** - * Returns the type name of this implementation, which is fixed to - * be ETag. + * Returns the type name of this implementation, which is fixed to be ETag. * * @return The fixed string ETag as the type name. */ @@ -732,12 +687,11 @@ } /** - * The IfList class extends the ArrayList class - * with the limitation to only support adding {@link IfListEntry} objects - * and adding a {@link #match} method. + * The IfList class extends the ArrayList class with the limitation to only support adding + * {@link IfListEntry} objects and adding a {@link #match} method. *

      - * This class is a container for data contained in the If - * production IfList + * This class is a container for data contained in the If production IfList + * *

            *    IfList = { [ "Not" ] ( ("<" Word ">" ) | ( "[" Word "]" ) ) } .
            * 
      @@ -765,8 +719,7 @@ * @param index the index * @param entry the entry * - * @throws IndexOutOfBoundsException if index is out of range - * (index < 0 || index > size()). + * @throws IndexOutOfBoundsException if index is out of range (index < 0 || index > size()). */ @Override public void add(int index, IfListEntry entry) { @@ -774,21 +727,19 @@ } /** - * Returns true if all {@link IfListEntry} objects in the - * list match the given token and etag. If the list is entry, it is - * considered to match the token and etag. + * Returns true if all {@link IfListEntry} objects in the list match the given token and etag. If + * the list is entry, it is considered to match the token and etag. * * @param tokens The token to compare. - * @param etag The etag to compare. + * @param etag The etag to compare. * - * @return true if all entries in the list match the - * given tag and token. + * @return true if all entries in the list match the given tag and token. */ public boolean match(List tokens, String etag) { if (log.isTraceEnabled()) { log.trace("match: Trying to match token=" + tokens + ", etag=" + etag); } - for (int i=0; i < size(); i++) { + for (int i = 0; i < size(); i++) { IfListEntry ile = get(i); boolean match = false; for (String token : tokens) { @@ -810,35 +761,31 @@ } /** - * The IfHeaderInterface interface abstracts away the difference of - * tagged and untagged If header lists. The single method provided - * by this interface is to check whether a request may be applied to a + * The IfHeaderInterface interface abstracts away the difference of tagged and untagged If + * header lists. The single method provided by this interface is to check whether a request may be applied to a * resource with given token and etag. */ private interface IfHeaderInterface { /** - * Matches the resource, token, and etag against this - * IfHeaderInterface instance. + * Matches the resource, token, and etag against this IfHeaderInterface instance. * - * @param resource The resource to match this instance against. This - * must be absolute URI of the resource as defined in Section 3 - * (URI Syntactic Components) of RFC 2396 Uniform Resource - * Identifiers (URI): Generic Syntax. - * @param tokens The resource's lock token to match - * @param etag The resource's etag to match - * - * @return true if the header matches the resource with - * token and etag, which means that the request is applicable - * to the resource according to the If header. + * @param resource The resource to match this instance against. This must be absolute URI of the resource as + * defined in Section 3 (URI Syntactic Components) of RFC 2396 Uniform Resource Identifiers + * (URI): Generic Syntax. + * @param tokens The resource's lock token to match + * @param etag The resource's etag to match + * + * @return true if the header matches the resource with token and etag, which means that the + * request is applicable to the resource according to the If header. */ boolean matches(String resource, List tokens, String etag); } /** - * The IfHeaderList class implements the {@link IfHeaderInterface} - * interface to support untagged lists of {@link IfList}s. This class - * implements the data container for the production : + * The IfHeaderList class implements the {@link IfHeaderInterface} interface to support untagged lists + * of {@link IfList}s. This class implements the data container for the production : + * *
            *    Untagged = { "(" IfList ")" } .
            * 
      @@ -848,19 +795,17 @@ private static final long serialVersionUID = 1L; /** - * Matches a list of {@link IfList}s against the token and etag. If any of - * the {@link IfList}s matches, the method returns true. - * On the other hand false is only returned if none of the + * Matches a list of {@link IfList}s against the token and etag. If any of the {@link IfList}s matches, the + * method returns true. On the other hand false is only returned if none of the * {@link IfList}s match. * - * @param resource The resource to match, which is ignored by this - * implementation. A value of null is therefor - * acceptable. - * @param tokens The tokens to compare. - * @param etag The ETag value to compare. + * @param resource The resource to match, which is ignored by this implementation. A value of null + * is therefor acceptable. + * @param tokens The tokens to compare. + * @param etag The ETag value to compare. * - * @return True if any of the {@link IfList}s matches the token - * and etag, else false is returned. + * @return True if any of the {@link IfList}s matches the token and etag, else false + * is returned. */ @Override public boolean matches(String resource, List tokens, String etag) { @@ -883,29 +828,27 @@ } /** - * The IfHeaderMap class implements the {@link IfHeaderInterface} - * interface to support tagged lists of {@link IfList}s. This class - * implements the data container for the production : + * The IfHeaderMap class implements the {@link IfHeaderInterface} interface to support tagged lists of + * {@link IfList}s. This class implements the data container for the production : + * *
            *    Tagged = { "<" Word ">" "(" IfList ")" } .
            * 
      */ - private class IfHeaderMap extends HashMap implements IfHeaderInterface { + private class IfHeaderMap extends HashMap implements IfHeaderInterface { private static final long serialVersionUID = 1L; /** - * Matches the token and etag for the given resource. If the resource is - * not mentioned in the header, a match is assumed and true - * is returned in this case. - * - * @param resource The absolute URI of the resource for which to find - * a match. - * @param tokens The tokens to compare. - * @param etag The etag to compare. + * Matches the token and etag for the given resource. If the resource is not mentioned in the header, a match is + * assumed and true is returned in this case. + * + * @param resource The absolute URI of the resource for which to find a match. + * @param tokens The tokens to compare. + * @param etag The etag to compare. * - * @return true if either no entry exists for the resource - * or if the entry for the resource matches the token and etag. + * @return true if either no entry exists for the resource or if the entry for the resource matches + * the token and etag. */ @Override public boolean matches(String resource, List tokens, String etag) { diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/http/fileupload/FileItem.java tomcat10-10.1.52/java/org/apache/tomcat/util/http/fileupload/FileItem.java --- tomcat10-10.1.40/java/org/apache/tomcat/util/http/fileupload/FileItem.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/http/fileupload/FileItem.java 2026-01-23 19:33:36.000000000 +0000 @@ -20,7 +20,6 @@ import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; -import java.io.UncheckedIOException; import java.io.UnsupportedEncodingException; /** @@ -47,18 +46,21 @@ */ public interface FileItem extends FileItemHeadersSupport { - // ------------------------------- Methods from javax.activation.DataSource + /** + * Deletes the underlying storage for a file item, including deleting any + * associated temporary disk file. Although this storage will be deleted + * automatically when the {@code FileItem} instance is garbage + * collected, this method can be used to ensure that this is done at an + * earlier time, thus preserving system resources. + */ + void delete(); /** - * Returns an {@link java.io.InputStream InputStream} that can be - * used to retrieve the contents of the file. - * - * @return An {@link java.io.InputStream InputStream} that can be - * used to retrieve the contents of the file. + * Returns the contents of the file item as an array of bytes. * - * @throws IOException if an error occurs. + * @return The contents of the file item as an array of bytes. */ - InputStream getInputStream() throws IOException; + byte[] get(); /** * Returns the content type passed by the browser or {@code null} if @@ -70,6 +72,25 @@ String getContentType(); /** + * Returns the name of the field in the multipart form corresponding to + * this file item. + * + * @return The name of the form field. + */ + String getFieldName(); + + /** + * Returns an {@link java.io.InputStream InputStream} that can be + * used to retrieve the contents of the file. + * + * @return An {@link java.io.InputStream InputStream} that can be + * used to retrieve the contents of the file. + * + * @throws IOException if an error occurs. + */ + InputStream getInputStream() throws IOException; + + /** * Returns the original file name in the client's file system, as provided by * the browser (or other client software). In most cases, this will be the * base file name, without path information. However, some clients, such as @@ -83,16 +104,16 @@ */ String getName(); - // ------------------------------------------------------- FileItem methods - /** - * Provides a hint as to whether or not the file contents will be read - * from memory. + * Returns an {@link java.io.OutputStream OutputStream} that can + * be used for storing the contents of the file. * - * @return {@code true} if the file contents will be read from memory; - * {@code false} otherwise. + * @return An {@link java.io.OutputStream OutputStream} that can be used + * for storing the contents of the file. + * + * @throws IOException if an error occurs. */ - boolean isInMemory(); + OutputStream getOutputStream() throws IOException; /** * Returns the size of the file item. @@ -102,13 +123,13 @@ long getSize(); /** - * Returns the contents of the file item as an array of bytes. - * - * @return The contents of the file item as an array of bytes. + * Returns the contents of the file item as a String, using the default + * character encoding. This method uses {@link #get()} to retrieve the + * contents of the item. * - * @throws UncheckedIOException if an I/O error occurs + * @return The contents of the item, as a string. */ - byte[] get() throws UncheckedIOException; + String getString(); /** * Returns the contents of the file item as a String, using the specified @@ -121,53 +142,26 @@ * * @throws UnsupportedEncodingException if the requested character * encoding is not available. - * @throws IOException if an I/O error occurs - */ - String getString(String encoding) throws UnsupportedEncodingException, IOException; - - /** - * Returns the contents of the file item as a String, using the default - * character encoding. This method uses {@link #get()} to retrieve the - * contents of the item. - * - * @return The contents of the item, as a string. */ - String getString(); + String getString(String encoding) throws UnsupportedEncodingException; /** - * A convenience method to write an uploaded item to disk. The client code - * is not concerned with whether or not the item is stored in memory, or on - * disk in a temporary location. They just want to write the uploaded item - * to a file. - *

      - * This method is not guaranteed to succeed if called more than once for - * the same item. This allows a particular implementation to use, for - * example, file renaming, where possible, rather than copying all of the - * underlying data, thus gaining a significant performance benefit. - * - * @param file The {@code File} into which the uploaded item should - * be stored. + * Determines whether or not a {@code FileItem} instance represents + * a simple form field. * - * @throws Exception if an error occurs. - */ - void write(File file) throws Exception; - - /** - * Deletes the underlying storage for a file item, including deleting any - * associated temporary disk file. Although this storage will be deleted - * automatically when the {@code FileItem} instance is garbage - * collected, this method can be used to ensure that this is done at an - * earlier time, thus preserving system resources. + * @return {@code true} if the instance represents a simple form + * field; {@code false} if it represents an uploaded file. */ - void delete(); + boolean isFormField(); /** - * Returns the name of the field in the multipart form corresponding to - * this file item. + * Provides a hint as to whether or not the file contents will be read + * from memory. * - * @return The name of the form field. + * @return {@code true} if the file contents will be read from memory; + * {@code false} otherwise. */ - String getFieldName(); + boolean isInMemory(); /** * Sets the field name used to reference this file item. @@ -177,15 +171,6 @@ void setFieldName(String name); /** - * Determines whether or not a {@code FileItem} instance represents - * a simple form field. - * - * @return {@code true} if the instance represents a simple form - * field; {@code false} if it represents an uploaded file. - */ - boolean isFormField(); - - /** * Specifies whether or not a {@code FileItem} instance represents * a simple form field. * @@ -195,14 +180,21 @@ void setFormField(boolean state); /** - * Returns an {@link java.io.OutputStream OutputStream} that can - * be used for storing the contents of the file. + * A convenience method to write an uploaded item to disk. The client code + * is not concerned with whether or not the item is stored in memory, or on + * disk in a temporary location. They just want to write the uploaded item + * to a file. + *

      + * This method is not guaranteed to succeed if called more than once for + * the same item. This allows a particular implementation to use, for + * example, file renaming, where possible, rather than copying all of the + * underlying data, thus gaining a significant performance benefit. * - * @return An {@link java.io.OutputStream OutputStream} that can be used - * for storing the contents of the file. + * @param file The {@code File} into which the uploaded item should + * be stored. * - * @throws IOException if an error occurs. + * @throws Exception if an error occurs. */ - OutputStream getOutputStream() throws IOException; + void write(File file) throws Exception; } diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/http/fileupload/FileItemHeaders.java tomcat10-10.1.52/java/org/apache/tomcat/util/http/fileupload/FileItemHeaders.java --- tomcat10-10.1.40/java/org/apache/tomcat/util/http/fileupload/FileItemHeaders.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/http/fileupload/FileItemHeaders.java 2026-01-23 19:33:36.000000000 +0000 @@ -44,6 +44,17 @@ /** *

      + * Returns an {@code Iterator} of all the header names. + *

      + * + * @return an {@code Iterator} containing all of the names of + * headers provided with this file item. If the item does not have + * any headers return an empty {@code Iterator} + */ + Iterator getHeaderNames(); + + /** + *

      * Returns all the values of the specified item header as an * {@code Iterator} of {@code String} objects. *

      @@ -60,15 +71,4 @@ */ Iterator getHeaders(String name); - /** - *

      - * Returns an {@code Iterator} of all the header names. - *

      - * - * @return an {@code Iterator} containing all of the names of - * headers provided with this file item. If the item does not have - * any headers return an empty {@code Iterator} - */ - Iterator getHeaderNames(); - } diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/http/fileupload/FileItemStream.java tomcat10-10.1.52/java/org/apache/tomcat/util/http/fileupload/FileItemStream.java --- tomcat10-10.1.40/java/org/apache/tomcat/util/http/fileupload/FileItemStream.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/http/fileupload/FileItemStream.java 2026-01-23 19:33:36.000000000 +0000 @@ -48,20 +48,14 @@ */ private static final long serialVersionUID = -7280778431581963740L; - } + /** + * Constructs a new instance. + */ + public ItemSkippedException() { + // empty + } - /** - * Creates an {@link InputStream}, which allows to read the - * items contents. - * - * @return The input stream, from which the items data may - * be read. - * @throws IllegalStateException The method was already invoked on - * this item. It is not possible to recreate the data stream. - * @throws IOException An I/O error occurred. - * @see ItemSkippedException - */ - InputStream openStream() throws IOException; + } /** * Returns the content type passed by the browser or {@code null} if @@ -73,6 +67,14 @@ String getContentType(); /** + * Returns the name of the field in the multipart form corresponding to + * this file item. + * + * @return The name of the form field. + */ + String getFieldName(); + + /** * Returns the original file name in the client's file system, as provided by * the browser (or other client software). In most cases, this will be the * base file name, without path information. However, some clients, such as @@ -83,14 +85,6 @@ String getName(); /** - * Returns the name of the field in the multipart form corresponding to - * this file item. - * - * @return The name of the form field. - */ - String getFieldName(); - - /** * Determines whether or not a {@code FileItem} instance represents * a simple form field. * @@ -99,4 +93,17 @@ */ boolean isFormField(); + /** + * Creates an {@link InputStream}, which allows to read the + * items contents. + * + * @return The input stream, from which the items data may + * be read. + * @throws IllegalStateException The method was already invoked on + * this item. It is not possible to recreate the data stream. + * @throws IOException An I/O error occurred. + * @see ItemSkippedException + */ + InputStream openStream() throws IOException; + } diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/http/fileupload/FileUpload.java tomcat10-10.1.52/java/org/apache/tomcat/util/http/fileupload/FileUpload.java --- tomcat10-10.1.40/java/org/apache/tomcat/util/http/fileupload/FileUpload.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/http/fileupload/FileUpload.java 2026-01-23 19:33:36.000000000 +0000 @@ -33,15 +33,11 @@ public class FileUpload extends FileUploadBase { - // ----------------------------------------------------------- Data members - /** * The factory to use to create new form items. */ private FileItemFactory fileItemFactory; - // ----------------------------------------------------------- Constructors - /** * Constructs an uninitialized instance of this class. * @@ -52,8 +48,6 @@ public FileUpload() { } - // ----------------------------------------------------- Property accessors - /** * Returns the factory class used when creating file items. * @@ -67,11 +61,11 @@ /** * Sets the factory class to use when creating file items. * - * @param factory The factory class for new file items. + * @param fileItemFactory The factory class for new file items. */ @Override - public void setFileItemFactory(final FileItemFactory factory) { - this.fileItemFactory = factory; + public void setFileItemFactory(final FileItemFactory fileItemFactory) { + this.fileItemFactory = fileItemFactory; } } diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/http/fileupload/FileUploadBase.java tomcat10-10.1.52/java/org/apache/tomcat/util/http/fileupload/FileUploadBase.java --- tomcat10-10.1.40/java/org/apache/tomcat/util/http/fileupload/FileUploadBase.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/http/fileupload/FileUploadBase.java 2026-01-23 19:33:36.000000000 +0000 @@ -33,9 +33,10 @@ /** - *

      High level API for processing file uploads.

      + * High level API for processing file uploads. * - *

      This class handles multiple files per single HTML widget, sent using + *

      + * This class handles multiple files per single HTML widget, sent using * {@code multipart/mixed} encoding type, as specified by * RFC 1867. Use {@link * #parseRequest(RequestContext)} to acquire a list of {@link @@ -48,7 +49,15 @@ */ public abstract class FileUploadBase { - // ----------------------------------------------------- Manifest constants + /** + * Line feed. + */ + private static final char LF = '\n'; + + /** + * Carriage return. + */ + private static final char CR = '\r'; /** * HTTP content type header name. @@ -90,7 +99,12 @@ */ public static final String MULTIPART_MIXED = "multipart/mixed"; - // ----------------------------------------------------------- Data members + /** + * Default per part header size limit in bytes. + * + * @since FileUpload 1.6.0 + */ + public static final int DEFAULT_PART_HEADER_SIZE_MAX = 512; /** * The maximum size permitted for the complete request, as opposed to @@ -111,6 +125,11 @@ private long fileCountMax = -1; /** + * The maximum permitted size of the headers provided with a single part in bytes. + */ + private int partHeaderSizeMax = DEFAULT_PART_HEADER_SIZE_MAX; + + /** * The content encoding to use when reading part headers. */ private String headerEncoding; @@ -120,70 +139,65 @@ */ private ProgressListener listener; - // ----------------------------------------------------- Property accessors - /** - * Returns the factory class used when creating file items. - * - * @return The factory class for new file items. + * Constructs a new instance. */ - public abstract FileItemFactory getFileItemFactory(); - - /** - * Sets the factory class to use when creating file items. - * - * @param factory The factory class for new file items. - */ - public abstract void setFileItemFactory(FileItemFactory factory); - - /** - * Returns the maximum allowed size of a complete request, as opposed - * to {@link #getFileSizeMax()}. - * - * @return The maximum allowed size, in bytes. The default value of - * -1 indicates, that there is no limit. - * - * @see #setSizeMax(long) - * - */ - public long getSizeMax() { - return sizeMax; + public FileUploadBase() { + // empty } /** - * Sets the maximum allowed size of a complete request, as opposed - * to {@link #setFileSizeMax(long)}. - * - * @param sizeMax The maximum allowed size, in bytes. The default value of - * -1 indicates, that there is no limit. + * Gets the boundary from the {@code Content-type} header. * - * @see #getSizeMax() + * @param contentType The value of the content type header from which to + * extract the boundary value. * + * @return The boundary, as a byte array. */ - public void setSizeMax(final long sizeMax) { - this.sizeMax = sizeMax; + public byte[] getBoundary(final String contentType) { + final ParameterParser parser = new ParameterParser(); + parser.setLowerCaseNames(true); + // Parameter parser can handle null input + final Map params = parser.parse(contentType, new char[] {';', ','}); + final String boundaryStr = params.get("boundary"); + + if (boundaryStr == null) { + return null; + } + return boundaryStr.getBytes(StandardCharsets.ISO_8859_1); } /** - * Returns the maximum allowed size of a single uploaded file, - * as opposed to {@link #getSizeMax()}. + * Gets the field name from the {@code Content-disposition} + * header. * - * @see #setFileSizeMax(long) - * @return Maximum size of a single uploaded file. + * @param headers A {@code Map} containing the HTTP request headers. + * + * @return The field name for the current {@code encapsulation}. */ - public long getFileSizeMax() { - return fileSizeMax; + public String getFieldName(final FileItemHeaders headers) { + return getFieldName(headers.getHeader(CONTENT_DISPOSITION)); } /** - * Sets the maximum allowed size of a single uploaded file, - * as opposed to {@link #getSizeMax()}. - * - * @see #getFileSizeMax() - * @param fileSizeMax Maximum size of a single uploaded file. + * Returns the field name, which is given by the content-disposition + * header. + * @param contentDisposition The content-dispositions header value. + * @return The field name. */ - public void setFileSizeMax(final long fileSizeMax) { - this.fileSizeMax = fileSizeMax; + private String getFieldName(final String contentDisposition) { + String fieldName = null; + if (contentDisposition != null && contentDisposition.toLowerCase(Locale.ROOT).startsWith(FORM_DATA)) { + final ParameterParser parser = new ParameterParser(); + parser.setLowerCaseNames(true); + // Parameter parser can handle null input + final Map params = parser.parse(contentDisposition, ';'); + fieldName = params.get("name"); + if (fieldName != null) { + fieldName = fieldName.trim(); + } + } + return fieldName; } /** @@ -196,155 +210,14 @@ } /** - * Sets the maximum number of files allowed per request. - * - * @param fileCountMax The new limit. {@code -1} means no limit. - */ - public void setFileCountMax(final long fileCountMax) { - this.fileCountMax = fileCountMax; - } - - /** - * Retrieves the character encoding used when reading the headers of an - * individual part. When not specified, or {@code null}, the request - * encoding is used. If that is also not specified, or {@code null}, - * the platform default encoding is used. - * - * @return The encoding used to read part headers. - */ - public String getHeaderEncoding() { - return headerEncoding; - } - - /** - * Specifies the character encoding to be used when reading the headers of - * individual part. When not specified, or {@code null}, the request - * encoding is used. If that is also not specified, or {@code null}, - * the platform default encoding is used. - * - * @param encoding The encoding used to read part headers. - */ - public void setHeaderEncoding(final String encoding) { - headerEncoding = encoding; - } - - // --------------------------------------------------------- Public methods - - /** - * Processes an RFC 1867 - * compliant {@code multipart/form-data} stream. - * - * @param ctx The context for the request to be parsed. - * - * @return An iterator to instances of {@code FileItemStream} - * parsed from the request, in the order that they were - * transmitted. - * - * @throws FileUploadException if there are problems reading/parsing - * the request or storing files. - * @throws IOException An I/O error occurred. This may be a network - * error while communicating with the client or a problem while - * storing the uploaded content. - */ - public FileItemIterator getItemIterator(final RequestContext ctx) - throws FileUploadException, IOException { - try { - return new FileItemIteratorImpl(this, ctx); - } catch (final FileUploadIOException e) { - // unwrap encapsulated SizeException - throw (FileUploadException) e.getCause(); - } - } - - /** - * Processes an RFC 1867 - * compliant {@code multipart/form-data} stream. - * - * @param ctx The context for the request to be parsed. - * - * @return A list of {@code FileItem} instances parsed from the - * request, in the order that they were transmitted. - * - * @throws FileUploadException if there are problems reading/parsing - * the request or storing files. - */ - public List parseRequest(final RequestContext ctx) - throws FileUploadException { - final List items = new ArrayList<>(); - boolean successful = false; - try { - final FileItemIterator iter = getItemIterator(ctx); - final FileItemFactory fileItemFactory = Objects.requireNonNull(getFileItemFactory(), - "No FileItemFactory has been set."); - final byte[] buffer = new byte[Streams.DEFAULT_BUFFER_SIZE]; - while (iter.hasNext()) { - if (items.size() == fileCountMax) { - // The next item will exceed the limit. - throw new FileCountLimitExceededException(ATTACHMENT, getFileCountMax()); - } - final FileItemStream item = iter.next(); - // Don't use getName() here to prevent an InvalidFileNameException. - final String fileName = item.getName(); - final FileItem fileItem = fileItemFactory.createItem(item.getFieldName(), item.getContentType(), - item.isFormField(), fileName); - items.add(fileItem); - try { - Streams.copy(item.openStream(), fileItem.getOutputStream(), true, buffer); - } catch (final FileUploadIOException e) { - throw (FileUploadException) e.getCause(); - } catch (final IOException e) { - throw new IOFileUploadException(String.format("Processing of %s request failed. %s", - MULTIPART_FORM_DATA, e.getMessage()), e); - } - final FileItemHeaders fih = item.getHeaders(); - fileItem.setHeaders(fih); - } - successful = true; - return items; - } catch (final FileUploadException e) { - throw e; - } catch (final IOException e) { - throw new FileUploadException(e.getMessage(), e); - } finally { - if (!successful) { - for (final FileItem fileItem : items) { - try { - fileItem.delete(); - } catch (final Exception ignored) { - // ignored TODO perhaps add to tracker delete failure list somehow? - } - } - } - } - } - - // ------------------------------------------------------ Protected methods - - /** - * Retrieves the boundary from the {@code Content-type} header. - * - * @param contentType The value of the content type header from which to - * extract the boundary value. + * Returns the factory class used when creating file items. * - * @return The boundary, as a byte array. + * @return The factory class for new file items. */ - public byte[] getBoundary(final String contentType) { - final ParameterParser parser = new ParameterParser(); - parser.setLowerCaseNames(true); - // Parameter parser can handle null input - final Map params = parser.parse(contentType, new char[] {';', ','}); - final String boundaryStr = params.get("boundary"); - - if (boundaryStr == null) { - return null; - } - final byte[] boundary; - boundary = boundaryStr.getBytes(StandardCharsets.ISO_8859_1); - return boundary; - } + public abstract FileItemFactory getFileItemFactory(); /** - * Retrieves the file name from the {@code Content-disposition} + * Gets the file name from the {@code Content-disposition} * header. * * @param headers The HTTP headers object. @@ -357,18 +230,18 @@ /** * Returns the given content-disposition headers file name. - * @param pContentDisposition The content-disposition headers value. + * @param contentDisposition The content-disposition headers value. * @return The file name */ - private String getFileName(final String pContentDisposition) { + private String getFileName(final String contentDisposition) { String fileName = null; - if (pContentDisposition != null) { - final String cdl = pContentDisposition.toLowerCase(Locale.ENGLISH); + if (contentDisposition != null) { + final String cdl = contentDisposition.toLowerCase(Locale.ROOT); if (cdl.startsWith(FORM_DATA) || cdl.startsWith(ATTACHMENT)) { final ParameterParser parser = new ParameterParser(); parser.setLowerCaseNames(true); // Parameter parser can handle null input - final Map params = parser.parse(pContentDisposition, ';'); + final Map params = parser.parse(contentDisposition, ';'); if (params.containsKey("filename")) { fileName = params.get("filename"); if (fileName != null) { @@ -386,37 +259,52 @@ } /** - * Retrieves the field name from the {@code Content-disposition} - * header. + * Returns the maximum allowed size of a single uploaded file, + * as opposed to {@link #getSizeMax()}. * - * @param headers A {@code Map} containing the HTTP request headers. + * @see #setFileSizeMax(long) + * @return Maximum size of a single uploaded file. + */ + public long getFileSizeMax() { + return fileSizeMax; + } + + /** + * Gets the character encoding used when reading the headers of an + * individual part. When not specified, or {@code null}, the request + * encoding is used. If that is also not specified, or {@code null}, + * the platform default encoding is used. * - * @return The field name for the current {@code encapsulation}. + * @return The encoding used to read part headers. */ - public String getFieldName(final FileItemHeaders headers) { - return getFieldName(headers.getHeader(CONTENT_DISPOSITION)); + public String getHeaderEncoding() { + return headerEncoding; } /** - * Returns the field name, which is given by the content-disposition - * header. - * @param pContentDisposition The content-dispositions header value. - * @return The field jake + * Processes an RFC 1867 + * compliant {@code multipart/form-data} stream. + * + * @param ctx The context for the request to be parsed. + * + * @return An iterator to instances of {@code FileItemStream} + * parsed from the request, in the order that they were + * transmitted. + * + * @throws FileUploadException if there are problems reading/parsing + * the request or storing files. + * @throws IOException An I/O error occurred. This may be a network + * error while communicating with the client or a problem while + * storing the uploaded content. */ - private String getFieldName(final String pContentDisposition) { - String fieldName = null; - if (pContentDisposition != null - && pContentDisposition.toLowerCase(Locale.ENGLISH).startsWith(FORM_DATA)) { - final ParameterParser parser = new ParameterParser(); - parser.setLowerCaseNames(true); - // Parameter parser can handle null input - final Map params = parser.parse(pContentDisposition, ';'); - fieldName = params.get("name"); - if (fieldName != null) { - fieldName = fieldName.trim(); - } + public FileItemIterator getItemIterator(final RequestContext ctx) + throws FileUploadException, IOException { + try { + return new FileItemIteratorImpl(this, ctx); + } catch (final FileUploadIOException e) { + // unwrap encapsulated SizeException + throw (FileUploadException) e.getCause(); } - return fieldName; } /** @@ -465,6 +353,40 @@ } /** + * Obtain the per part size limit for headers. + * + * @return The maximum size of the headers for a single part in bytes. + * + * @since FileUpload 1.6.0 + */ + public int getPartHeaderSizeMax() { + return partHeaderSizeMax; + } + + /** + * Returns the progress listener. + * + * @return The progress listener, if any, or null. + */ + public ProgressListener getProgressListener() { + return listener; + } + + /** + * Returns the maximum allowed size of a complete request, as opposed + * to {@link #getFileSizeMax()}. + * + * @return The maximum allowed size, in bytes. The default value of + * -1 indicates, that there is no limit. + * + * @see #setSizeMax(long) + * + */ + public long getSizeMax() { + return sizeMax; + } + + /** * Creates a new instance of {@link FileItemHeaders}. * @return The new instance. */ @@ -483,12 +405,12 @@ private int parseEndOfLine(final String headerPart, final int end) { int index = end; for (;;) { - final int offset = headerPart.indexOf('\r', index); + final int offset = headerPart.indexOf(CR, index); if (offset == -1 || offset + 1 >= headerPart.length()) { throw new IllegalStateException( "Expected headers to be terminated by an empty line."); } - if (headerPart.charAt(offset + 1) == '\n') { + if (headerPart.charAt(offset + 1) == LF) { return offset; } index = offset + 1; @@ -512,21 +434,137 @@ } /** - * Returns the progress listener. + * Processes an RFC 1867 + * compliant {@code multipart/form-data} stream. * - * @return The progress listener, if any, or null. + * @param ctx The context for the request to be parsed. + * + * @return A list of {@code FileItem} instances parsed from the + * request, in the order that they were transmitted. + * + * @throws FileUploadException if there are problems reading/parsing + * the request or storing files. */ - public ProgressListener getProgressListener() { - return listener; + public List parseRequest(final RequestContext ctx) throws FileUploadException { + final List items = new ArrayList<>(); + boolean successful = false; + try { + final FileItemIterator iter = getItemIterator(ctx); + final FileItemFactory fileItemFactory = getFileItemFactory(); + Objects.requireNonNull(fileItemFactory, "getFileItemFactory()"); + final byte[] buffer = new byte[Streams.DEFAULT_BUFFER_SIZE]; + while (iter.hasNext()) { + if (items.size() == fileCountMax) { + // The next item will exceed the limit. + throw new FileCountLimitExceededException(ATTACHMENT, getFileCountMax()); + } + final FileItemStream item = iter.next(); + // Don't use getName() here to prevent an InvalidFileNameException. + final String fileName = item.getName(); + final FileItem fileItem = fileItemFactory.createItem(item.getFieldName(), item.getContentType(), + item.isFormField(), fileName); + items.add(fileItem); + try { + Streams.copy(item.openStream(), fileItem.getOutputStream(), true, buffer); + } catch (final FileUploadIOException e) { + throw (FileUploadException) e.getCause(); + } catch (final IOException e) { + throw new IOFileUploadException(String.format("Processing of %s request failed. %s", + MULTIPART_FORM_DATA, e.getMessage()), e); + } + final FileItemHeaders fih = item.getHeaders(); + fileItem.setHeaders(fih); + } + successful = true; + return items; + } catch (final FileUploadException e) { + throw e; + } catch (final IOException e) { + throw new FileUploadException(e.getMessage(), e); + } finally { + if (!successful) { + for (final FileItem fileItem : items) { + try { + fileItem.delete(); + } catch (final Exception ignored) { + // ignored TODO perhaps add to tracker delete failure list somehow? + } + } + } + } + } + + /** + * Sets the maximum number of files allowed per request. + * + * @param fileCountMax The new limit. {@code -1} means no limit. + */ + public void setFileCountMax(final long fileCountMax) { + this.fileCountMax = fileCountMax; + } + + /** + * Sets the factory class to use when creating file items. + * + * @param factory The factory class for new file items. + */ + public abstract void setFileItemFactory(FileItemFactory factory); + + /** + * Sets the maximum allowed size of a single uploaded file, + * as opposed to {@link #getSizeMax()}. + * + * @see #getFileSizeMax() + * @param fileSizeMax Maximum size of a single uploaded file. + */ + public void setFileSizeMax(final long fileSizeMax) { + this.fileSizeMax = fileSizeMax; + } + + /** + * Specifies the character encoding to be used when reading the headers of + * individual part. When not specified, or {@code null}, the request + * encoding is used. If that is also not specified, or {@code null}, + * the platform default encoding is used. + * + * @param encoding The encoding used to read part headers. + */ + public void setHeaderEncoding(final String encoding) { + headerEncoding = encoding; + } + + /** + * Sets the per part size limit for headers. + * + * @param partHeaderSizeMax The maximum size of the headers in bytes. + * + * @since FileUpload 1.6.0 + */ + public void setPartHeaderSizeMax(final int partHeaderSizeMax) { + this.partHeaderSizeMax = partHeaderSizeMax; } /** * Sets the progress listener. * - * @param pListener The progress listener, if any. Defaults to null. + * @param listener The progress listener, if any. Defaults to null. + */ + public void setProgressListener(final ProgressListener listener) { + this.listener = listener; + } + + /** + * Sets the maximum allowed size of a complete request, as opposed + * to {@link #setFileSizeMax(long)}. + * + * @param sizeMax The maximum allowed size, in bytes. The default value of + * -1 indicates, that there is no limit. + * + * @see #getSizeMax() + * */ - public void setProgressListener(final ProgressListener pListener) { - listener = pListener; + public void setSizeMax(final long sizeMax) { + this.sizeMax = sizeMax; } } diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/http/fileupload/FileUploadException.java tomcat10-10.1.52/java/org/apache/tomcat/util/http/fileupload/FileUploadException.java --- tomcat10-10.1.40/java/org/apache/tomcat/util/http/fileupload/FileUploadException.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/http/fileupload/FileUploadException.java 2026-01-23 19:33:36.000000000 +0000 @@ -36,20 +36,20 @@ * Constructs a new {@code FileUploadException} with specified detail * message. * - * @param msg the error message. + * @param message the error message. */ - public FileUploadException(final String msg) { - super(msg); + public FileUploadException(final String message) { + super(message); } /** * Creates a new {@code FileUploadException} with the given * detail message and cause. * - * @param msg The exceptions detail message. + * @param message The exceptions detail message. * @param cause The exceptions cause. */ - public FileUploadException(final String msg, final Throwable cause) { - super(msg, cause); + public FileUploadException(final String message, final Throwable cause) { + super(message, cause); } } diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/http/fileupload/InvalidFileNameException.java tomcat10-10.1.52/java/org/apache/tomcat/util/http/fileupload/InvalidFileNameException.java --- tomcat10-10.1.40/java/org/apache/tomcat/util/http/fileupload/InvalidFileNameException.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/http/fileupload/InvalidFileNameException.java 2026-01-23 19:33:36.000000000 +0000 @@ -42,12 +42,12 @@ /** * Creates a new instance. * - * @param pName The file name causing the exception. - * @param pMessage A human readable error message. + * @param name The file name causing the exception. + * @param message A human readable error message. */ - public InvalidFileNameException(final String pName, final String pMessage) { - super(pMessage); - name = pName; + public InvalidFileNameException(final String name, final String message) { + super(message); + this.name = name; } /** diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/http/fileupload/MultipartStream.java tomcat10-10.1.52/java/org/apache/tomcat/util/http/fileupload/MultipartStream.java --- tomcat10-10.1.40/java/org/apache/tomcat/util/http/fileupload/MultipartStream.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/http/fileupload/MultipartStream.java 2026-01-23 19:33:36.000000000 +0000 @@ -23,11 +23,12 @@ import java.io.UnsupportedEncodingException; import org.apache.tomcat.util.http.fileupload.impl.FileUploadIOException; +import org.apache.tomcat.util.http.fileupload.impl.SizeLimitExceededException; import org.apache.tomcat.util.http.fileupload.util.Closeable; import org.apache.tomcat.util.http.fileupload.util.Streams; /** - *

      Low level API for processing file uploads. + * Low level API for processing file uploads. * *

      This class can be used to process data streams conforming to MIME * 'multipart' format as defined in @@ -58,7 +59,9 @@ * boundary token of the same length as the parent stream (see {@link * #setBoundary(byte[])}). * - *

      Here is an example of usage of this class.
      + *

      + * Here is an example of usage of this class. + *

      * *
        *   try {
      @@ -74,7 +77,7 @@
        *     }
        *   } catch(MultipartStream.MalformedStreamException e) {
        *     // the stream failed to follow required syntax
      - *   } catch(IOException e) {
      + *   } catch(IOException ioe) {
        *     // a read or write error occurred
        *   }
        * 
      @@ -82,6 +85,316 @@ public class MultipartStream { /** + * Thrown upon attempt of setting an invalid boundary token. + */ + public static class IllegalBoundaryException extends IOException { + + /** + * The UID to use when serializing this instance. + */ + private static final long serialVersionUID = -161533165102632918L; + + /** + * Constructs an {@code IllegalBoundaryException} with no + * detail message. + */ + public IllegalBoundaryException() { + } + + /** + * Constructs an {@code IllegalBoundaryException} with + * the specified detail message. + * + * @param message The detail message. + */ + public IllegalBoundaryException(final String message) { + super(message); + } + + } + + /** + * An {@link InputStream} for reading an items contents. + */ + public class ItemInputStream extends InputStream implements Closeable { + + /** + * Offset when converting negative bytes to integers. + */ + private static final int BYTE_POSITIVE_OFFSET = 256; + + /** + * The number of bytes, which have been read so far. + */ + private long total; + + /** + * The number of bytes, which must be hold, because + * they might be a part of the boundary. + */ + private int pad; + + /** + * The current offset in the buffer. + */ + private int pos; + + /** + * Whether the stream is already closed. + */ + private boolean closed; + + /** + * Creates a new instance. + */ + ItemInputStream() { + findSeparator(); + } + + /** + * Returns the number of bytes, which are currently + * available, without blocking. + * + * @throws IOException An I/O error occurs. + * @return Number of bytes in the buffer. + */ + @Override + public int available() throws IOException { + if (pos == -1) { + return tail - head - pad; + } + return pos - head; + } + + /** + * Closes the input stream. + * + * @throws IOException An I/O error occurred. + */ + @Override + public void close() throws IOException { + close(false); + } + + /** + * Closes the input stream. + * + * @param closeUnderlying Whether to close the underlying stream (hard close) + * @throws IOException An I/O error occurred. + */ + public void close(final boolean closeUnderlying) throws IOException { + if (closed) { + return; + } + if (closeUnderlying) { + closed = true; + input.close(); + } else { + for (;;) { + int available = available(); + if (available == 0) { + available = makeAvailable(); + if (available == 0) { + break; + } + } + if (skip(available) != available) { + // TODO log or throw? + } + } + } + closed = true; + } + + /** + * Called for finding the separator. + */ + private void findSeparator() { + pos = MultipartStream.this.findSeparator(); + if (pos == -1) { + if (tail - head > keepRegion) { + pad = keepRegion; + } else { + pad = tail - head; + } + } + } + + /** + * Returns the number of bytes, which have been read + * by the stream. + * + * @return Number of bytes, which have been read so far. + */ + public long getBytesRead() { + return total; + } + + /** + * Returns, whether the stream is closed. + * + * @return True, if the stream is closed, otherwise false. + */ + @Override + public boolean isClosed() { + return closed; + } + + /** + * Attempts to read more data. + * + * @return Number of available bytes + * @throws IOException An I/O error occurred. + */ + private int makeAvailable() throws IOException { + if (pos != -1) { + return 0; + } + + // Move the data to the beginning of the buffer. + total += tail - head - pad; + System.arraycopy(buffer, tail - pad, buffer, 0, pad); + + // Refill buffer with new data. + head = 0; + tail = pad; + + for (;;) { + final int bytesRead = input.read(buffer, tail, bufSize - tail); + if (bytesRead == -1) { + // The last pad amount is left in the buffer. + // Boundary can't be in there so signal an error + // condition. + final String msg = "Stream ended unexpectedly"; + throw new MalformedStreamException(msg); + } + if (notifier != null) { + notifier.noteBytesRead(bytesRead); + } + tail += bytesRead; + + findSeparator(); + final int av = available(); + + if (av > 0 || pos != -1) { + return av; + } + } + } + + /** + * Returns the next byte in the stream. + * + * @return The next byte in the stream, as a non-negative + * integer, or -1 for EOF. + * @throws IOException An I/O error occurred. + */ + @Override + public int read() throws IOException { + if (closed) { + throw new FileItemStream.ItemSkippedException(); + } + if (available() == 0 && makeAvailable() == 0) { + return -1; + } + ++total; + final int b = buffer[head++]; + if (b >= 0) { + return b; + } + return b + BYTE_POSITIVE_OFFSET; + } + + /** + * Reads bytes into the given buffer. + * + * @param b The destination buffer, where to write to. + * @param off Offset of the first byte in the buffer. + * @param len Maximum number of bytes to read. + * @return Number of bytes, which have been actually read, + * or -1 for EOF. + * @throws IOException An I/O error occurred. + */ + @Override + public int read(final byte[] b, final int off, final int len) throws IOException { + if (closed) { + throw new FileItemStream.ItemSkippedException(); + } + if (len == 0) { + return 0; + } + int res = available(); + if (res == 0) { + res = makeAvailable(); + if (res == 0) { + return -1; + } + } + res = Math.min(res, len); + System.arraycopy(buffer, head, b, off, res); + head += res; + total += res; + return res; + } + + /** + * Skips the given number of bytes. + * + * @param bytes Number of bytes to skip. + * @return The number of bytes, which have actually been + * skipped. + * @throws IOException An I/O error occurred. + */ + @Override + public long skip(final long bytes) throws IOException { + if (closed) { + throw new FileItemStream.ItemSkippedException(); + } + int av = available(); + if (av == 0) { + av = makeAvailable(); + if (av == 0) { + return 0; + } + } + final long res = Math.min(av, bytes); + head += res; + return res; + } + + } + + /** + * Thrown to indicate that the input stream fails to follow the + * required syntax. + */ + public static class MalformedStreamException extends IOException { + + /** + * The UID to use when serializing this instance. + */ + private static final long serialVersionUID = 6466926458059796677L; + + /** + * Constructs a {@code MalformedStreamException} with no + * detail message. + */ + public MalformedStreamException() { + } + + /** + * Constructs an {@code MalformedStreamException} with + * the specified detail message. + * + * @param message The detail message. + */ + public MalformedStreamException(final String message) { + super(message); + } + + } + + /** * Internal class, which is used to invoke the * {@link ProgressListener}. */ @@ -111,24 +424,24 @@ * Creates a new instance with the given listener * and content length. * - * @param pListener The listener to invoke. - * @param pContentLength The expected content length. + * @param listener The listener to invoke. + * @param contentLength The expected content length. */ - public ProgressNotifier(final ProgressListener pListener, final long pContentLength) { - listener = pListener; - contentLength = pContentLength; + public ProgressNotifier(final ProgressListener listener, final long contentLength) { + this.listener = listener; + this.contentLength = contentLength; } /** * Called to indicate that bytes have been read. * - * @param pBytes Number of bytes, which have been read. + * @param count Number of bytes, which have been read. */ - void noteBytesRead(final int pBytes) { + void noteBytesRead(final int count) { /* Indicates, that the given number of bytes have been read from * the input stream. */ - bytesRead += pBytes; + bytesRead += count; notifyListener(); } @@ -151,8 +464,6 @@ } - // ----------------------------------------------------- Manifest constants - /** * The Carriage Return ASCII character value. */ @@ -169,12 +480,6 @@ public static final byte DASH = 0x2D; /** - * The maximum length of {@code header-part} that will be - * processed (10 kilobytes = 10240 bytes.). - */ - public static final int HEADER_PART_SIZE_MAX = 10240; - - /** * The default length of the buffer used for processing a request. */ protected static final int DEFAULT_BUFSIZE = 4096; @@ -186,13 +491,13 @@ protected static final byte[] HEADER_SEPARATOR = {CR, LF, CR, LF}; /** - * A byte sequence that that follows a delimiter that will be + * A byte sequence that follows a delimiter that will be * followed by an encapsulation ({@code CRLF}). */ protected static final byte[] FIELD_SEPARATOR = {CR, LF}; /** - * A byte sequence that that follows a delimiter of the last + * A byte sequence that follows a delimiter of the last * encapsulation in the stream ({@code --}). */ protected static final byte[] STREAM_TERMINATOR = {DASH, DASH}; @@ -202,7 +507,27 @@ */ protected static final byte[] BOUNDARY_PREFIX = {CR, LF, DASH, DASH}; - // ----------------------------------------------------------- Data members + /** + * Compares {@code count} first bytes in the arrays + * {@code a} and {@code b}. + * + * @param a The first array to compare. + * @param b The second array to compare. + * @param count How many bytes should be compared. + * + * @return {@code true} if {@code count} first bytes in arrays + * {@code a} and {@code b} are equal. + */ + public static boolean arrayequals(final byte[] a, + final byte[] b, + final int count) { + for (int i = 0; i < count; i++) { + if (a[i] != b[i]) { + return false; + } + } + return true; + } /** * The input stream from which data is read. @@ -264,31 +589,28 @@ */ private final ProgressNotifier notifier; - // ----------------------------------------------------------- Constructors + /** + * The maximum permitted size of the headers provided with a single part in bytes. + */ + private int partHeaderSizeMax = FileUploadBase.DEFAULT_PART_HEADER_SIZE_MAX; /** - *

      Constructs a {@code MultipartStream} with a custom size buffer. - * - *

      Note that the buffer must be at least big enough to contain the - * boundary string, plus 4 characters for CR/LF and double dash, plus at - * least one byte of data. Too small a buffer size setting will degrade - * performance. + * Constructs a {@code MultipartStream} with a custom size buffer. + *

      + * Note that the buffer must be at least big enough to contain the boundary string, plus 4 characters for CR/LF and + * double dash, plus at least one byte of data. Too small a buffer size setting will degrade performance. * * @param input The {@code InputStream} to serve as a data source. - * @param boundary The token used for dividing the stream into - * {@code encapsulations}. + * @param boundary The token used for dividing the stream into {@code encapsulations}. * @param bufSize The size of the buffer to be used, in bytes. - * @param pNotifier The notifier, which is used for calling the - * progress listener, if any. + * @param notifier The notifier, which is used for calling the progress listener, if any. * * @throws IllegalArgumentException If the buffer size is too small * * @since FileUpload 1.3.1 */ - public MultipartStream(final InputStream input, - final byte[] boundary, - final int bufSize, - final ProgressNotifier pNotifier) { + public MultipartStream(final InputStream input, final byte[] boundary, final int bufSize, + final ProgressNotifier notifier) { if (boundary == null) { throw new IllegalArgumentException("boundary may not be null"); @@ -297,50 +619,103 @@ // body-data tokens. this.boundaryLength = boundary.length + BOUNDARY_PREFIX.length; if (bufSize < this.boundaryLength + 1) { - throw new IllegalArgumentException( - "The buffer size specified for the MultipartStream is too small"); + throw new IllegalArgumentException("The buffer size specified for the MultipartStream is too small"); } - this.input = input; this.bufSize = Math.max(bufSize, boundaryLength * 2); this.buffer = new byte[this.bufSize]; - this.notifier = pNotifier; - + this.notifier = notifier; this.boundary = new byte[this.boundaryLength]; this.boundaryTable = new int[this.boundaryLength + 1]; this.keepRegion = this.boundary.length; - - System.arraycopy(BOUNDARY_PREFIX, 0, this.boundary, 0, - BOUNDARY_PREFIX.length); - System.arraycopy(boundary, 0, this.boundary, BOUNDARY_PREFIX.length, - boundary.length); + System.arraycopy(BOUNDARY_PREFIX, 0, this.boundary, 0, BOUNDARY_PREFIX.length); + System.arraycopy(boundary, 0, this.boundary, BOUNDARY_PREFIX.length, boundary.length); computeBoundaryTable(); - head = 0; tail = 0; } /** - *

      Constructs a {@code MultipartStream} with a default size buffer. + * Constructs a {@code MultipartStream} with a default size buffer. * * @param input The {@code InputStream} to serve as a data source. * @param boundary The token used for dividing the stream into * {@code encapsulations}. - * @param pNotifier An object for calling the progress listener, if any. + * @param notifier An object for calling the progress listener, if any. * * * @see #MultipartStream(InputStream, byte[], int, ProgressNotifier) */ - public MultipartStream(final InputStream input, - final byte[] boundary, - final ProgressNotifier pNotifier) { - this(input, boundary, DEFAULT_BUFSIZE, pNotifier); + public MultipartStream(final InputStream input, final byte[] boundary, final ProgressNotifier notifier) { + this(input, boundary, DEFAULT_BUFSIZE, notifier); } - // --------------------------------------------------------- Public methods + /** + * Compute the table used for Knuth-Morris-Pratt search algorithm. + */ + private void computeBoundaryTable() { + int position = 2; + int candidate = 0; + + boundaryTable[0] = -1; + boundaryTable[1] = 0; + + while (position <= boundaryLength) { + if (boundary[position - 1] == boundary[candidate]) { + boundaryTable[position] = candidate + 1; + candidate++; + position++; + } else if (candidate > 0) { + candidate = boundaryTable[candidate]; + } else { + boundaryTable[position] = 0; + position++; + } + } + } + + /** + * Reads {@code body-data} from the current {@code encapsulation} and discards it. + *

      + * Use this method to skip encapsulations you don't need or don't understand. + * + * @return The amount of data discarded. + * + * @throws MalformedStreamException if the stream ends unexpectedly. + * @throws IOException if an i/o error occurs. + */ + public int discardBodyData() throws MalformedStreamException, IOException { + return readBodyData(null); + } + + /** + * Searches for the {@code boundary} in the {@code buffer} + * region delimited by {@code head} and {@code tail}. + * + * @return The position of the boundary found, counting from the + * beginning of the {@code buffer}, or {@code -1} if + * not found. + */ + protected int findSeparator() { + + int bufferPos = head; + int tablePos = 0; + + while (bufferPos < tail) { + while (tablePos >= 0 && buffer[bufferPos] != boundary[tablePos]) { + tablePos = boundaryTable[tablePos]; + } + bufferPos++; + tablePos++; + if (tablePos == boundaryLength) { + return bufferPos - boundaryLength; + } + } + return -1; + } /** - * Retrieves the character encoding used when reading the headers of an + * Gets the character encoding used when reading the headers of an * individual part. When not specified, or {@code null}, the platform * default encoding is used. * @@ -351,39 +726,42 @@ } /** - * Specifies the character encoding to be used when reading the headers of - * individual parts. When not specified, or {@code null}, the platform - * default encoding is used. + * Obtain the per part size limit for headers. * - * @param encoding The encoding used to read part headers. + * @return The maximum size of the headers for a single part in bytes. + * + * @since 1.6.0 */ - public void setHeaderEncoding(final String encoding) { - headerEncoding = encoding; + public int getPartHeaderSizeMax() { + return partHeaderSizeMax; } /** - * Reads a byte from the {@code buffer}, and refills it as - * necessary. + * Creates a new {@link ItemInputStream}. + * @return A new instance of {@link ItemInputStream}. + */ + public ItemInputStream newInputStream() { + return new ItemInputStream(); + } + + /** + * Reads {@code body-data} from the current {@code encapsulation} and writes its contents into the output + * {@code Stream}. + *

      + * Arbitrary large amounts of data can be processed by this method using a constant size buffer. (see {@link + * #MultipartStream(InputStream,byte[],int, MultipartStream.ProgressNotifier) constructor}). * - * @return The next byte from the input stream. + * @param output The {@code Stream} to write data into. May be null, in which case this method is equivalent to + * {@link #discardBodyData()}. * - * @throws IOException if there is no more data available. + * @return the amount of data written. + * + * @throws MalformedStreamException if the stream ends unexpectedly. + * @throws IOException if an i/o error occurs. */ - public byte readByte() throws IOException { - // Buffer depleted ? - if (head == tail) { - head = 0; - // Refill. - tail = input.read(buffer, head, bufSize); - if (tail == -1) { - // No more data available. - throw new IOException("No more data is available"); - } - if (notifier != null) { - notifier.noteBytesRead(tail); - } - } - return buffer[head++]; + public int readBodyData(final OutputStream output) + throws MalformedStreamException, IOException { + return (int) Streams.copy(newInputStream(), output, false); // Streams.copy closes the input stream } /** @@ -434,69 +812,35 @@ } /** - *

      Changes the boundary token used for partitioning the stream. - * - *

      This method allows single pass processing of nested multipart - * streams. - * - *

      The boundary token of the nested stream is {@code required} - * to be of the same length as the boundary token in parent stream. - * - *

      Restoring the parent stream boundary token after processing of a - * nested stream is left to the application. + * Reads a byte from the {@code buffer}, and refills it as + * necessary. * - * @param boundary The boundary to be used for parsing of the nested - * stream. + * @return The next byte from the input stream. * - * @throws IllegalBoundaryException if the {@code boundary} - * has a different length than the one - * being currently parsed. - */ - public void setBoundary(final byte[] boundary) - throws IllegalBoundaryException { - if (boundary.length != boundaryLength - BOUNDARY_PREFIX.length) { - throw new IllegalBoundaryException( - "The length of a boundary token cannot be changed"); - } - System.arraycopy(boundary, 0, this.boundary, BOUNDARY_PREFIX.length, - boundary.length); - computeBoundaryTable(); - } - - /** - * Compute the table used for Knuth-Morris-Pratt search algorithm. + * @throws IOException if there is no more data available. */ - private void computeBoundaryTable() { - int position = 2; - int candidate = 0; - - boundaryTable[0] = -1; - boundaryTable[1] = 0; - - while (position <= boundaryLength) { - if (boundary[position - 1] == boundary[candidate]) { - boundaryTable[position] = candidate + 1; - candidate++; - position++; - } else if (candidate > 0) { - candidate = boundaryTable[candidate]; - } else { - boundaryTable[position] = 0; - position++; + public byte readByte() throws IOException { + // Buffer depleted ? + if (head == tail) { + head = 0; + // Refill. + tail = input.read(buffer, head, bufSize); + if (tail == -1) { + // No more data available. + throw new IOException("No more data is available"); + } + if (notifier != null) { + notifier.noteBytesRead(tail); } } + return buffer[head++]; } /** - *

      Reads the {@code header-part} of the current - * {@code encapsulation}. - * - *

      Headers are returned verbatim to the input stream, including the - * trailing {@code CRLF} marker. Parsing is left to the - * application. - * - *

      TODO allow limiting maximum header size to - * protect against abuse. + * Reads the {@code header-part} of the current {@code encapsulation}. + *

      + * Headers are returned verbatim to the input stream, including the trailing {@code CRLF} marker. Parsing is left to + * the application. * * @return The {@code header-part} of the current encapsulation. * @@ -518,10 +862,11 @@ } catch (final IOException e) { throw new MalformedStreamException("Stream ended unexpectedly"); } - if (++size > HEADER_PART_SIZE_MAX) { - throw new MalformedStreamException(String.format( - "Header section has more than %s bytes (maybe it is not properly terminated)", - Integer.valueOf(HEADER_PART_SIZE_MAX))); + size++; + if (getPartHeaderSizeMax() != -1 && size > getPartHeaderSizeMax()) { + throw new FileUploadIOException(new SizeLimitExceededException( + String.format("Header section has more than %s bytes (maybe it is not properly terminated)", Integer.valueOf(getPartHeaderSizeMax())), + size, getPartHeaderSizeMax())); } if (b == HEADER_SEPARATOR[i]) { i++; @@ -530,7 +875,6 @@ } baos.write(b); } - String headers; if (headerEncoding != null) { try { @@ -543,56 +887,52 @@ } else { headers = baos.toString(); } - return headers; } /** - *

      Reads {@code body-data} from the current - * {@code encapsulation} and writes its contents into the - * output {@code Stream}. - * - *

      Arbitrary large amounts of data can be processed by this - * method using a constant size buffer. (see {@link - * #MultipartStream(InputStream,byte[],int, - * MultipartStream.ProgressNotifier) constructor}). - * - * @param output The {@code Stream} to write data into. May - * be null, in which case this method is equivalent - * to {@link #discardBodyData()}. + * Changes the boundary token used for partitioning the stream. + *

      + * This method allows single pass processing of nested multipart streams. + *

      + * The boundary token of the nested stream is {@code required} to be of the same length as the boundary token in + * parent stream. + *

      + * Restoring the parent stream boundary token after processing of a nested stream is left to the application. * - * @return the amount of data written. + * @param boundary The boundary to be used for parsing of the nested stream. * - * @throws MalformedStreamException if the stream ends unexpectedly. - * @throws IOException if an i/o error occurs. + * @throws IllegalBoundaryException if the {@code boundary} has a different length than the one being currently + * parsed. */ - public int readBodyData(final OutputStream output) - throws MalformedStreamException, IOException { - return (int) Streams.copy(newInputStream(), output, false); // N.B. Streams.copy closes the input stream + public void setBoundary(final byte[] boundary) throws IllegalBoundaryException { + if (boundary.length != boundaryLength - BOUNDARY_PREFIX.length) { + throw new IllegalBoundaryException("The length of a boundary token cannot be changed"); + } + System.arraycopy(boundary, 0, this.boundary, BOUNDARY_PREFIX.length, boundary.length); + computeBoundaryTable(); } /** - * Creates a new {@link ItemInputStream}. - * @return A new instance of {@link ItemInputStream}. + * Specifies the character encoding to be used when reading the headers of + * individual parts. When not specified, or {@code null}, the platform + * default encoding is used. + * + * @param encoding The encoding used to read part headers. */ - public ItemInputStream newInputStream() { - return new ItemInputStream(); + public void setHeaderEncoding(final String encoding) { + headerEncoding = encoding; } /** - *

      Reads {@code body-data} from the current - * {@code encapsulation} and discards it. + * Sets the per part size limit for headers. * - *

      Use this method to skip encapsulations you don't need or don't - * understand. + * @param partHeaderSizeMax The maximum size of the headers in bytes. * - * @return The amount of data discarded. - * - * @throws MalformedStreamException if the stream ends unexpectedly. - * @throws IOException if an i/o error occurs. + * @since 1.6.0 */ - public int discardBodyData() throws MalformedStreamException, IOException { - return readBodyData(null); + public void setPartHeaderSizeMax(final int partHeaderSizeMax) { + this.partHeaderSizeMax = partHeaderSizeMax; } /** @@ -627,361 +967,4 @@ } } - /** - * Compares {@code count} first bytes in the arrays - * {@code a} and {@code b}. - * - * @param a The first array to compare. - * @param b The second array to compare. - * @param count How many bytes should be compared. - * - * @return {@code true} if {@code count} first bytes in arrays - * {@code a} and {@code b} are equal. - */ - public static boolean arrayequals(final byte[] a, - final byte[] b, - final int count) { - for (int i = 0; i < count; i++) { - if (a[i] != b[i]) { - return false; - } - } - return true; - } - - /** - * Searches for the {@code boundary} in the {@code buffer} - * region delimited by {@code head} and {@code tail}. - * - * @return The position of the boundary found, counting from the - * beginning of the {@code buffer}, or {@code -1} if - * not found. - */ - protected int findSeparator() { - - int bufferPos = this.head; - int tablePos = 0; - - while (bufferPos < this.tail) { - while (tablePos >= 0 && buffer[bufferPos] != boundary[tablePos]) { - tablePos = boundaryTable[tablePos]; - } - bufferPos++; - tablePos++; - if (tablePos == boundaryLength) { - return bufferPos - boundaryLength; - } - } - return -1; - } - - /** - * Thrown to indicate that the input stream fails to follow the - * required syntax. - */ - public static class MalformedStreamException extends IOException { - - /** - * The UID to use when serializing this instance. - */ - private static final long serialVersionUID = 6466926458059796677L; - - /** - * Constructs a {@code MalformedStreamException} with no - * detail message. - */ - public MalformedStreamException() { - } - - /** - * Constructs an {@code MalformedStreamException} with - * the specified detail message. - * - * @param message The detail message. - */ - public MalformedStreamException(final String message) { - super(message); - } - - } - - /** - * Thrown upon attempt of setting an invalid boundary token. - */ - public static class IllegalBoundaryException extends IOException { - - /** - * The UID to use when serializing this instance. - */ - private static final long serialVersionUID = -161533165102632918L; - - /** - * Constructs an {@code IllegalBoundaryException} with no - * detail message. - */ - public IllegalBoundaryException() { - } - - /** - * Constructs an {@code IllegalBoundaryException} with - * the specified detail message. - * - * @param message The detail message. - */ - public IllegalBoundaryException(final String message) { - super(message); - } - - } - - /** - * An {@link InputStream} for reading an items contents. - */ - public class ItemInputStream extends InputStream implements Closeable { - - /** - * The number of bytes, which have been read so far. - */ - private long total; - - /** - * The number of bytes, which must be hold, because - * they might be a part of the boundary. - */ - private int pad; - - /** - * The current offset in the buffer. - */ - private int pos; - - /** - * Whether the stream is already closed. - */ - private boolean closed; - - /** - * Creates a new instance. - */ - ItemInputStream() { - findSeparator(); - } - - /** - * Called for finding the separator. - */ - private void findSeparator() { - pos = MultipartStream.this.findSeparator(); - if (pos == -1) { - if (tail - head > keepRegion) { - pad = keepRegion; - } else { - pad = tail - head; - } - } - } - - /** - * Returns the number of bytes, which have been read - * by the stream. - * - * @return Number of bytes, which have been read so far. - */ - public long getBytesRead() { - return total; - } - - /** - * Returns the number of bytes, which are currently - * available, without blocking. - * - * @throws IOException An I/O error occurs. - * @return Number of bytes in the buffer. - */ - @Override - public int available() throws IOException { - if (pos == -1) { - return tail - head - pad; - } - return pos - head; - } - - /** - * Offset when converting negative bytes to integers. - */ - private static final int BYTE_POSITIVE_OFFSET = 256; - - /** - * Returns the next byte in the stream. - * - * @return The next byte in the stream, as a non-negative - * integer, or -1 for EOF. - * @throws IOException An I/O error occurred. - */ - @Override - public int read() throws IOException { - if (closed) { - throw new FileItemStream.ItemSkippedException(); - } - if (available() == 0 && makeAvailable() == 0) { - return -1; - } - ++total; - final int b = buffer[head++]; - if (b >= 0) { - return b; - } - return b + BYTE_POSITIVE_OFFSET; - } - - /** - * Reads bytes into the given buffer. - * - * @param b The destination buffer, where to write to. - * @param off Offset of the first byte in the buffer. - * @param len Maximum number of bytes to read. - * @return Number of bytes, which have been actually read, - * or -1 for EOF. - * @throws IOException An I/O error occurred. - */ - @Override - public int read(final byte[] b, final int off, final int len) throws IOException { - if (closed) { - throw new FileItemStream.ItemSkippedException(); - } - if (len == 0) { - return 0; - } - int res = available(); - if (res == 0) { - res = makeAvailable(); - if (res == 0) { - return -1; - } - } - res = Math.min(res, len); - System.arraycopy(buffer, head, b, off, res); - head += res; - total += res; - return res; - } - - /** - * Closes the input stream. - * - * @throws IOException An I/O error occurred. - */ - @Override - public void close() throws IOException { - close(false); - } - - /** - * Closes the input stream. - * - * @param pCloseUnderlying Whether to close the underlying stream - * (hard close) - * @throws IOException An I/O error occurred. - */ - public void close(final boolean pCloseUnderlying) throws IOException { - if (closed) { - return; - } - if (pCloseUnderlying) { - closed = true; - input.close(); - } else { - for (;;) { - int av = available(); - if (av == 0) { - av = makeAvailable(); - if (av == 0) { - break; - } - } - skip(av); - } - } - closed = true; - } - - /** - * Skips the given number of bytes. - * - * @param bytes Number of bytes to skip. - * @return The number of bytes, which have actually been - * skipped. - * @throws IOException An I/O error occurred. - */ - @Override - public long skip(final long bytes) throws IOException { - if (closed) { - throw new FileItemStream.ItemSkippedException(); - } - int av = available(); - if (av == 0) { - av = makeAvailable(); - if (av == 0) { - return 0; - } - } - final long res = Math.min(av, bytes); - head += res; - return res; - } - - /** - * Attempts to read more data. - * - * @return Number of available bytes - * @throws IOException An I/O error occurred. - */ - private int makeAvailable() throws IOException { - if (pos != -1) { - return 0; - } - - // Move the data to the beginning of the buffer. - total += tail - head - pad; - System.arraycopy(buffer, tail - pad, buffer, 0, pad); - - // Refill buffer with new data. - head = 0; - tail = pad; - - for (;;) { - final int bytesRead = input.read(buffer, tail, bufSize - tail); - if (bytesRead == -1) { - // The last pad amount is left in the buffer. - // Boundary can't be in there so signal an error - // condition. - final String msg = "Stream ended unexpectedly"; - throw new MalformedStreamException(msg); - } - if (notifier != null) { - notifier.noteBytesRead(bytesRead); - } - tail += bytesRead; - - findSeparator(); - final int av = available(); - - if (av > 0 || pos != -1) { - return av; - } - } - } - - /** - * Returns, whether the stream is closed. - * - * @return True, if the stream is closed, otherwise false. - */ - @Override - public boolean isClosed() { - return closed; - } - - } - } diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/http/fileupload/ParameterParser.java tomcat10-10.1.52/java/org/apache/tomcat/util/http/fileupload/ParameterParser.java --- tomcat10-10.1.40/java/org/apache/tomcat/util/http/fileupload/ParameterParser.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/http/fileupload/ParameterParser.java 2026-01-23 19:33:36.000000000 +0000 @@ -22,7 +22,6 @@ import java.util.Map; import org.apache.tomcat.util.http.fileupload.util.mime.MimeUtility; -import org.apache.tomcat.util.http.fileupload.util.mime.RFC2231Utility; /** * A simple parser intended to parse sequences of name/value pairs. @@ -40,32 +39,32 @@ /** * String to be parsed. */ - private char[] chars = null; + private char[] chars; /** * Current position in the string. */ - private int pos = 0; + private int pos; /** * Maximum position in the string. */ - private int len = 0; + private int len; /** * Start of a token. */ - private int i1 = 0; + private int i1; /** * End of a token. */ - private int i2 = 0; + private int i2; /** * Whether names stored in the map should be converted to lower case. */ - private boolean lowerCaseNames = false; + private boolean lowerCaseNames; /** * Default ParameterParser constructor. @@ -74,16 +73,6 @@ } /** - * Are there any characters left to parse? - * - * @return {@code true} if there are unparsed characters, - * {@code false} otherwise. - */ - private boolean hasChar() { - return this.pos < this.len; - } - - /** * A helper method to process the parsed token. This method removes * leading and trailing blanks as well as enclosing quotation marks, * when necessary. @@ -94,18 +83,18 @@ */ private String getToken(final boolean quoted) { // Trim leading white spaces - while ((i1 < i2) && (Character.isWhitespace(chars[i1]))) { + while (i1 < i2 && Character.isWhitespace(chars[i1])) { i1++; } // Trim trailing white spaces - while ((i2 > i1) && (Character.isWhitespace(chars[i2 - 1]))) { + while (i2 > i1 && Character.isWhitespace(chars[i2 - 1])) { i2--; } // Strip away quotation marks if necessary if (quoted - && ((i2 - i1) >= 2) - && (chars[i1] == '"') - && (chars[i2 - 1] == '"')) { + && i2 - i1 >= 2 + && chars[i1] == '"' + && chars[i2 - 1] == '"') { i1++; i2--; } @@ -117,6 +106,28 @@ } /** + * Are there any characters left to parse? + * + * @return {@code true} if there are unparsed characters, + * {@code false} otherwise. + */ + private boolean hasChar() { + return pos < len; + } + + /** + * Returns {@code true} if parameter names are to be converted to lower + * case when name/value pairs are parsed. + * + * @return {@code true} if parameter names are to be + * converted to lower case when name/value pairs are parsed. + * Otherwise returns {@code false} + */ + public boolean isLowerCaseNames() { + return lowerCaseNames; + } + + /** * Tests if the given character is present in the array of characters. * * @param ch the character to test for presence in the array of characters @@ -137,83 +148,83 @@ } /** - * Parses out a token until any of the given terminators - * is encountered. + * Extracts a map of name/value pairs from the given array of + * characters. Names are expected to be unique. * - * @param terminators the array of terminating characters. Any of these - * characters when encountered signify the end of the token + * @param charArray the array of characters that contains a sequence of + * name/value pairs + * @param separator the name/value pairs separator * - * @return the token + * @return a map of name/value pairs */ - private String parseToken(final char[] terminators) { - char ch; - i1 = pos; - i2 = pos; - while (hasChar()) { - ch = chars[pos]; - if (isOneOf(ch, terminators)) { - break; - } - i2++; - pos++; + public Map parse(final char[] charArray, final char separator) { + if (charArray == null) { + return new HashMap<>(); } - return getToken(false); + return parse(charArray, 0, charArray.length, separator); } /** - * Parses out a token until any of the given terminators - * is encountered outside the quotation marks. + * Extracts a map of name/value pairs from the given array of characters. Names are expected to be unique. * - * @param terminators the array of terminating characters. Any of these - * characters when encountered outside the quotation marks signify the end - * of the token + * @param charArray the array of characters that contains a sequence of name/value pairs + * @param offset the initial offset. + * @param length the length. + * @param separator the name/value pairs separator * - * @return the token + * @return a map of name/value pairs */ - private String parseQuotedToken(final char[] terminators) { - char ch; - i1 = pos; - i2 = pos; - boolean quoted = false; - boolean charEscaped = false; + public Map parse(final char[] charArray, final int offset, final int length, final char separator) { + if (charArray == null) { + return new HashMap<>(); + } + final HashMap params = new HashMap<>(); + chars = charArray.clone(); + pos = offset; + len = length; while (hasChar()) { - ch = chars[pos]; - if (!quoted && isOneOf(ch, terminators)) { - break; + String paramName = parseToken(new char[] { '=', separator }); + String paramValue = null; + if (hasChar() && charArray[pos] == '=') { + pos++; // skip '=' + paramValue = parseQuotedToken(new char[] { separator }); + if (paramValue != null) { + try { + paramValue = RFC2231Utility.hasEncodedValue(paramName) ? RFC2231Utility.decodeText(paramValue) + : MimeUtility.decodeText(paramValue); + } catch (final UnsupportedEncodingException e) { + // let's keep the original value in this case + } + } } - if (!charEscaped && ch == '"') { - quoted = !quoted; + if (hasChar() && charArray[pos] == separator) { + pos++; // skip separator + } + if (paramName != null && !paramName.isEmpty()) { + paramName = RFC2231Utility.stripDelimiter(paramName); + if (lowerCaseNames) { + paramName = paramName.toLowerCase(Locale.ROOT); + } + params.put(paramName, paramValue); } - charEscaped = (!charEscaped && ch == '\\'); - i2++; - pos++; - } - return getToken(true); + return params; } /** - * Returns {@code true} if parameter names are to be converted to lower - * case when name/value pairs are parsed. + * Extracts a map of name/value pairs from the given string. Names are + * expected to be unique. * - * @return {@code true} if parameter names are to be - * converted to lower case when name/value pairs are parsed. - * Otherwise returns {@code false} - */ - public boolean isLowerCaseNames() { - return this.lowerCaseNames; - } - - /** - * Sets the flag if parameter names are to be converted to lower case when - * name/value pairs are parsed. + * @param str the string that contains a sequence of name/value pairs + * @param separator the name/value pairs separator * - * @param b {@code true} if parameter names are to be - * converted to lower case when name/value pairs are parsed. - * {@code false} otherwise. + * @return a map of name/value pairs */ - public void setLowerCaseNames(final boolean b) { - this.lowerCaseNames = b; + public Map parse(final String str, final char separator) { + if (str == null) { + return new HashMap<>(); + } + return parse(str.toCharArray(), separator); } /** @@ -245,96 +256,71 @@ } /** - * Extracts a map of name/value pairs from the given string. Names are - * expected to be unique. + * Parses out a token until any of the given terminators + * is encountered outside the quotation marks. * - * @param str the string that contains a sequence of name/value pairs - * @param separator the name/value pairs separator + * @param terminators the array of terminating characters. Any of these + * characters when encountered outside the quotation marks signify the end + * of the token * - * @return a map of name/value pairs + * @return the token */ - public Map parse(final String str, final char separator) { - if (str == null) { - return new HashMap<>(); + private String parseQuotedToken(final char[] terminators) { + char ch; + i1 = pos; + i2 = pos; + boolean quoted = false; + boolean charEscaped = false; + while (hasChar()) { + ch = chars[pos]; + if (!quoted && isOneOf(ch, terminators)) { + break; + } + if (!charEscaped && ch == '"') { + quoted = !quoted; + } + charEscaped = !charEscaped && ch == '\\'; + i2++; + pos++; + } - return parse(str.toCharArray(), separator); + return getToken(true); } /** - * Extracts a map of name/value pairs from the given array of - * characters. Names are expected to be unique. + * Parses out a token until any of the given terminators + * is encountered. * - * @param charArray the array of characters that contains a sequence of - * name/value pairs - * @param separator the name/value pairs separator + * @param terminators the array of terminating characters. Any of these + * characters when encountered signify the end of the token * - * @return a map of name/value pairs + * @return the token */ - public Map parse(final char[] charArray, final char separator) { - if (charArray == null) { - return new HashMap<>(); + private String parseToken(final char[] terminators) { + char ch; + i1 = pos; + i2 = pos; + while (hasChar()) { + ch = chars[pos]; + if (isOneOf(ch, terminators)) { + break; + } + i2++; + pos++; } - return parse(charArray, 0, charArray.length, separator); + return getToken(false); } /** - * Extracts a map of name/value pairs from the given array of - * characters. Names are expected to be unique. - * - * @param charArray the array of characters that contains a sequence of - * name/value pairs - * @param offset - the initial offset. - * @param length - the length. - * @param separator the name/value pairs separator + * Sets the flag if parameter names are to be converted to lower case when + * name/value pairs are parsed. * - * @return a map of name/value pairs + * @param b {@code true} if parameter names are to be + * converted to lower case when name/value pairs are parsed. + * {@code false} otherwise. */ - public Map parse( - final char[] charArray, - final int offset, - final int length, - final char separator) { - - if (charArray == null) { - return new HashMap<>(); - } - final HashMap params = new HashMap<>(); - this.chars = charArray.clone(); - this.pos = offset; - this.len = length; - - String paramName; - String paramValue; - while (hasChar()) { - paramName = parseToken(new char[] { - '=', separator }); - paramValue = null; - if (hasChar() && (charArray[pos] == '=')) { - pos++; // skip '=' - paramValue = parseQuotedToken(new char[] { - separator }); - - if (paramValue != null) { - try { - paramValue = RFC2231Utility.hasEncodedValue(paramName) ? RFC2231Utility.decodeText(paramValue) - : MimeUtility.decodeText(paramValue); - } catch (final UnsupportedEncodingException e) { - // let's keep the original value in this case - } - } - } - if (hasChar() && (charArray[pos] == separator)) { - pos++; // skip separator - } - if ((paramName != null) && !paramName.isEmpty()) { - paramName = RFC2231Utility.stripDelimiter(paramName); - if (this.lowerCaseNames) { - paramName = paramName.toLowerCase(Locale.ENGLISH); - } - params.put(paramName, paramValue); - } - } - return params; + public void setLowerCaseNames(final boolean b) { + lowerCaseNames = b; } } diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/http/fileupload/ProgressListener.java tomcat10-10.1.52/java/org/apache/tomcat/util/http/fileupload/ProgressListener.java --- tomcat10-10.1.40/java/org/apache/tomcat/util/http/fileupload/ProgressListener.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/http/fileupload/ProgressListener.java 2026-01-23 19:33:36.000000000 +0000 @@ -25,13 +25,13 @@ /** * Updates the listeners status information. * - * @param pBytesRead The total number of bytes, which have been read + * @param bytesRead The total number of bytes, which have been read * so far. - * @param pContentLength The total number of bytes, which are being + * @param contentLength The total number of bytes, which are being * read. May be -1, if this number is unknown. - * @param pItems The number of the field, which is currently being + * @param items The number of the field, which is currently being * read. (0 = no item so far, 1 = first item is being read, ...) */ - void update(long pBytesRead, long pContentLength, int pItems); + void update(long bytesRead, long contentLength, int items); } diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/http/fileupload/RFC2231Utility.java tomcat10-10.1.52/java/org/apache/tomcat/util/http/fileupload/RFC2231Utility.java --- tomcat10-10.1.40/java/org/apache/tomcat/util/http/fileupload/RFC2231Utility.java 1970-01-01 00:00:00.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/http/fileupload/RFC2231Utility.java 2026-01-23 19:33:36.000000000 +0000 @@ -0,0 +1,158 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.tomcat.util.http.fileupload; + +import java.io.ByteArrayOutputStream; +import java.io.UnsupportedEncodingException; + +/** + * Utility class to decode/encode character set on HTTP Header fields based on RFC 2231. This implementation adheres to RFC 5987 in particular, which was + * defined for HTTP headers. + *

      + * RFC 5987 builds on RFC 2231, but has lesser scope like mandatory charset definition and + * no parameter continuation + *

      + * + * @see RFC 2231 + * @see RFC 5987 + */ +final class RFC2231Utility { + + /** + * Percent character '{@value}'. + */ + private static final char PERCENT = '%'; + /** + * The Hexadecimal values char array. + */ + private static final char[] HEX_DIGITS = "0123456789ABCDEF".toCharArray(); + /** + * The Hexadecimal representation of 127. + */ + private static final byte MASK = 0x7f; + /** + * The Hexadecimal representation of 128. + */ + private static final int MASK_128 = 0x80; + /** + * The Hexadecimal decode value. + */ + private static final byte[] HEX_DECODE = new byte[MASK_128]; + // create a ASCII decoded array of Hexadecimal values + static { + for (int i = 0; i < HEX_DIGITS.length; i++) { + HEX_DECODE[HEX_DIGITS[i]] = (byte) i; + HEX_DECODE[Character.toLowerCase(HEX_DIGITS[i])] = (byte) i; + } + } + + /** + * Decodes a string of text obtained from a HTTP header as per RFC 2231 + *

      + * Eg 1. {@code us-ascii'en-us'This%20is%20%2A%2A%2Afun%2A%2A%2A} will be decoded to {@code This is ***fun***} + *

      + *

      + * Eg 2. {@code iso-8859-1'en'%A3%20rate} will be decoded to {@code £ rate} + *

      + *

      + * Eg 3. {@code UTF-8''%c2%a3%20and%20%e2%82%ac%20rates} will be decoded to {@code £ and € rates} + *

      + * + * @param encodedText Text to be decoded has a format of {@code ''} and ASCII only + * @return Decoded text based on charset encoding + * @throws UnsupportedEncodingException The requested character set wasn't found. + */ + static String decodeText(final String encodedText) throws UnsupportedEncodingException { + final int langDelimitStart = encodedText.indexOf('\''); + if (langDelimitStart == -1) { + // missing charset + return encodedText; + } + final String mimeCharset = encodedText.substring(0, langDelimitStart); + final int langDelimitEnd = encodedText.indexOf('\'', langDelimitStart + 1); + if (langDelimitEnd == -1) { + // missing language + return encodedText; + } + final byte[] bytes = fromHex(encodedText.substring(langDelimitEnd + 1)); + return new String(bytes, getJavaCharset(mimeCharset)); + } + + /** + * Converts {@code text} to their corresponding Hex value. + * + * @param text ASCII text input + * @return Byte array of characters decoded from ASCII table + */ + private static byte[] fromHex(final String text) { + final int shift = 4; + final ByteArrayOutputStream out = new ByteArrayOutputStream(text.length()); + for (int i = 0; i < text.length();) { + final char c = text.charAt(i++); + if (c == PERCENT) { + if (i > text.length() - 2) { + break; // unterminated sequence + } + final byte b1 = HEX_DECODE[text.charAt(i++) & MASK]; + final byte b2 = HEX_DECODE[text.charAt(i++) & MASK]; + out.write(b1 << shift | b2); + } else { + out.write((byte) c); + } + } + return out.toByteArray(); + } + + private static String getJavaCharset(final String mimeCharset) { + // good enough for standard values + return mimeCharset; + } + + /** + * Checks if Asterisk (*) at the end of parameter name to indicate, if it has charset and language information to decode the value. + * + * @param paramName The parameter, which is being checked. + * @return {@code true}, if encoded as per RFC 2231, {@code false} otherwise + */ + static boolean hasEncodedValue(final String paramName) { + if (paramName != null) { + return paramName.lastIndexOf('*') == paramName.length() - 1; + } + return false; + } + + /** + * If {@code paramName} has Asterisk (*) at the end, it will be stripped off, else the passed value will be returned. + * + * @param paramName The parameter, which is being inspected. + * @return stripped {@code paramName} of Asterisk (*), if RFC2231 encoded + */ + static String stripDelimiter(final String paramName) { + if (hasEncodedValue(paramName)) { + final StringBuilder paramBuilder = new StringBuilder(paramName); + paramBuilder.deleteCharAt(paramName.lastIndexOf('*')); + return paramBuilder.toString(); + } + return paramName; + } + + /** + * Private constructor so that no instances can be created. This class contains only static utility methods. + */ + private RFC2231Utility() { + } +} diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/http/fileupload/disk/DiskFileItem.java tomcat10-10.1.52/java/org/apache/tomcat/util/http/fileupload/disk/DiskFileItem.java --- tomcat10-10.1.40/java/org/apache/tomcat/util/http/fileupload/disk/DiskFileItem.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/http/fileupload/disk/DiskFileItem.java 2026-01-23 19:33:36.000000000 +0000 @@ -37,259 +37,175 @@ import org.apache.tomcat.util.http.fileupload.FileItemHeaders; import org.apache.tomcat.util.http.fileupload.FileUploadException; import org.apache.tomcat.util.http.fileupload.IOUtils; +import org.apache.tomcat.util.http.fileupload.InvalidFileNameException; import org.apache.tomcat.util.http.fileupload.ParameterParser; import org.apache.tomcat.util.http.fileupload.util.Streams; /** - *

      The default implementation of the - * {@link org.apache.tomcat.util.http.fileupload.FileItem FileItem} interface. - * - *

      After retrieving an instance of this class from a {@link - * org.apache.tomcat.util.http.fileupload.FileUpload FileUpload} instance (see + * The default implementation of the {@link org.apache.tomcat.util.http.fileupload.FileItem FileItem} interface. + *

      + * After retrieving an instance of this class from a {@link DiskFileItemFactory} instance (see * {@link org.apache.tomcat.util.http.fileupload.FileUpload - * #parseRequest(org.apache.tomcat.util.http.fileupload.RequestContext)}), you - * may either request all contents of file at once using {@link #get()} or - * request an {@link java.io.InputStream InputStream} with - * {@link #getInputStream()} and process the file without attempting to load - * it into memory, which may come handy with large files. - * - *

      Temporary files, which are created for file items, will be deleted when - * the associated request is recycled.

      + * #parseRequest(org.apache.tomcat.util.http.fileupload.RequestContext)}), you may either request all contents of file + * at once using {@link #get()} or request an {@link java.io.InputStream InputStream} with {@link #getInputStream()} and + * process the file without attempting to load it into memory, which may come handy with large files. + *

      + * Temporary files, which are created for file items, will be deleted when the associated request is recycled. + *

      * * @since FileUpload 1.1 */ -public class DiskFileItem - implements FileItem { +public class DiskFileItem implements FileItem { - // ----------------------------------------------------- Manifest constants + /** + * Counter used in unique identifier generation. + */ + private static final AtomicInteger COUNTER = new AtomicInteger(0); /** - * Default content charset to be used when no explicit charset - * parameter is provided by the sender. Media subtypes of the - * "text" type are defined to have a default charset value of - * "ISO-8859-1" when received via HTTP. + * Default content charset to be used when no explicit charset parameter is provided by the sender. Media subtypes + * of the "text" type are defined to have a default charset value of "ISO-8859-1" when received via HTTP. */ public static final String DEFAULT_CHARSET = "ISO-8859-1"; - // ----------------------------------------------------------- Data members - /** * UID used in unique file name generation. */ - private static final String UID = - UUID.randomUUID().toString().replace('-', '_'); + private static final String UID = UUID.randomUUID().toString().replace('-', '_'); /** - * Counter used in unique identifier generation. + * Returns an identifier that is unique within the class loader used to load this class, but does not have + * random-like appearance. + * + * @return A String with the non-random looking instance identifier. */ - private static final AtomicInteger COUNTER = new AtomicInteger(0); + private static String getUniqueId() { + final int limit = 100000000; + final int current = COUNTER.getAndIncrement(); + String id = Integer.toString(current); + + // If you manage to get more than 100 million of ids, you'll + // start getting ids longer than 8 characters. + if (current < limit) { + id = ("00000000" + id).substring(id.length()); + } + return id; + } /** - * The name of the form field as provided by the browser. + * Cached contents of the file. */ - private String fieldName; + private byte[] cachedContent; /** - * The content type passed by the browser, or {@code null} if - * not defined. + * The content type passed by the browser, or {@code null} if not defined. */ private final String contentType; /** - * Whether or not this item is a simple form field. + * Default content charset to be used when no explicit charset parameter is provided by the sender. */ - private boolean isFormField; + private String defaultCharset = DEFAULT_CHARSET; /** - * The original file name in the user's file system. + * Output stream for this item. */ - private final String fileName; + private transient DeferredFileOutputStream dfos; /** - * The size of the item, in bytes. This is used to cache the size when a - * file item is moved from its original location. + * The name of the form field as provided by the browser. */ - private long size = -1; - + private String fieldName; /** - * The threshold above which uploads will be stored on disk. + * The original file name in the user's file system. */ - private final int sizeThreshold; + private final String fileName; /** - * The directory in which uploaded files will be stored, if stored on disk. + * The file items headers. */ - private final File repository; + private FileItemHeaders headers; /** - * Cached contents of the file. + * Whether or not this item is a simple form field. */ - private byte[] cachedContent; + private boolean formField; /** - * Output stream for this item. + * The directory in which uploaded files will be stored, if stored on disk. */ - private transient DeferredFileOutputStream dfos; + private final File repository; /** - * The temporary file to use. + * The size of the item, in bytes. This is used to cache the size when a file item is moved from its original + * location. */ - private transient File tempFile; + private long size = -1; /** - * The file items headers. + * The threshold above which uploads will be stored on disk. */ - private FileItemHeaders headers; + private final int sizeThreshold; /** - * Default content charset to be used when no explicit charset - * parameter is provided by the sender. + * The temporary file to use. */ - private String defaultCharset = DEFAULT_CHARSET; - - // ----------------------------------------------------------- Constructors + private transient File tempFile; /** * Constructs a new {@code DiskFileItem} instance. * * @param fieldName The name of the form field. - * @param contentType The content type passed by the browser or - * {@code null} if not specified. - * @param isFormField Whether or not this item is a plain form field, as - * opposed to a file upload. - * @param fileName The original file name in the user's file system, or - * {@code null} if not specified. - * @param sizeThreshold The threshold, in bytes, below which items will be - * retained in memory and above which they will be - * stored as a file. - * @param repository The data repository, which is the directory in - * which files will be created, should the item size - * exceed the threshold. - */ - public DiskFileItem(final String fieldName, - final String contentType, final boolean isFormField, final String fileName, - final int sizeThreshold, final File repository) { + * @param contentType The content type passed by the browser or {@code null} if not specified. + * @param isFormField Whether or not this item is a plain form field, as opposed to a file upload. + * @param fileName The original file name in the user's file system, or {@code null} if not specified. + * @param sizeThreshold The threshold, in bytes, below which items will be retained in memory and above which they + * will be stored as a file. + * @param repository The data repository, which is the directory in which files will be created, should the item + * size exceed the threshold. + */ + public DiskFileItem(final String fieldName, final String contentType, final boolean isFormField, + final String fileName, final int sizeThreshold, final File repository) { this.fieldName = fieldName; this.contentType = contentType; - this.isFormField = isFormField; + this.formField = isFormField; this.fileName = fileName; this.sizeThreshold = sizeThreshold; this.repository = repository; } - // ------------------------------- Methods from javax.activation.DataSource - /** - * Returns an {@link java.io.InputStream InputStream} that can be - * used to retrieve the contents of the file. - * - * @return An {@link java.io.InputStream InputStream} that can be - * used to retrieve the contents of the file. - * - * @throws IOException if an error occurs. + * Clears the cache. */ - @Override - public InputStream getInputStream() - throws IOException { - if (!isInMemory()) { - return Files.newInputStream(dfos.getFile().toPath()); - } - - if (cachedContent == null) { - cachedContent = dfos.getData(); - } - return new ByteArrayInputStream(cachedContent); + private void clear() { + cachedContent = null; // NOPMD } /** - * Returns the content type passed by the agent or {@code null} if - * not defined. - * - * @return The content type passed by the agent or {@code null} if - * not defined. + * Deletes the underlying storage for a file item, including deleting any associated temporary disk file. This + * method can be used to ensure that this is done at an earlier time, thus preserving system resources. */ @Override - public String getContentType() { - return contentType; - } - - /** - * Returns the content charset passed by the agent or {@code null} if - * not defined. - * - * @return The content charset passed by the agent or {@code null} if - * not defined. - */ - public String getCharSet() { - final ParameterParser parser = new ParameterParser(); - parser.setLowerCaseNames(true); - // Parameter parser can handle null input - final Map params = parser.parse(getContentType(), ';'); - return params.get("charset"); - } - - /** - * Returns the original file name in the client's file system. - * - * @return The original file name in the client's file system. - * @throws org.apache.tomcat.util.http.fileupload.InvalidFileNameException - * The file name contains a NUL character, which might be an indicator of - * a security attack. If you intend to use the file name anyways, catch - * the exception and use {@link - * org.apache.tomcat.util.http.fileupload.InvalidFileNameException#getName()}. - */ - @Override - public String getName() { - return Streams.checkFileName(fileName); - } - - // ------------------------------------------------------- FileItem methods - - /** - * Provides a hint as to whether or not the file contents will be read - * from memory. - * - * @return {@code true} if the file contents will be read - * from memory; {@code false} otherwise. - */ - @Override - public boolean isInMemory() { - if (cachedContent != null) { - return true; - } - return dfos.isInMemory(); - } - - /** - * Returns the size of the file. - * - * @return The size of the file, in bytes. - */ - @Override - public long getSize() { - if (size >= 0) { - return size; - } - if (cachedContent != null) { - return cachedContent.length; - } - if (dfos.isInMemory()) { - return dfos.getData().length; + public void delete() { + clear(); + final File outputFile = getStoreLocation(); + if (outputFile != null && !isInMemory() && outputFile.exists()) { + if (!outputFile.delete()) { + final String desc = "Cannot delete " + outputFile.toString(); + throw new UncheckedIOException(desc, new IOException(desc)); + } } - return dfos.getFile().length(); } /** - * Returns the contents of the file as an array of bytes. If the - * contents of the file were not yet cached in memory, they will be - * loaded from the disk storage and cached. + * Gets the contents of the file as an array of bytes. If the contents of the file were not yet cached in memory, + * they will be loaded from the disk storage and cached. * - * @return The contents of the file as an array of bytes - * or {@code null} if the data cannot be read + * @return The contents of the file as an array of bytes or {@code null} if the data cannot be read. * * @throws UncheckedIOException if an I/O error occurs - * @throws ArithmeticException if the file {@code size} overflows an int + * @throws ArithmeticException if the file {@code size} overflows an int */ @Override public byte[] get() throws UncheckedIOException { @@ -311,132 +227,43 @@ } /** - * Returns the contents of the file as a String, using the specified - * encoding. This method uses {@link #get()} to retrieve the - * contents of the file. - * - * @param charset The charset to use. + * Gets the content charset passed by the agent or {@code null} if not defined. * - * @return The contents of the file, as a string. - * - * @throws UnsupportedEncodingException if the requested character - * encoding is not available. + * @return The content charset passed by the agent or {@code null} if not defined. */ - @Override - public String getString(final String charset) - throws UnsupportedEncodingException, IOException { - return new String(get(), charset); + public String getCharSet() { + final ParameterParser parser = new ParameterParser(); + parser.setLowerCaseNames(true); + // Parameter parser can handle null input + final Map params = parser.parse(getContentType(), ';'); + return params.get("charset"); } /** - * Returns the contents of the file as a String, using the default - * character encoding. This method uses {@link #get()} to retrieve the - * contents of the file. - * - * TODO Consider making this method throw UnsupportedEncodingException. + * Gets the content type passed by the agent or {@code null} if not defined. * - * @return The contents of the file, as a string. + * @return The content type passed by the agent or {@code null} if not defined. */ @Override - public String getString() { - try { - final byte[] rawData = get(); - String charset = getCharSet(); - if (charset == null) { - charset = defaultCharset; - } - return new String(rawData, charset); - } catch (final IOException e) { - return ""; - } + public String getContentType() { + return contentType; } /** - * A convenience method to write an uploaded item to disk. The client code - * is not concerned with whether or not the item is stored in memory, or on - * disk in a temporary location. They just want to write the uploaded item - * to a file. - *

      - * This implementation first attempts to rename the uploaded item to the - * specified destination file, if the item was originally written to disk. - * Otherwise, the data will be copied to the specified file. - *

      - * This method is only guaranteed to work once, the first time it - * is invoked for a particular item. This is because, in the event that the - * method renames a temporary file, that file will no longer be available - * to copy or rename again at a later time. - * - * @param file The {@code File} into which the uploaded item should - * be stored. + * Gets the default charset for use when no explicit charset parameter is provided by the sender. * - * @throws Exception if an error occurs. - */ - @Override - public void write(final File file) throws Exception { - if (isInMemory()) { - try (OutputStream fout = Files.newOutputStream(file.toPath())) { - fout.write(get()); - } - } else { - final File outputFile = getStoreLocation(); - if (outputFile == null) { - /* - * For whatever reason we cannot write the - * file to disk. - */ - throw new FileUploadException( - "Cannot write uploaded file to disk!"); - } - // Save the length of the file - size = outputFile.length(); - /* - * The uploaded file is being stored on disk - * in a temporary location so move it to the - * desired file. - */ - if (file.exists() && !file.delete()) { - throw new FileUploadException("Cannot write uploaded file to disk!"); - } - if (!outputFile.renameTo(file)) { - BufferedInputStream in = null; - BufferedOutputStream out = null; - try { - in = new BufferedInputStream(new FileInputStream(outputFile)); - out = new BufferedOutputStream(new FileOutputStream(file)); - IOUtils.copy(in, out); - out.close(); - } finally { - IOUtils.closeQuietly(in); - IOUtils.closeQuietly(out); - } - } - } - } - - /** - * Deletes the underlying storage for a file item, including deleting any associated temporary disk file. - * This method can be used to ensure that this is done at an earlier time, thus preserving system resources. + * @return the default charset */ - @Override - public void delete() { - cachedContent = null; - final File outputFile = getStoreLocation(); - if (outputFile != null && !isInMemory() && outputFile.exists()) { - if (!outputFile.delete()) { - final String desc = "Cannot delete " + outputFile.toString(); - throw new UncheckedIOException(desc, new IOException(desc)); - } - } + public String getDefaultCharset() { + return defaultCharset; } /** - * Returns the name of the field in the multipart form corresponding to - * this file item. + * Gets the name of the field in the multipart form corresponding to this file item. * * @return The name of the form field. * * @see #setFieldName(String) - * */ @Override public String getFieldName() { @@ -444,55 +271,52 @@ } /** - * Sets the field name used to reference this file item. - * - * @param fieldName The name of the form field. - * - * @see #getFieldName() + * Gets the file item headers. * + * @return The file items headers. */ @Override - public void setFieldName(final String fieldName) { - this.fieldName = fieldName; + public FileItemHeaders getHeaders() { + return headers; } /** - * Determines whether or not a {@code FileItem} instance represents - * a simple form field. - * - * @return {@code true} if the instance represents a simple form - * field; {@code false} if it represents an uploaded file. + * Gets an {@link java.io.InputStream InputStream} that can be used to retrieve the contents of the file. * - * @see #setFormField(boolean) + * @return An {@link java.io.InputStream InputStream} that can be used to retrieve the contents of the file. * + * @throws IOException if an error occurs. */ @Override - public boolean isFormField() { - return isFormField; + public InputStream getInputStream() throws IOException { + if (!isInMemory()) { + return Files.newInputStream(dfos.getFile().toPath()); + } + if (cachedContent == null) { + cachedContent = dfos.getData(); + } + return new ByteArrayInputStream(cachedContent); } /** - * Specifies whether or not a {@code FileItem} instance represents - * a simple form field. - * - * @param state {@code true} if the instance represents a simple form - * field; {@code false} if it represents an uploaded file. + * Gets the original file name in the client's file system. * - * @see #isFormField() + * @return The original file name in the client's file system. * + * @throws InvalidFileNameException The file name contains a NUL character, which might be an indicator of a + * security attack. If you intend to use the file name anyways, catch the + * exception and use + * {@link org.apache.tomcat.util.http.fileupload.InvalidFileNameException#getName()}. */ @Override - public void setFormField(final boolean state) { - isFormField = state; + public String getName() { + return Streams.checkFileName(fileName); } /** - * Returns an {@link java.io.OutputStream OutputStream} that can - * be used for storing the contents of the file. - * - * @return An {@link java.io.OutputStream OutputStream} that can be used - * for storing the contents of the file. + * Gets an {@link java.io.OutputStream OutputStream} that can be used for storing the contents of the file. * + * @return An {@link java.io.OutputStream OutputStream} that can be used for storing the contents of the file. */ @Override public OutputStream getOutputStream() { @@ -503,20 +327,32 @@ return dfos; } - // --------------------------------------------------------- Public methods + /** + * Gets the size of the file. + * + * @return The size of the file, in bytes. + */ + @Override + public long getSize() { + if (size >= 0) { + return size; + } + if (cachedContent != null) { + return cachedContent.length; + } + if (dfos.isInMemory()) { + return dfos.getData().length; + } + return dfos.getFile().length(); + } /** - * Returns the {@link java.io.File} object for the {@code FileItem}'s - * data's temporary location on the disk. Note that for - * {@code FileItem}s that have their data stored in memory, - * this method will return {@code null}. When handling large - * files, you can use {@link java.io.File#renameTo(java.io.File)} to - * move the file to new location without copying the data, if the - * source and destination locations reside within the same logical - * volume. + * Gets the {@link java.io.File} object for the {@code FileItem}'s data's temporary location on the disk. Note + * that for {@code FileItem}s that have their data stored in memory, this method will return {@code null}. When + * handling large files, you can use {@link java.io.File#renameTo(java.io.File)} to move the file to new location + * without copying the data, if the source and destination locations reside within the same logical volume. * - * @return The data file, or {@code null} if the data is stored in - * memory. + * @return The data file, or {@code null} if the data is stored in memory. */ public File getStoreLocation() { if (dfos == null) { @@ -528,16 +364,49 @@ return dfos.getFile(); } - // ------------------------------------------------------ Protected methods + /** + * Gets the contents of the file as a String, using the default character encoding. This method uses + * {@link #get()} to retrieve the contents of the file. + *

      + * TODO Consider making this method throw UnsupportedEncodingException. + * + * @return The contents of the file, as a string. + */ + @Override + public String getString() { + final byte[] rawData = get(); + String charset = getCharSet(); + if (charset == null) { + charset = defaultCharset; + } + try { + return new String(rawData, charset); + } catch (final UnsupportedEncodingException e) { + return ""; + } + } /** - * Creates and returns a {@link java.io.File File} representing a uniquely - * named temporary file in the configured repository path. The lifetime of - * the file is tied to the lifetime of the {@code FileItem} instance; - * the file will be deleted when the instance is garbage collected. + * Gets the contents of the file as a String, using the specified encoding. This method uses {@link #get()} to + * retrieve the contents of the file. + * + * @param charset The charset to use. + * + * @return The contents of the file, as a string. + * + * @throws UnsupportedEncodingException if the requested character encoding is not available. + */ + @Override + public String getString(final String charset) throws UnsupportedEncodingException { + return new String(get(), charset); + } + + /** + * Creates and returns a {@link java.io.File File} representing a uniquely named temporary file in the configured + * repository path. The lifetime of the file is tied to the lifetime of the {@code FileItem} instance; the file will + * be deleted when the instance is garbage collected. *

      - * Note: Subclasses that override this method must ensure that they return the - * same File each time. + * Note: Subclasses that override this method must ensure that they return the same File each time. * * @return The {@link java.io.File File} to be used for temporary storage. */ @@ -555,71 +424,138 @@ return tempFile; } - // -------------------------------------------------------- Private methods - /** - * Returns an identifier that is unique within the class loader used to - * load this class, but does not have random-like appearance. + * Tests whether or not a {@code FileItem} instance represents a simple form field. * - * @return A String with the non-random looking instance identifier. + * @return {@code true} if the instance represents a simple form field; {@code false} if it represents an uploaded + * file. + * + * @see #setFormField(boolean) */ - private static String getUniqueId() { - final int limit = 100000000; - final int current = COUNTER.getAndIncrement(); - String id = Integer.toString(current); + @Override + public boolean isFormField() { + return formField; + } - // If you manage to get more than 100 million of ids, you'll - // start getting ids longer than 8 characters. - if (current < limit) { - id = ("00000000" + id).substring(id.length()); + /** + * Provides a hint as to whether or not the file contents will be read from memory. + * + * @return {@code true} if the file contents will be read from memory; {@code false} otherwise. + */ + @Override + public boolean isInMemory() { + if (cachedContent != null) { + return true; } - return id; + return dfos.isInMemory(); } /** - * Returns a string representation of this object. + * Sets the default charset for use when no explicit charset parameter is provided by the sender. * - * @return a string representation of this object. + * @param charset the default charset + */ + public void setDefaultCharset(final String charset) { + defaultCharset = charset; + } + + /** + * Sets the field name used to reference this file item. + * + * @param fieldName The name of the form field. + * + * @see #getFieldName() */ @Override - public String toString() { - return String.format("name=%s, StoreLocation=%s, size=%s bytes, isFormField=%s, FieldName=%s", - getName(), getStoreLocation(), Long.valueOf(getSize()), Boolean.valueOf(isFormField()), getFieldName()); + public void setFieldName(final String fieldName) { + this.fieldName = fieldName; } /** - * Returns the file item headers. - * @return The file items headers. + * Sets whether or not a {@code FileItem} instance represents a simple form field. + * + * @param formField {@code true} if the instance represents a simple form field; {@code false} if it represents an + * uploaded file. + * + * @see #isFormField() */ @Override - public FileItemHeaders getHeaders() { - return headers; + public void setFormField(final boolean formField) { + this.formField = formField; } /** * Sets the file item headers. - * @param pHeaders The file items headers. + * + * @param headers The file items headers. */ @Override - public void setHeaders(final FileItemHeaders pHeaders) { - headers = pHeaders; + public void setHeaders(final FileItemHeaders headers) { + this.headers = headers; } /** - * Returns the default charset for use when no explicit charset - * parameter is provided by the sender. - * @return the default charset + * Returns a string representation of this object. + * + * @return a string representation of this object. */ - public String getDefaultCharset() { - return defaultCharset; + @Override + public String toString() { + return String.format("name=%s, StoreLocation=%s, size=%s bytes, isFormField=%s, FieldName=%s", getName(), + getStoreLocation(), Long.valueOf(getSize()), Boolean.valueOf(isFormField()), getFieldName()); } /** - * Sets the default charset for use when no explicit charset - * parameter is provided by the sender. - * @param charset the default charset + * A convenience method to write an uploaded item to disk. The client code is not concerned with whether or not the + * item is stored in memory, or on disk in a temporary location. They just want to write the uploaded item to a + * file. + *

      + * This implementation first attempts to rename the uploaded item to the specified destination file, if the item was + * originally written to disk. Otherwise, the data will be copied to the specified file. + *

      + * This method is only guaranteed to work once, the first time it is invoked for a particular item. This is + * because, in the event that the method renames a temporary file, that file will no longer be available to copy or + * rename again at a later time. + * + * @param file The {@code File} into which the uploaded item should be stored. + * + * @throws Exception if an error occurs. */ - public void setDefaultCharset(final String charset) { - defaultCharset = charset; + @Override + public void write(final File file) throws Exception { + if (isInMemory()) { + try (OutputStream fout = Files.newOutputStream(file.toPath())) { + fout.write(get()); + } + } else { + final File outputFile = getStoreLocation(); + if (outputFile == null) { + /* + * For whatever reason we cannot write the file to disk. + */ + throw new FileUploadException("Cannot write uploaded file to disk!"); + } + // Save the length of the file + size = outputFile.length(); + /* + * The uploaded file is being stored on disk in a temporary location so move it to the desired file. + */ + if (file.exists() && !file.delete()) { + throw new FileUploadException("Cannot write uploaded file to disk!"); + } + if (!outputFile.renameTo(file)) { + BufferedInputStream in = null; + BufferedOutputStream out = null; + try { + in = new BufferedInputStream(new FileInputStream(outputFile)); + out = new BufferedOutputStream(new FileOutputStream(file)); + IOUtils.copy(in, out); + out.close(); + } finally { + IOUtils.closeQuietly(in); + IOUtils.closeQuietly(out); + } + } + } } } diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/http/fileupload/disk/DiskFileItemFactory.java tomcat10-10.1.52/java/org/apache/tomcat/util/http/fileupload/disk/DiskFileItemFactory.java --- tomcat10-10.1.40/java/org/apache/tomcat/util/http/fileupload/disk/DiskFileItemFactory.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/http/fileupload/disk/DiskFileItemFactory.java 2026-01-23 19:33:36.000000000 +0000 @@ -39,7 +39,7 @@ * {@code System.getProperty("java.io.tmpdir")}. * *

      - * NOTE: Files are created in the system default temp directory with + * NOTE: Files are created in the system default temp directory with * predictable names. This means that a local attacker with write access to that * directory can perform a TOUTOC attack to replace any uploaded file with a * file of the attackers choice. The implications of this will depend on how the @@ -58,15 +58,11 @@ */ public class DiskFileItemFactory implements FileItemFactory { - // ----------------------------------------------------- Manifest constants - /** * The default threshold above which uploads will be stored on disk. */ public static final int DEFAULT_SIZE_THRESHOLD = 10240; - // ----------------------------------------------------- Instance Variables - /** * The directory in which uploaded files will be stored, if stored on disk. */ @@ -83,8 +79,6 @@ */ private String defaultCharset = DiskFileItem.DEFAULT_CHARSET; - // ----------------------------------------------------------- Constructors - /** * Constructs an unconfigured instance of this class. The resulting factory * may be configured by calling the appropriate setter methods. @@ -108,36 +102,53 @@ this.repository = repository; } - // ------------------------------------------------------------- Properties - /** - * Returns the directory used to temporarily store files that are larger - * than the configured size threshold. - * - * @return The directory in which temporary files will be located. + * Create a new {@link DiskFileItem} + * instance from the supplied parameters and the local factory + * configuration. * - * @see #setRepository(java.io.File) + * @param fieldName The name of the form field. + * @param contentType The content type of the form field. + * @param isFormField {@code true} if this is a plain form field; + * {@code false} otherwise. + * @param fileName The name of the uploaded file, if any, as supplied + * by the browser or other client. * + * @return The newly created file item. */ - public File getRepository() { - return repository; + @Override + public FileItem createItem(final String fieldName, final String contentType, + final boolean isFormField, final String fileName) { + final DiskFileItem result = new DiskFileItem(fieldName, contentType, + isFormField, fileName, sizeThreshold, repository); + result.setDefaultCharset(defaultCharset); + return result; } /** - * Sets the directory used to temporarily store files that are larger + * Gets the default charset for use when no explicit charset + * parameter is provided by the sender. + * @return the default charset + */ + public String getDefaultCharset() { + return defaultCharset; + } + + /** + * Gets the directory used to temporarily store files that are larger * than the configured size threshold. * - * @param repository The directory in which temporary files will be located. + * @return The directory in which temporary files will be located. * - * @see #getRepository() + * @see #setRepository(java.io.File) * */ - public void setRepository(final File repository) { - this.repository = repository; + public File getRepository() { + return repository; } /** - * Returns the size threshold beyond which files are written directly to + * Gets the size threshold beyond which files are written directly to * disk. The default value is 10240 bytes. * * @return The size threshold, in bytes. @@ -149,57 +160,37 @@ } /** - * Sets the size threshold beyond which files are written directly to disk. - * - * @param sizeThreshold The size threshold, in bytes. - * - * @see #getSizeThreshold() + * Sets the default charset for use when no explicit charset + * parameter is provided by the sender. * + * @param charset the default charset */ - public void setSizeThreshold(final int sizeThreshold) { - this.sizeThreshold = sizeThreshold; + public void setDefaultCharset(final String charset) { + this.defaultCharset = charset; } - // --------------------------------------------------------- Public Methods - /** - * Create a new {@link DiskFileItem} - * instance from the supplied parameters and the local factory - * configuration. + * Sets the directory used to temporarily store files that are larger + * than the configured size threshold. * - * @param fieldName The name of the form field. - * @param contentType The content type of the form field. - * @param isFormField {@code true} if this is a plain form field; - * {@code false} otherwise. - * @param fileName The name of the uploaded file, if any, as supplied - * by the browser or other client. + * @param repository The directory in which temporary files will be located. + * + * @see #getRepository() * - * @return The newly created file item. - */ - @Override - public FileItem createItem(final String fieldName, final String contentType, - final boolean isFormField, final String fileName) { - final DiskFileItem result = new DiskFileItem(fieldName, contentType, - isFormField, fileName, sizeThreshold, repository); - result.setDefaultCharset(defaultCharset); - return result; - } - - /** - * Returns the default charset for use when no explicit charset - * parameter is provided by the sender. - * @return the default charset */ - public String getDefaultCharset() { - return defaultCharset; + public void setRepository(final File repository) { + this.repository = repository; } /** - * Sets the default charset for use when no explicit charset - * parameter is provided by the sender. - * @param pCharset the default charset + * Sets the size threshold beyond which files are written directly to disk. + * + * @param sizeThreshold The size threshold, in bytes. + * + * @see #getSizeThreshold() + * */ - public void setDefaultCharset(final String pCharset) { - defaultCharset = pCharset; + public void setSizeThreshold(final int sizeThreshold) { + this.sizeThreshold = sizeThreshold; } } diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/http/fileupload/impl/FileItemIteratorImpl.java tomcat10-10.1.52/java/org/apache/tomcat/util/http/fileupload/impl/FileItemIteratorImpl.java --- tomcat10-10.1.40/java/org/apache/tomcat/util/http/fileupload/impl/FileItemIteratorImpl.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/http/fileupload/impl/FileItemIteratorImpl.java 2026-01-23 19:33:36.000000000 +0000 @@ -198,6 +198,7 @@ String.format("The boundary specified in the %s header is too long", FileUploadBase.CONTENT_TYPE), iae); } multiPartStream.setHeaderEncoding(charEncoding); + multiPartStream.setPartHeaderSizeMax(fileUploadBase.getPartHeaderSizeMax()); } public MultipartStream getMultiPartStream() throws FileUploadException, IOException { diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/http/fileupload/package-info.java tomcat10-10.1.52/java/org/apache/tomcat/util/http/fileupload/package-info.java --- tomcat10-10.1.40/java/org/apache/tomcat/util/http/fileupload/package-info.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/http/fileupload/package-info.java 2026-01-23 19:33:36.000000000 +0000 @@ -16,8 +16,8 @@ */ /** - *

      NOTE: This code has been copied from commons-fileupload trunk - * 1.3 and commons-io 1.4 and package renamed to avoid clashes with + *

      NOTE: This code has been copied from commons-fileupload + * 1.x and commons-io 1.4 and package renamed to avoid clashes with * any web apps that may wish to use these libraries. *

      *

      diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/http/fileupload/servlet/ServletRequestContext.java tomcat10-10.1.52/java/org/apache/tomcat/util/http/fileupload/servlet/ServletRequestContext.java --- tomcat10-10.1.40/java/org/apache/tomcat/util/http/fileupload/servlet/ServletRequestContext.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/http/fileupload/servlet/ServletRequestContext.java 2026-01-23 19:33:36.000000000 +0000 @@ -32,15 +32,11 @@ */ public class ServletRequestContext implements UploadContext { - // ----------------------------------------------------- Instance Variables - /** * The request for which the context is being provided. */ private final HttpServletRequest request; - // ----------------------------------------------------------- Constructors - /** * Construct a context for this request. * @@ -50,7 +46,22 @@ this.request = request; } - // --------------------------------------------------------- Public Methods + /** + * Retrieve the content length of the request. + * + * @return The content length of the request. + * @since FileUpload 1.3 + */ + @Override + public long contentLength() { + long size; + try { + size = Long.parseLong(request.getHeader(FileUploadBase.CONTENT_LENGTH)); + } catch (final NumberFormatException e) { + size = request.getContentLength(); + } + return size; + } /** * Retrieve the character encoding for the request. @@ -73,23 +84,6 @@ } /** - * Retrieve the content length of the request. - * - * @return The content length of the request. - * @since FileUpload 1.3 - */ - @Override - public long contentLength() { - long size; - try { - size = Long.parseLong(request.getHeader(FileUploadBase.CONTENT_LENGTH)); - } catch (final NumberFormatException e) { - size = request.getContentLength(); - } - return size; - } - - /** * Retrieve the input stream for the request. * * @return The input stream for the request. @@ -109,7 +103,7 @@ @Override public String toString() { return String.format("ContentLength=%s, ContentType=%s", - Long.valueOf(this.contentLength()), this.getContentType()); + Long.valueOf(contentLength()), getContentType()); } } diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/http/fileupload/util/FileItemHeadersImpl.java tomcat10-10.1.52/java/org/apache/tomcat/util/http/fileupload/util/FileItemHeadersImpl.java --- tomcat10-10.1.40/java/org/apache/tomcat/util/http/fileupload/util/FileItemHeadersImpl.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/http/fileupload/util/FileItemHeadersImpl.java 2026-01-23 19:33:36.000000000 +0000 @@ -45,9 +45,29 @@ */ private final Map> headerNameToValueListMap = new LinkedHashMap<>(); + /** + * Constructs a new instance. + */ + public FileItemHeadersImpl() { + // empty + } + + /** + * Method to add header values to this instance. + * + * @param name name of this header + * @param value value of this header + */ + public synchronized void addHeader(final String name, final String value) { + final String nameLower = name.toLowerCase(Locale.ROOT); + final List headerValueList = headerNameToValueListMap. + computeIfAbsent(nameLower, k -> new ArrayList<>()); + headerValueList.add(value); + } + @Override public String getHeader(final String name) { - final String nameLower = name.toLowerCase(Locale.ENGLISH); + final String nameLower = name.toLowerCase(Locale.ROOT); final List headerValueList = headerNameToValueListMap.get(nameLower); if (null == headerValueList) { return null; @@ -62,7 +82,7 @@ @Override public Iterator getHeaders(final String name) { - final String nameLower = name.toLowerCase(Locale.ENGLISH); + final String nameLower = name.toLowerCase(Locale.ROOT); List headerValueList = headerNameToValueListMap.get(nameLower); if (null == headerValueList) { headerValueList = Collections.emptyList(); @@ -70,17 +90,4 @@ return headerValueList.iterator(); } - /** - * Method to add header values to this instance. - * - * @param name name of this header - * @param value value of this header - */ - public synchronized void addHeader(final String name, final String value) { - final String nameLower = name.toLowerCase(Locale.ENGLISH); - final List headerValueList = headerNameToValueListMap. - computeIfAbsent(nameLower, k -> new ArrayList<>()); - headerValueList.add(value); - } - } diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/http/fileupload/util/LimitedInputStream.java tomcat10-10.1.52/java/org/apache/tomcat/util/http/fileupload/util/LimitedInputStream.java --- tomcat10-10.1.40/java/org/apache/tomcat/util/http/fileupload/util/LimitedInputStream.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/http/fileupload/util/LimitedInputStream.java 2026-01-23 19:33:36.000000000 +0000 @@ -45,27 +45,15 @@ * Creates a new instance. * * @param inputStream The input stream, which shall be limited. - * @param pSizeMax The limit; no more than this number of bytes + * @param sizeMax The limit; no more than this number of bytes * shall be returned by the source stream. */ - public LimitedInputStream(final InputStream inputStream, final long pSizeMax) { + public LimitedInputStream(final InputStream inputStream, final long sizeMax) { super(inputStream); - sizeMax = pSizeMax; + this.sizeMax = sizeMax; } /** - * Called to indicate, that the input streams limit has - * been exceeded. - * - * @param pSizeMax The input streams limit, in bytes. - * @param pCount The actual number of bytes. - * @throws IOException The called method is expected - * to raise an IOException. - */ - protected abstract void raiseError(long pSizeMax, long pCount) - throws IOException; - - /** * Called to check, whether the input streams * limit is reached. * @@ -78,6 +66,43 @@ } /** + * Closes this input stream and releases any system resources + * associated with the stream. + * This + * method simply performs {@code in.close()}. + * + * @throws IOException if an I/O error occurs. + * @see java.io.FilterInputStream#in + */ + @Override + public void close() throws IOException { + closed = true; + super.close(); + } + + /** + * Returns, whether this stream is already closed. + * + * @return True, if the stream is closed, otherwise false. + * @throws IOException An I/O error occurred. + */ + @Override + public boolean isClosed() throws IOException { + return closed; + } + + /** + * Called to indicate, that the input streams limit has + * been exceeded. + * + * @param sizeMax The input streams limit, in bytes. + * @param count The actual number of bytes. + * @throws IOException The called method is expected + * to raise an IOException. + */ + protected abstract void raiseError(long sizeMax, long count) throws IOException; + + /** * Reads the next byte of data from this input stream. The value * byte is returned as an {@code int} in the range * {@code 0} to {@code 255}. If no byte is available @@ -137,30 +162,4 @@ return res; } - /** - * Returns, whether this stream is already closed. - * - * @return True, if the stream is closed, otherwise false. - * @throws IOException An I/O error occurred. - */ - @Override - public boolean isClosed() throws IOException { - return closed; - } - - /** - * Closes this input stream and releases any system resources - * associated with the stream. - * This - * method simply performs {@code in.close()}. - * - * @throws IOException if an I/O error occurs. - * @see java.io.FilterInputStream#in - */ - @Override - public void close() throws IOException { - closed = true; - super.close(); - } - } diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/http/fileupload/util/Streams.java tomcat10-10.1.52/java/org/apache/tomcat/util/http/fileupload/util/Streams.java --- tomcat10-10.1.40/java/org/apache/tomcat/util/http/fileupload/util/Streams.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/http/fileupload/util/Streams.java 2026-01-23 19:33:36.000000000 +0000 @@ -28,24 +28,47 @@ public final class Streams { /** - * Private constructor, to prevent instantiation. - * This class has only static methods. - */ - private Streams() { - // Does nothing - } - - /** * Default buffer size for use in * {@link #copy(InputStream, OutputStream, boolean)}. */ public static final int DEFAULT_BUFFER_SIZE = 8192; /** + * Checks, whether the given file name is valid in the sense, + * that it doesn't contain any NUL characters. If the file name + * is valid, it will be returned without any modifications. Otherwise, + * an {@link InvalidFileNameException} is raised. + * + * @param fileName The file name to check + * @return Unmodified file name, if valid. + * @throws InvalidFileNameException The file name was found to be invalid. + */ + public static String checkFileName(final String fileName) { + if (fileName != null && fileName.indexOf('\u0000') != -1) { + // fileName.replace("\u0000", "\\0") + final StringBuilder sb = new StringBuilder(); + for (int i = 0; i < fileName.length(); i++) { + final char c = fileName.charAt(i); + switch (c) { + case 0: + sb.append("\\0"); + break; + default: + sb.append(c); + break; + } + } + throw new InvalidFileNameException(fileName, + "Invalid file name: " + sb); + } + return fileName; + } + + /** * Copies the contents of the given {@link InputStream} * to the given {@link OutputStream}. Shortcut for *

      -     *   copy(pInputStream, pOutputStream, new byte[8192]);
      +     *   copy(pInputStream, outputStream, new byte[8192]);
            * 
      * * @param inputStream The input stream, which is being read. @@ -116,35 +139,12 @@ } } - /** - * Checks, whether the given file name is valid in the sense, - * that it doesn't contain any NUL characters. If the file name - * is valid, it will be returned without any modifications. Otherwise, - * an {@link InvalidFileNameException} is raised. - * - * @param fileName The file name to check - * @return Unmodified file name, if valid. - * @throws InvalidFileNameException The file name was found to be invalid. + /** + * Private constructor, to prevent instantiation. + * This class has only static methods. */ - public static String checkFileName(final String fileName) { - if (fileName != null && fileName.indexOf('\u0000') != -1) { - // pFileName.replace("\u0000", "\\0") - final StringBuilder sb = new StringBuilder(); - for (int i = 0; i < fileName.length(); i++) { - final char c = fileName.charAt(i); - switch (c) { - case 0: - sb.append("\\0"); - break; - default: - sb.append(c); - break; - } - } - throw new InvalidFileNameException(fileName, - "Invalid file name: " + sb); - } - return fileName; + private Streams() { + // Does nothing } } diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/http/fileupload/util/mime/MimeUtility.java tomcat10-10.1.52/java/org/apache/tomcat/util/http/fileupload/util/mime/MimeUtility.java --- tomcat10-10.1.40/java/org/apache/tomcat/util/http/fileupload/util/mime/MimeUtility.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/http/fileupload/util/mime/MimeUtility.java 2026-01-23 19:33:36.000000000 +0000 @@ -76,13 +76,6 @@ } /** - * Hidden constructor, this class must not be instantiated. - */ - private MimeUtility() { - // do nothing - } - - /** * Decode a string of text obtained from a mail header into * its proper form. The text generally will consist of a * string of tokens, some of which may be encoded using @@ -207,7 +200,7 @@ } // pull out the character set information (this is the MIME name at this point). - final String charset = word.substring(2, charsetPos).toLowerCase(Locale.ENGLISH); + final String charset = word.substring(2, charsetPos).toLowerCase(Locale.ROOT); // now pull out the encoding token the same way. final int encodingPos = word.indexOf('?', charsetPos + 1); @@ -266,7 +259,7 @@ return null; } - final String mappedCharset = MIME2JAVA.get(charset.toLowerCase(Locale.ENGLISH)); + final String mappedCharset = MIME2JAVA.get(charset.toLowerCase(Locale.ROOT)); // if there is no mapping, then the original name is used. Many of the MIME character set // names map directly back into Java. The reverse isn't necessarily true. if (mappedCharset == null) { @@ -275,4 +268,11 @@ return mappedCharset; } + /** + * Hidden constructor, this class must not be instantiated. + */ + private MimeUtility() { + // do nothing + } + } diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/http/fileupload/util/mime/ParseException.java tomcat10-10.1.52/java/org/apache/tomcat/util/http/fileupload/util/mime/ParseException.java --- tomcat10-10.1.40/java/org/apache/tomcat/util/http/fileupload/util/mime/ParseException.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/http/fileupload/util/mime/ParseException.java 2026-01-23 19:33:36.000000000 +0000 @@ -17,6 +17,8 @@ package org.apache.tomcat.util.http.fileupload.util.mime; /** + * Thrown for a parsing problem. + * * @since FileUpload 1.3 */ final class ParseException extends Exception { diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/http/fileupload/util/mime/QuotedPrintableDecoder.java tomcat10-10.1.52/java/org/apache/tomcat/util/http/fileupload/util/mime/QuotedPrintableDecoder.java --- tomcat10-10.1.40/java/org/apache/tomcat/util/http/fileupload/util/mime/QuotedPrintableDecoder.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/http/fileupload/util/mime/QuotedPrintableDecoder.java 2026-01-23 19:33:36.000000000 +0000 @@ -25,17 +25,35 @@ final class QuotedPrintableDecoder { /** - * The shift value required to create the upper nibble - * from the first of 2 byte values converted from ascii hex. + * Carriage return character '{@value}'. */ - private static final int UPPER_NIBBLE_SHIFT = Byte.SIZE / 2; + private static final char CR = '\r'; /** - * Hidden constructor, this class must not be instantiated. + * Equal character '{@value}'. */ - private QuotedPrintableDecoder() { - // do nothing - } + private static final char EQUAL = '='; + + /** + * Line feed character '{@value}'. + */ + private static final char LF = '\n'; + + /** + * Space character '{@value}'. + */ + private static final char SP = ' '; + + /** + * Underscore character '{@value}'. + */ + private static final char UNDERSCORE = '_'; + + /** + * The shift value required to create the upper nibble + * from the first of 2 byte values converted from ASCII hex. + */ + private static final int UPPER_NIBBLE_SHIFT = Byte.SIZE / 2; /** * Decode the encoded byte data writing it to the given output stream. @@ -56,9 +74,9 @@ final byte ch = data[off++]; // space characters were translated to '_' on encode, so we need to translate them back. - if (ch == '_') { - out.write(' '); - } else if (ch == '=') { + if (ch == UNDERSCORE) { + out.write(SP); + } else if (ch == EQUAL) { // we found an encoded character. Reduce the 3 char sequence to one. // but first, make sure we have two characters to work with. if (off + 1 >= endOffset) { @@ -69,8 +87,8 @@ final byte b2 = data[off++]; // we've found an encoded carriage return. The next char needs to be a newline - if (b1 == '\r') { - if (b2 != '\n') { + if (b1 == CR) { + if (b2 != LF) { throw new IOException("Invalid quoted printable encoding; CR must be followed by LF"); } // this was a soft linebreak inserted by the encoding. We just toss this away @@ -79,7 +97,7 @@ // this is a hex pair we need to convert back to a single byte. final int c1 = hexToBinary(b1); final int c2 = hexToBinary(b2); - out.write((c1 << UPPER_NIBBLE_SHIFT) | c2); + out.write(c1 << UPPER_NIBBLE_SHIFT | c2); // 3 bytes in, one byte out bytesWritten++; } @@ -96,7 +114,7 @@ /** * Convert a hex digit to the binary value it represents. * - * @param b the ascii hex byte to convert (0-0, A-F, a-f) + * @param b the ASCII hex byte to convert (0-0, A-F, a-f) * @return the int value of the hex byte, 0-15 * @throws IOException if the byte is not a valid hex digit. */ @@ -109,4 +127,11 @@ return i; } + /** + * Hidden constructor, this class must not be instantiated. + */ + private QuotedPrintableDecoder() { + // do nothing + } + } diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/http/fileupload/util/mime/RFC2231Utility.java tomcat10-10.1.52/java/org/apache/tomcat/util/http/fileupload/util/mime/RFC2231Utility.java --- tomcat10-10.1.40/java/org/apache/tomcat/util/http/fileupload/util/mime/RFC2231Utility.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/http/fileupload/util/mime/RFC2231Utility.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,154 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.tomcat.util.http.fileupload.util.mime; - -import java.io.ByteArrayOutputStream; -import java.io.UnsupportedEncodingException; -/** - * Utility class to decode/encode character set on HTTP Header fields based on RFC 2231. - * This implementation adheres to RFC 5987 in particular, which was defined for HTTP headers. - *

      - * RFC 5987 builds on RFC 2231, but has lesser scope like - * mandatory charset definition - * and no parameter continuation - * - * @see RFC 2231 - * @see RFC 5987 - */ -public final class RFC2231Utility { - /** - * The Hexadecimal values char array. - */ - private static final char[] HEX_DIGITS = "0123456789ABCDEF".toCharArray(); - /** - * The Hexadecimal representation of 127. - */ - private static final byte MASK = 0x7f; - /** - * The Hexadecimal representation of 128. - */ - private static final int MASK_128 = 0x80; - /** - * The Hexadecimal decode value. - */ - private static final byte[] HEX_DECODE = new byte[MASK_128]; - - // create a ASCII decoded array of Hexadecimal values - static { - for (int i = 0; i < HEX_DIGITS.length; i++) { - HEX_DECODE[HEX_DIGITS[i]] = (byte) i; - HEX_DECODE[Character.toLowerCase(HEX_DIGITS[i])] = (byte) i; - } - } - - /** - * Private constructor so that no instances can be created. This class - * contains only static utility methods. - */ - private RFC2231Utility() { - } - - /** - * Checks if Asterisk (*) at the end of parameter name to indicate, - * if it has charset and language information to decode the value. - * @param paramName The parameter, which is being checked. - * @return {@code true}, if encoded as per RFC 2231, {@code false} otherwise - */ - public static boolean hasEncodedValue(final String paramName) { - if (paramName != null) { - return paramName.lastIndexOf('*') == (paramName.length() - 1); - } - return false; - } - - /** - * If {@code paramName} has Asterisk (*) at the end, it will be stripped off, - * else the passed value will be returned. - * @param paramName The parameter, which is being inspected. - * @return stripped {@code paramName} of Asterisk (*), if RFC2231 encoded - */ - public static String stripDelimiter(final String paramName) { - if (hasEncodedValue(paramName)) { - final StringBuilder paramBuilder = new StringBuilder(paramName); - paramBuilder.deleteCharAt(paramName.lastIndexOf('*')); - return paramBuilder.toString(); - } - return paramName; - } - - /** - * Decode a string of text obtained from a HTTP header as per RFC 2231 - *

      - * Eg 1. {@code us-ascii'en-us'This%20is%20%2A%2A%2Afun%2A%2A%2A} - * will be decoded to {@code This is ***fun***} - *

      - * Eg 2. {@code iso-8859-1'en'%A3%20rate} - * will be decoded to {@code £ rate} - *

      - * Eg 3. {@code UTF-8''%c2%a3%20and%20%e2%82%ac%20rates} - * will be decoded to {@code £ and € rates} - * - * @param encodedText - Text to be decoded has a format of {@code ''} - * and ASCII only - * @return Decoded text based on charset encoding - * @throws UnsupportedEncodingException The requested character set wasn't found. - */ - public static String decodeText(final String encodedText) throws UnsupportedEncodingException { - final int langDelimitStart = encodedText.indexOf('\''); - if (langDelimitStart == -1) { - // missing charset - return encodedText; - } - final String mimeCharset = encodedText.substring(0, langDelimitStart); - final int langDelimitEnd = encodedText.indexOf('\'', langDelimitStart + 1); - if (langDelimitEnd == -1) { - // missing language - return encodedText; - } - final byte[] bytes = fromHex(encodedText.substring(langDelimitEnd + 1)); - return new String(bytes, getJavaCharset(mimeCharset)); - } - - /** - * Convert {@code text} to their corresponding Hex value. - * @param text - ASCII text input - * @return Byte array of characters decoded from ASCII table - */ - private static byte[] fromHex(final String text) { - final int shift = 4; - final ByteArrayOutputStream out = new ByteArrayOutputStream(text.length()); - for (int i = 0; i < text.length();) { - final char c = text.charAt(i++); - if (c == '%') { - if (i > text.length() - 2) { - break; // unterminated sequence - } - final byte b1 = HEX_DECODE[text.charAt(i++) & MASK]; - final byte b2 = HEX_DECODE[text.charAt(i++) & MASK]; - out.write((b1 << shift) | b2); - } else { - out.write((byte) c); - } - } - return out.toByteArray(); - } - - private static String getJavaCharset(final String mimeCharset) { - // good enough for standard values - return mimeCharset; - } -} diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/http/parser/Cookie.java tomcat10-10.1.52/java/org/apache/tomcat/util/http/parser/Cookie.java --- tomcat10-10.1.40/java/org/apache/tomcat/util/http/parser/Cookie.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/http/parser/Cookie.java 2026-01-23 19:33:36.000000000 +0000 @@ -68,8 +68,8 @@ // %x21 / %x23-2B / %x2D-3A / %x3C-5B / %x5D-7E (RFC6265) // %x80 to %xFF (UTF-8) for (int i = 0; i < 256; i++) { - isCookieOctet[i] = !(i < 0x21 || i == QUOTE_BYTE || i == COMMA_BYTE || - i == SEMICOLON_BYTE || i == SLASH_BYTE || i == DEL_BYTE); + isCookieOctet[i] = !(i < 0x21 || i == QUOTE_BYTE || i == COMMA_BYTE || i == SEMICOLON_BYTE || + i == SLASH_BYTE || i == DEL_BYTE); } for (int i = 0; i < 256; i++) { isText[i] = !(i < TAB_BYTE || (i > TAB_BYTE && i < SPACE_BYTE) || i == DEL_BYTE); diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/http/parser/HttpHeaderParser.java tomcat10-10.1.52/java/org/apache/tomcat/util/http/parser/HttpHeaderParser.java --- tomcat10-10.1.40/java/org/apache/tomcat/util/http/parser/HttpHeaderParser.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/http/parser/HttpHeaderParser.java 2026-01-23 19:33:36.000000000 +0000 @@ -33,10 +33,6 @@ private static final byte SP = (byte) ' '; private static final byte HT = (byte) '\t'; private static final byte COLON = (byte) ':'; - private static final byte A = (byte) 'A'; - private static final byte a = (byte) 'a'; - private static final byte Z = (byte) 'Z'; - private static final byte LC_OFFSET = A - a; private final HeaderDataSource source; private final MimeHeaders headers; @@ -150,11 +146,6 @@ // skipLine() will handle the error return skipLine(); } - - // chr is next byte of header name. Convert to lowercase. - if (chr >= A && chr <= Z) { - source.getHeaderByteBuffer().put(pos, (byte) (chr - LC_OFFSET)); - } } // Skip the line and ignore the header diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/http/parser/LocalStrings_es.properties tomcat10-10.1.52/java/org/apache/tomcat/util/http/parser/LocalStrings_es.properties --- tomcat10-10.1.40/java/org/apache/tomcat/util/http/parser/LocalStrings_es.properties 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/http/parser/LocalStrings_es.properties 2026-01-23 19:33:36.000000000 +0000 @@ -21,5 +21,6 @@ http.illegalCharacterIpv4=El caracter [{0}] nunca es válido en una dirección IPv4.\n http.illegalCharacterIpv6=El caracter [{0}] nunca es válido en una dirección IPv6.\n http.invalidHextet=Hextet no válido. Hextet debe consistir de 4 caracteres hexadecimales o menos. +http.invalidIpv4Location=La dirección IPv6 contiene una dirección IPv4 incrustada en una ubicación no válida. http.singleColonEnd=Una dirección IPv6 no puede terminar con solo un ':'.\n http.tooManyColons=Una dirección IPv6 no puede contener más de 2 caracteres ":" seguidos diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/http/parser/MediaType.java tomcat10-10.1.52/java/org/apache/tomcat/util/http/parser/MediaType.java --- tomcat10-10.1.40/java/org/apache/tomcat/util/http/parser/MediaType.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/http/parser/MediaType.java 2026-01-23 19:33:36.000000000 +0000 @@ -17,7 +17,7 @@ package org.apache.tomcat.util.http.parser; import java.io.IOException; -import java.io.StringReader; +import java.io.Reader; import java.util.LinkedHashMap; import java.util.Locale; import java.util.Map; @@ -124,7 +124,7 @@ * * @throws IOException if there was a problem reading the input */ - public static MediaType parseMediaType(StringReader input) throws IOException { + public static MediaType parseMediaType(Reader input) throws IOException { // Type (required) String type = HttpParser.readToken(input); @@ -151,9 +151,11 @@ while (lookForSemiColon == SkipResult.FOUND) { String attribute = HttpParser.readToken(input); - String value = ""; + String value; if (HttpParser.skipConstant(input, "=") == SkipResult.FOUND) { value = HttpParser.readTokenOrQuotedString(input, true); + } else { + value = ""; } if (attribute != null) { diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/http/parser/MediaTypeCache.java tomcat10-10.1.52/java/org/apache/tomcat/util/http/parser/MediaTypeCache.java --- tomcat10-10.1.40/java/org/apache/tomcat/util/http/parser/MediaTypeCache.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/http/parser/MediaTypeCache.java 2026-01-23 19:33:36.000000000 +0000 @@ -51,7 +51,7 @@ MediaType m = null; try { m = MediaType.parseMediaType(new StringReader(input)); - } catch (IOException e) { + } catch (IOException ignore) { // Ignore - return null } if (m != null) { diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/json/JSONFilter.java tomcat10-10.1.52/java/org/apache/tomcat/util/json/JSONFilter.java --- tomcat10-10.1.40/java/org/apache/tomcat/util/json/JSONFilter.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/json/JSONFilter.java 2026-01-23 19:33:36.000000000 +0000 @@ -17,15 +17,16 @@ package org.apache.tomcat.util.json; /** - * Provides escaping of values so they can be included in a JSON document. - * Escaping is based on the definition of JSON found in - * RFC 8259. + * Provides escaping of values so they can be included in a JSON document. Escaping is based on the definition of JSON + * found in RFC 8259. */ public class JSONFilter { /** * Escape the given char. + * * @param c the char + * * @return a char array with the escaped sequence */ public static char[] escape(char c) { @@ -48,7 +49,9 @@ /** * Escape the given string. + * * @param input the string + * * @return the escaped string */ public static String escape(String input) { @@ -57,7 +60,9 @@ /** * Escape the given char sequence. + * * @param input the char sequence + * * @return the escaped char sequence */ public static CharSequence escape(CharSequence input) { @@ -66,16 +71,17 @@ /** * Escape the given char sequence. - * @param input the char sequence - * @param off the offset on which escaping will start + * + * @param input the char sequence + * @param off the offset on which escaping will start * @param length the length which should be escaped + * * @return the escaped char sequence corresponding to the specified range */ public static CharSequence escape(CharSequence input, int off, int length) { /* - * While any character MAY be escaped, only U+0000 to U+001F (control - * characters), U+0022 (quotation mark) and U+005C (reverse solidus) - * MUST be escaped. + * While any character MAY be escaped, only U+0000 to U+001F (control characters), U+0022 (quotation mark) and + * U+005C (reverse solidus) MUST be escaped. */ StringBuilder escaped = null; int lastUnescapedStart = off; diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/json/JSONParser.java tomcat10-10.1.52/java/org/apache/tomcat/util/json/JSONParser.java --- tomcat10-10.1.40/java/org/apache/tomcat/util/json/JSONParser.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/json/JSONParser.java 2026-01-23 19:33:36.000000000 +0000 @@ -20,8 +20,8 @@ /** * Basic JSON parser generated by JavaCC. It consumes the input provided through the constructor when - * {@code parseObject()}, {@code parseList()}, or {@code parse()} are called, and there is no way to directly - * reset the state. + * {@code parseObject()}, {@code parseList()}, or {@code parse()} are called, and there is no way to directly reset the + * state. */ @SuppressWarnings("all") // Ignore warnings in generated code public class JSONParser implements JSONParserConstants { @@ -35,8 +35,8 @@ /** * Parses a JSON object into a Java {@code Map}. */ - public java.util.LinkedHashMap parseObject() throws ParseException { - java.util.LinkedHashMap toReturn = object(); + public java.util.LinkedHashMap parseObject() throws ParseException { + java.util.LinkedHashMap toReturn = object(); if (!ensureEOF()) { throw new IllegalStateException("Expected EOF, but still had content to parse"); } @@ -81,575 +81,633 @@ return this.nativeNumbers; } - final public boolean ensureEOF() throws ParseException { - jj_consume_token(0); -{if ("" != null) { - return true; -}} - throw new Error("Missing return statement in function"); -} + final public boolean ensureEOF() throws ParseException { + jj_consume_token(0); + { + if ("" != null) { + return true; + } + } + throw new Error("Missing return statement in function"); + } - final public Object anything() throws ParseException {Object x; - switch (jj_nt.kind) { - case BRACE_OPEN:{ - x = object(); - break; - } - case BRACKET_OPEN:{ - x = list(); - break; - } - case NUMBER_INTEGER: - case NUMBER_DECIMAL: - case TRUE: - case FALSE: - case NULL: - case STRING_SINGLE_EMPTY: - case STRING_DOUBLE_EMPTY: - case STRING_SINGLE_NONEMPTY: - case STRING_DOUBLE_NONEMPTY:{ - x = value(); - break; - } - default: - jj_la1[0] = jj_gen; - jj_consume_token(-1); - throw new ParseException(); - } -{if ("" != null) { - return x; -}} - throw new Error("Missing return statement in function"); -} + final public Object anything() throws ParseException { + Object x; + switch (jj_nt.kind) { + case BRACE_OPEN: { + x = object(); + break; + } + case BRACKET_OPEN: { + x = list(); + break; + } + case NUMBER_INTEGER: + case NUMBER_DECIMAL: + case TRUE: + case FALSE: + case NULL: + case STRING_SINGLE_EMPTY: + case STRING_DOUBLE_EMPTY: + case STRING_SINGLE_NONEMPTY: + case STRING_DOUBLE_NONEMPTY: { + x = value(); + break; + } + default: + jj_la1[0] = jj_gen; + jj_consume_token(-1); + throw new ParseException(); + } + { + if ("" != null) { + return x; + } + } + throw new Error("Missing return statement in function"); + } - final public String objectKey() throws ParseException {Object o; - String key; - switch (jj_nt.kind) { - case STRING_SINGLE_EMPTY: - case STRING_DOUBLE_EMPTY: - case STRING_SINGLE_NONEMPTY: - case STRING_DOUBLE_NONEMPTY:{ - key = string(); - break; - } - case SYMBOL:{ - key = symbol(); - break; - } - case NULL:{ - nullValue(); -key = null; - break; - } - case NUMBER_INTEGER: - case NUMBER_DECIMAL: - case TRUE: - case FALSE:{ - switch (jj_nt.kind) { - case TRUE: - case FALSE:{ - o = booleanValue(); - break; - } - case NUMBER_INTEGER: - case NUMBER_DECIMAL:{ - o = number(); - break; - } - default: - jj_la1[1] = jj_gen; - jj_consume_token(-1); - throw new ParseException(); - } -key = o.toString(); - break; - } - default: - jj_la1[2] = jj_gen; - jj_consume_token(-1); - throw new ParseException(); - } -{if ("" != null) { - return key; -}} - throw new Error("Missing return statement in function"); -} + final public String objectKey() throws ParseException { + Object o; + String key; + switch (jj_nt.kind) { + case STRING_SINGLE_EMPTY: + case STRING_DOUBLE_EMPTY: + case STRING_SINGLE_NONEMPTY: + case STRING_DOUBLE_NONEMPTY: { + key = string(); + break; + } + case SYMBOL: { + key = symbol(); + break; + } + case NULL: { + nullValue(); + key = null; + break; + } + case NUMBER_INTEGER: + case NUMBER_DECIMAL: + case TRUE: + case FALSE: { + switch (jj_nt.kind) { + case TRUE: + case FALSE: { + o = booleanValue(); + break; + } + case NUMBER_INTEGER: + case NUMBER_DECIMAL: { + o = number(); + break; + } + default: + jj_la1[1] = jj_gen; + jj_consume_token(-1); + throw new ParseException(); + } + key = o.toString(); + break; + } + default: + jj_la1[2] = jj_gen; + jj_consume_token(-1); + throw new ParseException(); + } + { + if ("" != null) { + return key; + } + } + throw new Error("Missing return statement in function"); + } - final public java.util.LinkedHashMap object() throws ParseException {final java.util.LinkedHashMap map = new java.util.LinkedHashMap(); - String key; - Object value; - jj_consume_token(BRACE_OPEN); - switch (jj_nt.kind) { - case NUMBER_INTEGER: - case NUMBER_DECIMAL: - case TRUE: - case FALSE: - case NULL: - case STRING_SINGLE_EMPTY: - case STRING_DOUBLE_EMPTY: - case STRING_SINGLE_NONEMPTY: - case STRING_DOUBLE_NONEMPTY: - case SYMBOL:{ - key = objectKey(); - jj_consume_token(COLON); - value = anything(); -map.put(key, value); -key = null; value = null; - label_1: - while (true) { + final public java.util.LinkedHashMap object() throws ParseException { + final java.util.LinkedHashMap map = new java.util.LinkedHashMap(); + String key; + Object value; + jj_consume_token(BRACE_OPEN); switch (jj_nt.kind) { - case COMMA:{ - ; - break; - } - default: - jj_la1[3] = jj_gen; - break label_1; - } - jj_consume_token(COMMA); - key = objectKey(); - jj_consume_token(COLON); - value = anything(); -map.put(key, value); -key = null; value = null; - } - break; - } - default: - jj_la1[4] = jj_gen; - ; - } - jj_consume_token(BRACE_CLOSE); -{if ("" != null) { - return map; -}} - throw new Error("Missing return statement in function"); -} + case NUMBER_INTEGER: + case NUMBER_DECIMAL: + case TRUE: + case FALSE: + case NULL: + case STRING_SINGLE_EMPTY: + case STRING_DOUBLE_EMPTY: + case STRING_SINGLE_NONEMPTY: + case STRING_DOUBLE_NONEMPTY: + case SYMBOL: { + key = objectKey(); + jj_consume_token(COLON); + value = anything(); + map.put(key, value); + key = null; + value = null; + label_1: + while (true) { + switch (jj_nt.kind) { + case COMMA: { + ; + break; + } + default: + jj_la1[3] = jj_gen; + break label_1; + } + jj_consume_token(COMMA); + key = objectKey(); + jj_consume_token(COLON); + value = anything(); + map.put(key, value); + key = null; + value = null; + } + break; + } + default: + jj_la1[4] = jj_gen; + ; + } + jj_consume_token(BRACE_CLOSE); + { + if ("" != null) { + return map; + } + } + throw new Error("Missing return statement in function"); + } - final public java.util.ArrayList list() throws ParseException {final java.util.ArrayList list = new java.util.ArrayList(); - Object value; - jj_consume_token(BRACKET_OPEN); - switch (jj_nt.kind) { - case BRACE_OPEN: - case BRACKET_OPEN: - case NUMBER_INTEGER: - case NUMBER_DECIMAL: - case TRUE: - case FALSE: - case NULL: - case STRING_SINGLE_EMPTY: - case STRING_DOUBLE_EMPTY: - case STRING_SINGLE_NONEMPTY: - case STRING_DOUBLE_NONEMPTY:{ - value = anything(); -list.add(value); -value = null; - label_2: - while (true) { + final public java.util.ArrayList list() throws ParseException { + final java.util.ArrayList list = new java.util.ArrayList(); + Object value; + jj_consume_token(BRACKET_OPEN); switch (jj_nt.kind) { - case COMMA:{ - ; - break; - } - default: - jj_la1[5] = jj_gen; - break label_2; - } - jj_consume_token(COMMA); - value = anything(); -list.add(value); -value = null; - } - break; - } - default: - jj_la1[6] = jj_gen; - ; - } - jj_consume_token(BRACKET_CLOSE); -list.trimToSize(); - {if ("" != null) { - return list; - }} - throw new Error("Missing return statement in function"); -} + case BRACE_OPEN: + case BRACKET_OPEN: + case NUMBER_INTEGER: + case NUMBER_DECIMAL: + case TRUE: + case FALSE: + case NULL: + case STRING_SINGLE_EMPTY: + case STRING_DOUBLE_EMPTY: + case STRING_SINGLE_NONEMPTY: + case STRING_DOUBLE_NONEMPTY: { + value = anything(); + list.add(value); + value = null; + label_2: + while (true) { + switch (jj_nt.kind) { + case COMMA: { + ; + break; + } + default: + jj_la1[5] = jj_gen; + break label_2; + } + jj_consume_token(COMMA); + value = anything(); + list.add(value); + value = null; + } + break; + } + default: + jj_la1[6] = jj_gen; + ; + } + jj_consume_token(BRACKET_CLOSE); + list.trimToSize(); + { + if ("" != null) { + return list; + } + } + throw new Error("Missing return statement in function"); + } - final public Object value() throws ParseException {Object x; - switch (jj_nt.kind) { - case STRING_SINGLE_EMPTY: - case STRING_DOUBLE_EMPTY: - case STRING_SINGLE_NONEMPTY: - case STRING_DOUBLE_NONEMPTY:{ - x = string(); - break; - } - case NUMBER_INTEGER: - case NUMBER_DECIMAL:{ - x = number(); - break; - } - case TRUE: - case FALSE:{ - x = booleanValue(); - break; - } - case NULL:{ - x = nullValue(); - break; - } - default: - jj_la1[7] = jj_gen; - jj_consume_token(-1); - throw new ParseException(); - } -{if ("" != null) { - return x; -}} - throw new Error("Missing return statement in function"); -} + final public Object value() throws ParseException { + Object x; + switch (jj_nt.kind) { + case STRING_SINGLE_EMPTY: + case STRING_DOUBLE_EMPTY: + case STRING_SINGLE_NONEMPTY: + case STRING_DOUBLE_NONEMPTY: { + x = string(); + break; + } + case NUMBER_INTEGER: + case NUMBER_DECIMAL: { + x = number(); + break; + } + case TRUE: + case FALSE: { + x = booleanValue(); + break; + } + case NULL: { + x = nullValue(); + break; + } + default: + jj_la1[7] = jj_gen; + jj_consume_token(-1); + throw new ParseException(); + } + { + if ("" != null) { + return x; + } + } + throw new Error("Missing return statement in function"); + } - final public Object nullValue() throws ParseException { - jj_consume_token(NULL); -{if ("" != null) { - return null; -}} - throw new Error("Missing return statement in function"); -} + final public Object nullValue() throws ParseException { + jj_consume_token(NULL); + { + if ("" != null) { + return null; + } + } + throw new Error("Missing return statement in function"); + } - final public Boolean booleanValue() throws ParseException {Boolean b; - switch (jj_nt.kind) { - case TRUE:{ - jj_consume_token(TRUE); -b = Boolean.TRUE; - break; - } - case FALSE:{ - jj_consume_token(FALSE); -b = Boolean.FALSE; - break; - } - default: - jj_la1[8] = jj_gen; - jj_consume_token(-1); - throw new ParseException(); - } -{if ("" != null) { - return b; -}} - throw new Error("Missing return statement in function"); -} + final public Boolean booleanValue() throws ParseException { + Boolean b; + switch (jj_nt.kind) { + case TRUE: { + jj_consume_token(TRUE); + b = Boolean.TRUE; + break; + } + case FALSE: { + jj_consume_token(FALSE); + b = Boolean.FALSE; + break; + } + default: + jj_la1[8] = jj_gen; + jj_consume_token(-1); + throw new ParseException(); + } + { + if ("" != null) { + return b; + } + } + throw new Error("Missing return statement in function"); + } - final public Number number() throws ParseException {Token t; - switch (jj_nt.kind) { - case NUMBER_DECIMAL:{ - t = jj_consume_token(NUMBER_DECIMAL); -if (nativeNumbers) { - {if ("" != null) { - return Long.valueOf(t.image); - }} - } else { - {if ("" != null) { - return new java.math.BigDecimal(t.image); - }} - } - break; - } - case NUMBER_INTEGER:{ - t = jj_consume_token(NUMBER_INTEGER); -if (nativeNumbers) { - {if ("" != null) { - return Double.valueOf(t.image); - }} - } else { - {if ("" != null) { - return new java.math.BigInteger(substringBefore(t.image, '.')); - }} - } - break; - } - default: - jj_la1[9] = jj_gen; - jj_consume_token(-1); - throw new ParseException(); + final public Number number() throws ParseException { + Token t; + switch (jj_nt.kind) { + case NUMBER_DECIMAL: { + t = jj_consume_token(NUMBER_DECIMAL); + if (nativeNumbers) { + { + if ("" != null) { + return Long.valueOf(t.image); + } + } + } else { + { + if ("" != null) { + return new java.math.BigDecimal(t.image); + } + } + } + break; + } + case NUMBER_INTEGER: { + t = jj_consume_token(NUMBER_INTEGER); + if (nativeNumbers) { + { + if ("" != null) { + return Double.valueOf(t.image); + } + } + } else { + { + if ("" != null) { + return new java.math.BigInteger(substringBefore(t.image, '.')); + } + } + } + break; + } + default: + jj_la1[9] = jj_gen; + jj_consume_token(-1); + throw new ParseException(); + } + throw new Error("Missing return statement in function"); } - throw new Error("Missing return statement in function"); -} - final public String string() throws ParseException {String s; - switch (jj_nt.kind) { - case STRING_DOUBLE_EMPTY: - case STRING_DOUBLE_NONEMPTY:{ - s = doubleQuoteString(); - break; - } - case STRING_SINGLE_EMPTY: - case STRING_SINGLE_NONEMPTY:{ - s = singleQuoteString(); - break; - } - default: - jj_la1[10] = jj_gen; - jj_consume_token(-1); - throw new ParseException(); - } -{if ("" != null) { - return s; -}} - throw new Error("Missing return statement in function"); -} + final public String string() throws ParseException { + String s; + switch (jj_nt.kind) { + case STRING_DOUBLE_EMPTY: + case STRING_DOUBLE_NONEMPTY: { + s = doubleQuoteString(); + break; + } + case STRING_SINGLE_EMPTY: + case STRING_SINGLE_NONEMPTY: { + s = singleQuoteString(); + break; + } + default: + jj_la1[10] = jj_gen; + jj_consume_token(-1); + throw new ParseException(); + } + { + if ("" != null) { + return s; + } + } + throw new Error("Missing return statement in function"); + } - final public String doubleQuoteString() throws ParseException { - switch (jj_nt.kind) { - case STRING_DOUBLE_EMPTY:{ - jj_consume_token(STRING_DOUBLE_EMPTY); -{if ("" != null) { - return ""; -}} - break; - } - case STRING_DOUBLE_NONEMPTY:{ - jj_consume_token(STRING_DOUBLE_NONEMPTY); -String image = token.image; - {if ("" != null) { - return image.substring(1, image.length() - 1); - }} - break; - } - default: - jj_la1[11] = jj_gen; - jj_consume_token(-1); - throw new ParseException(); + final public String doubleQuoteString() throws ParseException { + switch (jj_nt.kind) { + case STRING_DOUBLE_EMPTY: { + jj_consume_token(STRING_DOUBLE_EMPTY); + { + if ("" != null) { + return ""; + } + } + break; + } + case STRING_DOUBLE_NONEMPTY: { + jj_consume_token(STRING_DOUBLE_NONEMPTY); + String image = token.image; + { + if ("" != null) { + return image.substring(1, image.length() - 1); + } + } + break; + } + default: + jj_la1[11] = jj_gen; + jj_consume_token(-1); + throw new ParseException(); + } + throw new Error("Missing return statement in function"); } - throw new Error("Missing return statement in function"); -} - final public String singleQuoteString() throws ParseException { - switch (jj_nt.kind) { - case STRING_SINGLE_EMPTY:{ - jj_consume_token(STRING_SINGLE_EMPTY); -{if ("" != null) { - return ""; -}} - break; - } - case STRING_SINGLE_NONEMPTY:{ - jj_consume_token(STRING_SINGLE_NONEMPTY); -String image = token.image; - {if ("" != null) { - return image.substring(1, image.length() - 1); - }} - break; - } - default: - jj_la1[12] = jj_gen; - jj_consume_token(-1); - throw new ParseException(); + final public String singleQuoteString() throws ParseException { + switch (jj_nt.kind) { + case STRING_SINGLE_EMPTY: { + jj_consume_token(STRING_SINGLE_EMPTY); + { + if ("" != null) { + return ""; + } + } + break; + } + case STRING_SINGLE_NONEMPTY: { + jj_consume_token(STRING_SINGLE_NONEMPTY); + String image = token.image; + { + if ("" != null) { + return image.substring(1, image.length() - 1); + } + } + break; + } + default: + jj_la1[12] = jj_gen; + jj_consume_token(-1); + throw new ParseException(); + } + throw new Error("Missing return statement in function"); } - throw new Error("Missing return statement in function"); -} - final public String symbol() throws ParseException { - jj_consume_token(SYMBOL); -{if ("" != null) { - return token.image; -}} - throw new Error("Missing return statement in function"); -} + final public String symbol() throws ParseException { + jj_consume_token(SYMBOL); + { + if ("" != null) { + return token.image; + } + } + throw new Error("Missing return statement in function"); + } - /** Generated Token Manager. */ - public JSONParserTokenManager token_source; - JavaCharStream jj_input_stream; - /** Current token. */ - public Token token; - /** Next token. */ - public Token jj_nt; - private int jj_gen; - final private int[] jj_la1 = new int[13]; - static private int[] jj_la1_0; - static { - jj_la1_init_0(); - } - private static void jj_la1_init_0() { - jj_la1_0 = new int[] {0xccf8480,0x78000,0x1ccf8000,0x40,0x1ccf8000,0x40,0xccf8480,0xccf8000,0x60000,0x18000,0xcc00000,0x8800000,0x4400000,}; - } - - /** Constructor with InputStream. */ - public JSONParser(java.io.InputStream stream) { - this(stream, null); - } - /** Constructor with InputStream and supplied encoding */ - public JSONParser(java.io.InputStream stream, String encoding) { - try { jj_input_stream = new JavaCharStream(stream, encoding, 1, 1); } catch(java.io.UnsupportedEncodingException e) { throw new RuntimeException(e); } - token_source = new JSONParserTokenManager(jj_input_stream); - token = new Token(); - token.next = jj_nt = token_source.getNextToken(); - jj_gen = 0; - for (int i = 0; i < 13; i++) { - jj_la1[i] = -1; - } - } - - /** Reinitialise. */ - public void ReInit(java.io.InputStream stream) { - ReInit(stream, null); - } - /** Reinitialise. */ - public void ReInit(java.io.InputStream stream, String encoding) { - try { jj_input_stream.ReInit(stream, encoding, 1, 1); } catch(java.io.UnsupportedEncodingException e) { throw new RuntimeException(e); } - token_source.ReInit(jj_input_stream); - token = new Token(); - token.next = jj_nt = token_source.getNextToken(); - jj_gen = 0; - for (int i = 0; i < 13; i++) { - jj_la1[i] = -1; - } - } - - /** Constructor. */ - public JSONParser(java.io.Reader stream) { - jj_input_stream = new JavaCharStream(stream, 1, 1); - token_source = new JSONParserTokenManager(jj_input_stream); - token = new Token(); - token.next = jj_nt = token_source.getNextToken(); - jj_gen = 0; - for (int i = 0; i < 13; i++) { - jj_la1[i] = -1; - } - } - - /** Reinitialise. */ - public void ReInit(java.io.Reader stream) { - if (jj_input_stream == null) { - jj_input_stream = new JavaCharStream(stream, 1, 1); - } else { - jj_input_stream.ReInit(stream, 1, 1); - } - if (token_source == null) { - token_source = new JSONParserTokenManager(jj_input_stream); - } - - token_source.ReInit(jj_input_stream); - token = new Token(); - token.next = jj_nt = token_source.getNextToken(); - jj_gen = 0; - for (int i = 0; i < 13; i++) { - jj_la1[i] = -1; - } - } - - /** Constructor with generated Token Manager. */ - public JSONParser(JSONParserTokenManager tm) { - token_source = tm; - token = new Token(); - token.next = jj_nt = token_source.getNextToken(); - jj_gen = 0; - for (int i = 0; i < 13; i++) { - jj_la1[i] = -1; - } - } - - /** Reinitialise. */ - public void ReInit(JSONParserTokenManager tm) { - token_source = tm; - token = new Token(); - token.next = jj_nt = token_source.getNextToken(); - jj_gen = 0; - for (int i = 0; i < 13; i++) { - jj_la1[i] = -1; - } - } - - private Token jj_consume_token(int kind) throws ParseException { - Token oldToken = token; - if ((token = jj_nt).next != null) { - jj_nt = jj_nt.next; - } else { - jj_nt = jj_nt.next = token_source.getNextToken(); - } - if (token.kind == kind) { - jj_gen++; - return token; - } - jj_nt = token; - token = oldToken; - jj_kind = kind; - throw generateParseException(); - } - - -/** Get the next Token. */ - final public Token getNextToken() { - if ((token = jj_nt).next != null) { - jj_nt = jj_nt.next; - } else { - jj_nt = jj_nt.next = token_source.getNextToken(); - } - jj_gen++; - return token; - } - -/** Get the specific Token. */ - final public Token getToken(int index) { - Token t = token; - for (int i = 0; i < index; i++) { - if (t.next != null) { - t = t.next; - } else { - t = t.next = token_source.getNextToken(); - } - } - return t; - } - - private java.util.List jj_expentries = new java.util.ArrayList(); - private int[] jj_expentry; - private int jj_kind = -1; - - /** Generate ParseException. */ - public ParseException generateParseException() { - jj_expentries.clear(); - boolean[] la1tokens = new boolean[29]; - if (jj_kind >= 0) { - la1tokens[jj_kind] = true; - jj_kind = -1; - } - for (int i = 0; i < 13; i++) { - if (jj_la1[i] == jj_gen) { - for (int j = 0; j < 32; j++) { - if ((jj_la1_0[i] & (1< jj_expentries = new java.util.ArrayList(); + private int[] jj_expentry; + private int jj_kind = -1; + + /** Generate ParseException. */ + public ParseException generateParseException() { + jj_expentries.clear(); + boolean[] la1tokens = new boolean[29]; + if (jj_kind >= 0) { + la1tokens[jj_kind] = true; + jj_kind = -1; + } + for (int i = 0; i < 13; i++) { + if (jj_la1[i] == jj_gen) { + for (int j = 0; j < 32; j++) { + if ((jj_la1_0[i] & (1 << j)) != 0) { + la1tokens[j] = true; + } + } + } + } + for (int i = 0; i < 29; i++) { + if (la1tokens[i]) { + jj_expentry = new int[1]; + jj_expentry[0] = i; + jj_expentries.add(jj_expentry); + } + } + int[][] exptokseq = new int[jj_expentries.size()][]; + for (int i = 0; i < jj_expentries.size(); i++) { + exptokseq[i] = jj_expentries.get(i); + } + return new ParseException(token, exptokseq, tokenImage); + } + + private int trace_indent = 0; + private boolean trace_enabled; + + /** Trace enabled. */ + final public boolean trace_enabled() { + return trace_enabled; + } + + /** Enable tracing. */ + final public void enable_tracing() { + } + + /** Disable tracing. */ + final public void disable_tracing() { + } } diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/json/JSONParserConstants.java tomcat10-10.1.52/java/org/apache/tomcat/util/json/JSONParserConstants.java --- tomcat10-10.1.40/java/org/apache/tomcat/util/json/JSONParserConstants.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/json/JSONParserConstants.java 2026-01-23 19:33:36.000000000 +0000 @@ -19,104 +19,77 @@ /** - * Token literal values and constants. - * Generated by org.javacc.parser.OtherFilesGen#start() + * Token literal values and constants. Generated by org.javacc.parser.OtherFilesGen#start() */ public interface JSONParserConstants { - /** End of File. */ - int EOF = 0; - /** RegularExpression Id. */ - int C_SINGLE_COMMENT = 1; - /** RegularExpression Id. */ - int C_MULTILINE_COMMENT = 2; - /** RegularExpression Id. */ - int SH_SINGLE_COMMENT = 3; - /** RegularExpression Id. */ - int WHITESPACE = 4; - /** RegularExpression Id. */ - int EOL = 5; - /** RegularExpression Id. */ - int COMMA = 6; - /** RegularExpression Id. */ - int BRACE_OPEN = 7; - /** RegularExpression Id. */ - int BRACE_CLOSE = 8; - /** RegularExpression Id. */ - int COLON = 9; - /** RegularExpression Id. */ - int BRACKET_OPEN = 10; - /** RegularExpression Id. */ - int BRACKET_CLOSE = 11; - /** RegularExpression Id. */ - int ZERO = 12; - /** RegularExpression Id. */ - int DIGIT_NONZERO = 13; - /** RegularExpression Id. */ - int DIGIT = 14; - /** RegularExpression Id. */ - int NUMBER_INTEGER = 15; - /** RegularExpression Id. */ - int NUMBER_DECIMAL = 16; - /** RegularExpression Id. */ - int TRUE = 17; - /** RegularExpression Id. */ - int FALSE = 18; - /** RegularExpression Id. */ - int NULL = 19; - /** RegularExpression Id. */ - int QUOTE_DOUBLE = 20; - /** RegularExpression Id. */ - int QUOTE_SINGLE = 21; - /** RegularExpression Id. */ - int STRING_SINGLE_EMPTY = 22; - /** RegularExpression Id. */ - int STRING_DOUBLE_EMPTY = 23; - /** RegularExpression Id. */ - int STRING_SINGLE_BODY = 24; - /** RegularExpression Id. */ - int STRING_DOUBLE_BODY = 25; - /** RegularExpression Id. */ - int STRING_SINGLE_NONEMPTY = 26; - /** RegularExpression Id. */ - int STRING_DOUBLE_NONEMPTY = 27; - /** RegularExpression Id. */ - int SYMBOL = 28; - - /** Lexical state. */ - int DEFAULT = 0; - - /** Literal token values. */ - String[] tokenImage = { - "", - "", - "", - "", - "", - "", - "\",\"", - "\"{\"", - "\"}\"", - "\":\"", - "\"[\"", - "\"]\"", - "\"0\"", - "", - "", - "", - "", - "\"true\"", - "\"false\"", - "\"null\"", - "\"\\\"\"", - "\"\\\'\"", - "\"\\\'\\\'\"", - "\"\\\"\\\"\"", - "", - "", - "", - "", - "", - }; + /** End of File. */ + int EOF = 0; + /** RegularExpression Id. */ + int C_SINGLE_COMMENT = 1; + /** RegularExpression Id. */ + int C_MULTILINE_COMMENT = 2; + /** RegularExpression Id. */ + int SH_SINGLE_COMMENT = 3; + /** RegularExpression Id. */ + int WHITESPACE = 4; + /** RegularExpression Id. */ + int EOL = 5; + /** RegularExpression Id. */ + int COMMA = 6; + /** RegularExpression Id. */ + int BRACE_OPEN = 7; + /** RegularExpression Id. */ + int BRACE_CLOSE = 8; + /** RegularExpression Id. */ + int COLON = 9; + /** RegularExpression Id. */ + int BRACKET_OPEN = 10; + /** RegularExpression Id. */ + int BRACKET_CLOSE = 11; + /** RegularExpression Id. */ + int ZERO = 12; + /** RegularExpression Id. */ + int DIGIT_NONZERO = 13; + /** RegularExpression Id. */ + int DIGIT = 14; + /** RegularExpression Id. */ + int NUMBER_INTEGER = 15; + /** RegularExpression Id. */ + int NUMBER_DECIMAL = 16; + /** RegularExpression Id. */ + int TRUE = 17; + /** RegularExpression Id. */ + int FALSE = 18; + /** RegularExpression Id. */ + int NULL = 19; + /** RegularExpression Id. */ + int QUOTE_DOUBLE = 20; + /** RegularExpression Id. */ + int QUOTE_SINGLE = 21; + /** RegularExpression Id. */ + int STRING_SINGLE_EMPTY = 22; + /** RegularExpression Id. */ + int STRING_DOUBLE_EMPTY = 23; + /** RegularExpression Id. */ + int STRING_SINGLE_BODY = 24; + /** RegularExpression Id. */ + int STRING_DOUBLE_BODY = 25; + /** RegularExpression Id. */ + int STRING_SINGLE_NONEMPTY = 26; + /** RegularExpression Id. */ + int STRING_DOUBLE_NONEMPTY = 27; + /** RegularExpression Id. */ + int SYMBOL = 28; + + /** Lexical state. */ + int DEFAULT = 0; + + /** Literal token values. */ + String[] tokenImage = { "", "", "", "", + "", "", "\",\"", "\"{\"", "\"}\"", "\":\"", "\"[\"", "\"]\"", "\"0\"", "", + "", "", "", "\"true\"", "\"false\"", "\"null\"", "\"\\\"\"", + "\"\\\'\"", "\"\\\'\\\'\"", "\"\\\"\\\"\"", "", "", + "", "", "", }; } diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/json/JSONParserTokenManager.java tomcat10-10.1.52/java/org/apache/tomcat/util/json/JSONParserTokenManager.java --- tomcat10-10.1.40/java/org/apache/tomcat/util/json/JSONParserTokenManager.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/json/JSONParserTokenManager.java 2026-01-23 19:33:36.000000000 +0000 @@ -22,842 +22,850 @@ @SuppressWarnings("all") // Ignore warnings in generated code public class JSONParserTokenManager implements JSONParserConstants { - /** Debug output. */ - public java.io.PrintStream debugStream = System.out; - /** Set debug output. */ - public void setDebugStream(java.io.PrintStream ds) { debugStream = ds; } -private final int jjStopStringLiteralDfa_0(int pos, long active0){ - switch (pos) - { - case 0: - if ((active0 & 0xe0000L) != 0L) - { - jjmatchedKind = 28; - return 15; - } - if ((active0 & 0x400000L) != 0L) { - return 38; - } - if ((active0 & 0x800000L) != 0L) { - return 39; - } - return -1; - case 1: - if ((active0 & 0xe0000L) != 0L) - { - jjmatchedKind = 28; - jjmatchedPos = 1; - return 15; - } - return -1; - case 2: - if ((active0 & 0xe0000L) != 0L) - { - jjmatchedKind = 28; - jjmatchedPos = 2; - return 15; - } - return -1; - case 3: - if ((active0 & 0xa0000L) != 0L) { - return 15; - } - if ((active0 & 0x40000L) != 0L) - { - jjmatchedKind = 28; - jjmatchedPos = 3; - return 15; - } - return -1; - default : - return -1; - } -} -private final int jjStartNfa_0(int pos, long active0){ - return jjMoveNfa_0(jjStopStringLiteralDfa_0(pos, active0), pos + 1); -} -private int jjStopAtPos(int pos, int kind) -{ - jjmatchedKind = kind; - jjmatchedPos = pos; - return pos + 1; -} -private int jjMoveStringLiteralDfa0_0(){ - switch(curChar) - { - case 34: - return jjMoveStringLiteralDfa1_0(0x800000L); - case 39: - return jjMoveStringLiteralDfa1_0(0x400000L); - case 44: - return jjStopAtPos(0, 6); - case 58: - return jjStopAtPos(0, 9); - case 91: - return jjStopAtPos(0, 10); - case 93: - return jjStopAtPos(0, 11); - case 70: - case 102: - return jjMoveStringLiteralDfa1_0(0x40000L); - case 78: - case 110: - return jjMoveStringLiteralDfa1_0(0x80000L); - case 84: - case 116: - return jjMoveStringLiteralDfa1_0(0x20000L); - case 123: - return jjStopAtPos(0, 7); - case 125: - return jjStopAtPos(0, 8); - default : - return jjMoveNfa_0(0, 0); - } -} -private int jjMoveStringLiteralDfa1_0(long active0){ - try { curChar = input_stream.readChar(); } - catch(java.io.IOException e) { - jjStopStringLiteralDfa_0(0, active0); - return 1; - } - switch(curChar) - { - case 34: - if ((active0 & 0x800000L) != 0L) { - return jjStopAtPos(1, 23); - } - break; - case 39: - if ((active0 & 0x400000L) != 0L) { - return jjStopAtPos(1, 22); - } - break; - case 65: - case 97: - return jjMoveStringLiteralDfa2_0(active0, 0x40000L); - case 82: - case 114: - return jjMoveStringLiteralDfa2_0(active0, 0x20000L); - case 85: - case 117: - return jjMoveStringLiteralDfa2_0(active0, 0x80000L); - default : - break; - } - return jjStartNfa_0(0, active0); -} -private int jjMoveStringLiteralDfa2_0(long old0, long active0){ - if (((active0 &= old0)) == 0L) { - return jjStartNfa_0(0, old0); - } - try { curChar = input_stream.readChar(); } - catch(java.io.IOException e) { - jjStopStringLiteralDfa_0(1, active0); - return 2; - } - switch(curChar) - { - case 76: - case 108: - return jjMoveStringLiteralDfa3_0(active0, 0xc0000L); - case 85: - case 117: - return jjMoveStringLiteralDfa3_0(active0, 0x20000L); - default : - break; - } - return jjStartNfa_0(1, active0); -} -private int jjMoveStringLiteralDfa3_0(long old0, long active0){ - if (((active0 &= old0)) == 0L) { - return jjStartNfa_0(1, old0); - } - try { curChar = input_stream.readChar(); } - catch(java.io.IOException e) { - jjStopStringLiteralDfa_0(2, active0); - return 3; - } - switch(curChar) - { - case 69: - case 101: - if ((active0 & 0x20000L) != 0L) { - return jjStartNfaWithStates_0(3, 17, 15); - } - break; - case 76: - case 108: - if ((active0 & 0x80000L) != 0L) { - return jjStartNfaWithStates_0(3, 19, 15); - } - break; - case 83: - case 115: - return jjMoveStringLiteralDfa4_0(active0, 0x40000L); - default : - break; - } - return jjStartNfa_0(2, active0); -} -private int jjMoveStringLiteralDfa4_0(long old0, long active0){ - if (((active0 &= old0)) == 0L) { - return jjStartNfa_0(2, old0); - } - try { curChar = input_stream.readChar(); } - catch(java.io.IOException e) { - jjStopStringLiteralDfa_0(3, active0); - return 4; - } - switch(curChar) - { - case 69: - case 101: - if ((active0 & 0x40000L) != 0L) { - return jjStartNfaWithStates_0(4, 18, 15); - } - break; - default : - break; - } - return jjStartNfa_0(3, active0); -} -private int jjStartNfaWithStates_0(int pos, int kind, int state) -{ - jjmatchedKind = kind; - jjmatchedPos = pos; - try { curChar = input_stream.readChar(); } - catch(java.io.IOException e) { return pos + 1; } - return jjMoveNfa_0(state, pos + 1); -} -static final long[] jjbitVec0 = { - 0xfffffffffffffffeL, 0xffffffffffffffffL, 0xffffffffffffffffL, 0xffffffffffffffffL -}; -static final long[] jjbitVec2 = { - 0x0L, 0x0L, 0xffffffffffffffffL, 0xffffffffffffffffL -}; -private int jjMoveNfa_0(int startState, int curPos) -{ - int startsAt = 0; - jjnewStateCnt = 38; - int i = 1; - jjstateSet[0] = startState; - int kind = 0x7fffffff; - for (;;) - { - if (++jjround == 0x7fffffff) { - ReInitRounds(); - } - if (curChar < 64) - { - long l = 1L << curChar; - do - { - switch(jjstateSet[--i]) - { - case 0: - if ((0x3ff000000000000L & l) != 0L) - { - if (kind > 28) { - kind = 28; - } - { jjCheckNAdd(15); } - } - else if ((0x3400L & l) != 0L) - { - if (kind > 5) { - kind = 5; - } - } - else if ((0x100000200L & l) != 0L) - { - if (kind > 4) { - kind = 4; + /** Debug output. */ + public java.io.PrintStream debugStream = System.out; + + /** Set debug output. */ + public void setDebugStream(java.io.PrintStream ds) { + debugStream = ds; + } + + private final int jjStopStringLiteralDfa_0(int pos, long active0) { + switch (pos) { + case 0: + if ((active0 & 0xe0000L) != 0L) { + jjmatchedKind = 28; + return 15; + } + if ((active0 & 0x400000L) != 0L) { + return 38; + } + if ((active0 & 0x800000L) != 0L) { + return 39; + } + return -1; + case 1: + if ((active0 & 0xe0000L) != 0L) { + jjmatchedKind = 28; + jjmatchedPos = 1; + return 15; + } + return -1; + case 2: + if ((active0 & 0xe0000L) != 0L) { + jjmatchedKind = 28; + jjmatchedPos = 2; + return 15; + } + return -1; + case 3: + if ((active0 & 0xa0000L) != 0L) { + return 15; + } + if ((active0 & 0x40000L) != 0L) { + jjmatchedKind = 28; + jjmatchedPos = 3; + return 15; + } + return -1; + default: + return -1; + } + } + + private final int jjStartNfa_0(int pos, long active0) { + return jjMoveNfa_0(jjStopStringLiteralDfa_0(pos, active0), pos + 1); + } + + private int jjStopAtPos(int pos, int kind) { + jjmatchedKind = kind; + jjmatchedPos = pos; + return pos + 1; + } + + private int jjMoveStringLiteralDfa0_0() { + switch (curChar) { + case 34: + return jjMoveStringLiteralDfa1_0(0x800000L); + case 39: + return jjMoveStringLiteralDfa1_0(0x400000L); + case 44: + return jjStopAtPos(0, 6); + case 58: + return jjStopAtPos(0, 9); + case 91: + return jjStopAtPos(0, 10); + case 93: + return jjStopAtPos(0, 11); + case 70: + case 102: + return jjMoveStringLiteralDfa1_0(0x40000L); + case 78: + case 110: + return jjMoveStringLiteralDfa1_0(0x80000L); + case 84: + case 116: + return jjMoveStringLiteralDfa1_0(0x20000L); + case 123: + return jjStopAtPos(0, 7); + case 125: + return jjStopAtPos(0, 8); + default: + return jjMoveNfa_0(0, 0); + } + } + + private int jjMoveStringLiteralDfa1_0(long active0) { + try { + curChar = input_stream.readChar(); + } catch (java.io.IOException e) { + jjStopStringLiteralDfa_0(0, active0); + return 1; + } + switch (curChar) { + case 34: + if ((active0 & 0x800000L) != 0L) { + return jjStopAtPos(1, 23); + } + break; + case 39: + if ((active0 & 0x400000L) != 0L) { + return jjStopAtPos(1, 22); + } + break; + case 65: + case 97: + return jjMoveStringLiteralDfa2_0(active0, 0x40000L); + case 82: + case 114: + return jjMoveStringLiteralDfa2_0(active0, 0x20000L); + case 85: + case 117: + return jjMoveStringLiteralDfa2_0(active0, 0x80000L); + default: + break; + } + return jjStartNfa_0(0, active0); + } + + private int jjMoveStringLiteralDfa2_0(long old0, long active0) { + if (((active0 &= old0)) == 0L) { + return jjStartNfa_0(0, old0); + } + try { + curChar = input_stream.readChar(); + } catch (java.io.IOException e) { + jjStopStringLiteralDfa_0(1, active0); + return 2; + } + switch (curChar) { + case 76: + case 108: + return jjMoveStringLiteralDfa3_0(active0, 0xc0000L); + case 85: + case 117: + return jjMoveStringLiteralDfa3_0(active0, 0x20000L); + default: + break; + } + return jjStartNfa_0(1, active0); + } + + private int jjMoveStringLiteralDfa3_0(long old0, long active0) { + if (((active0 &= old0)) == 0L) { + return jjStartNfa_0(1, old0); + } + try { + curChar = input_stream.readChar(); + } catch (java.io.IOException e) { + jjStopStringLiteralDfa_0(2, active0); + return 3; + } + switch (curChar) { + case 69: + case 101: + if ((active0 & 0x20000L) != 0L) { + return jjStartNfaWithStates_0(3, 17, 15); + } + break; + case 76: + case 108: + if ((active0 & 0x80000L) != 0L) { + return jjStartNfaWithStates_0(3, 19, 15); + } + break; + case 83: + case 115: + return jjMoveStringLiteralDfa4_0(active0, 0x40000L); + default: + break; + } + return jjStartNfa_0(2, active0); + } + + private int jjMoveStringLiteralDfa4_0(long old0, long active0) { + if (((active0 &= old0)) == 0L) { + return jjStartNfa_0(2, old0); + } + try { + curChar = input_stream.readChar(); + } catch (java.io.IOException e) { + jjStopStringLiteralDfa_0(3, active0); + return 4; + } + switch (curChar) { + case 69: + case 101: + if ((active0 & 0x40000L) != 0L) { + return jjStartNfaWithStates_0(4, 18, 15); + } + break; + default: + break; + } + return jjStartNfa_0(3, active0); + } + + private int jjStartNfaWithStates_0(int pos, int kind, int state) { + jjmatchedKind = kind; + jjmatchedPos = pos; + try { + curChar = input_stream.readChar(); + } catch (java.io.IOException e) { + return pos + 1; + } + return jjMoveNfa_0(state, pos + 1); + } + + static final long[] jjbitVec0 = + { 0xfffffffffffffffeL, 0xffffffffffffffffL, 0xffffffffffffffffL, 0xffffffffffffffffL }; + static final long[] jjbitVec2 = { 0x0L, 0x0L, 0xffffffffffffffffL, 0xffffffffffffffffL }; + + private int jjMoveNfa_0(int startState, int curPos) { + int startsAt = 0; + jjnewStateCnt = 38; + int i = 1; + jjstateSet[0] = startState; + int kind = 0x7fffffff; + for (;;) { + if (++jjround == 0x7fffffff) { + ReInitRounds(); + } + if (curChar < 64) { + long l = 1L << curChar; + do { + switch (jjstateSet[--i]) { + case 0: + if ((0x3ff000000000000L & l) != 0L) { + if (kind > 28) { + kind = 28; + } + { + jjCheckNAdd(15); + } + } else if ((0x3400L & l) != 0L) { + if (kind > 5) { + kind = 5; + } + } else if ((0x100000200L & l) != 0L) { + if (kind > 4) { + kind = 4; + } + } else if (curChar == 45) { + jjCheckNAddStates(0, 3); + } else if (curChar == 47) { + jjAddStates(4, 5); + } else if (curChar == 34) { + jjCheckNAddTwoStates(11, 12); + } else if (curChar == 39) { + jjCheckNAddTwoStates(6, 7); + } else if (curChar == 35) { + jjCheckNAddTwoStates(1, 2); + } + if ((0x3fe000000000000L & l) != 0L) { + if (kind > 15) { + kind = 15; + } + { + jjCheckNAddStates(6, 8); + } + } else if (curChar == 48) { + if (kind > 15) { + kind = 15; + } + { + jjCheckNAddStates(9, 11); + } + } + break; + case 38: + case 6: + if ((0xffffff7fffffc9ffL & l) != 0L) { + jjCheckNAddStates(12, 14); + } + break; + case 39: + case 11: + if ((0xfffffffbffffc9ffL & l) != 0L) { + jjCheckNAddStates(15, 17); + } + break; + case 1: + if ((0xffffffffffffcbffL & l) != 0L) { + jjCheckNAddTwoStates(1, 2); + } + break; + case 2: + if ((0x3400L & l) != 0L && kind > 3) { + kind = 3; + } + break; + case 3: + if ((0x100000200L & l) != 0L && kind > 4) { + kind = 4; + } + break; + case 4: + if ((0x3400L & l) != 0L && kind > 5) { + kind = 5; + } + break; + case 5: + if (curChar == 39) { + jjCheckNAddTwoStates(6, 7); + } + break; + case 8: + if ((0x808000000000L & l) != 0L) { + jjCheckNAddStates(12, 14); + } + break; + case 9: + if (curChar == 39 && kind > 26) { + kind = 26; + } + break; + case 10: + if (curChar == 34) { + jjCheckNAddTwoStates(11, 12); + } + break; + case 13: + if ((0x800400000000L & l) != 0L) { + jjCheckNAddStates(15, 17); + } + break; + case 14: + if (curChar == 34 && kind > 27) { + kind = 27; + } + break; + case 15: + if ((0x3ff000000000000L & l) == 0L) { + break; + } + if (kind > 28) { + kind = 28; + } { + jjCheckNAdd(15); + } + break; + case 16: + if (curChar == 47) { + jjAddStates(4, 5); + } + break; + case 17: + if (curChar == 47) { + jjCheckNAddTwoStates(18, 19); + } + break; + case 18: + if ((0xffffffffffffcbffL & l) != 0L) { + jjCheckNAddTwoStates(18, 19); + } + break; + case 19: + if ((0x3400L & l) != 0L && kind > 1) { + kind = 1; + } + break; + case 20: + if (curChar == 42) { + jjCheckNAddTwoStates(21, 23); + } + break; + case 21: { + jjCheckNAddTwoStates(21, 23); + } + break; + case 22: + if (curChar == 47 && kind > 2) { + kind = 2; + } + break; + case 23: + if (curChar == 42) { + jjstateSet[jjnewStateCnt++] = 22; + } + break; + case 24: + if (curChar == 45) { + jjCheckNAddStates(0, 3); + } + break; + case 25: + if (curChar != 48) { + break; + } + if (kind > 15) { + kind = 15; + } { + jjCheckNAdd(25); + } + break; + case 26: + if ((0x3fe000000000000L & l) == 0L) { + break; + } + if (kind > 15) { + kind = 15; + } { + jjCheckNAdd(27); + } + break; + case 27: + if ((0x3ff000000000000L & l) == 0L) { + break; + } + if (kind > 15) { + kind = 15; + } { + jjCheckNAdd(27); + } + break; + case 28: + if (curChar == 48) { + jjCheckNAddTwoStates(28, 29); + } + break; + case 29: + if (curChar == 46) { + jjCheckNAdd(30); + } + break; + case 30: + if ((0x3ff000000000000L & l) == 0L) { + break; + } + if (kind > 16) { + kind = 16; + } { + jjCheckNAddTwoStates(30, 31); + } + break; + case 32: + if ((0x280000000000L & l) != 0L) { + jjCheckNAdd(33); + } + break; + case 33: + if ((0x3ff000000000000L & l) == 0L) { + break; + } + if (kind > 16) { + kind = 16; + } { + jjCheckNAdd(33); + } + break; + case 34: + if ((0x3fe000000000000L & l) != 0L) { + jjCheckNAddTwoStates(35, 29); + } + break; + case 35: + if ((0x3ff000000000000L & l) != 0L) { + jjCheckNAddTwoStates(35, 29); + } + break; + case 36: + if (curChar != 48) { + break; + } + if (kind > 15) { + kind = 15; + } { + jjCheckNAddStates(9, 11); + } + break; + case 37: + if ((0x3fe000000000000L & l) == 0L) { + break; + } + if (kind > 15) { + kind = 15; + } { + jjCheckNAddStates(6, 8); + } + break; + default: + break; } - } - else if (curChar == 45) - { jjCheckNAddStates(0, 3); } - else if (curChar == 47) - { jjAddStates(4, 5); } - else if (curChar == 34) - { jjCheckNAddTwoStates(11, 12); } - else if (curChar == 39) - { jjCheckNAddTwoStates(6, 7); } - else if (curChar == 35) - { jjCheckNAddTwoStates(1, 2); } - if ((0x3fe000000000000L & l) != 0L) - { - if (kind > 15) { - kind = 15; + } while (i != startsAt); + } else if (curChar < 128) { + long l = 1L << (curChar & 077); + do { + switch (jjstateSet[--i]) { + case 0: + case 15: + if ((0x7fffffe07fffffeL & l) == 0L) { + break; + } + if (kind > 28) { + kind = 28; + } { + jjCheckNAdd(15); + } + break; + case 38: + if ((0xffffffffefffffffL & l) != 0L) { + jjCheckNAddStates(12, 14); + } else if (curChar == 92) { + jjstateSet[jjnewStateCnt++] = 8; + } + break; + case 39: + if ((0xffffffffefffffffL & l) != 0L) { + jjCheckNAddStates(15, 17); + } else if (curChar == 92) { + jjstateSet[jjnewStateCnt++] = 13; + } + break; + case 1: { + jjAddStates(18, 19); + } + break; + case 6: + if ((0xffffffffefffffffL & l) != 0L) { + jjCheckNAddStates(12, 14); + } + break; + case 7: + if (curChar == 92) { + jjstateSet[jjnewStateCnt++] = 8; + } + break; + case 8: + if ((0x14404410144044L & l) != 0L) { + jjCheckNAddStates(12, 14); + } + break; + case 11: + if ((0xffffffffefffffffL & l) != 0L) { + jjCheckNAddStates(15, 17); + } + break; + case 12: + if (curChar == 92) { + jjstateSet[jjnewStateCnt++] = 13; + } + break; + case 13: + if ((0x14404410144044L & l) != 0L) { + jjCheckNAddStates(15, 17); + } + break; + case 18: { + jjAddStates(20, 21); + } + break; + case 21: { + jjAddStates(22, 23); + } + break; + case 31: + if ((0x2000000020L & l) != 0L) { + jjAddStates(24, 25); + } + break; + default: + break; } - { jjCheckNAddStates(6, 8); } - } - else if (curChar == 48) - { - if (kind > 15) { - kind = 15; + } while (i != startsAt); + } else { + int hiByte = (curChar >> 8); + int i1 = hiByte >> 6; + long l1 = 1L << (hiByte & 077); + int i2 = (curChar & 0xff) >> 6; + long l2 = 1L << (curChar & 077); + do { + switch (jjstateSet[--i]) { + case 38: + case 6: + if (jjCanMove_0(hiByte, i1, i2, l1, l2)) { + jjCheckNAddStates(12, 14); + } + break; + case 39: + case 11: + if (jjCanMove_0(hiByte, i1, i2, l1, l2)) { + jjCheckNAddStates(15, 17); + } + break; + case 1: + if (jjCanMove_0(hiByte, i1, i2, l1, l2)) { + jjAddStates(18, 19); + } + break; + case 18: + if (jjCanMove_0(hiByte, i1, i2, l1, l2)) { + jjAddStates(20, 21); + } + break; + case 21: + if (jjCanMove_0(hiByte, i1, i2, l1, l2)) { + jjAddStates(22, 23); + } + break; + default: + if (i1 == 0 || l1 == 0 || i2 == 0 || l2 == 0) { + break; + } else { + break; + } } - { jjCheckNAddStates(9, 11); } - } - break; - case 38: - case 6: - if ((0xffffff7fffffc9ffL & l) != 0L) - { jjCheckNAddStates(12, 14); } - break; - case 39: - case 11: - if ((0xfffffffbffffc9ffL & l) != 0L) - { jjCheckNAddStates(15, 17); } - break; - case 1: - if ((0xffffffffffffcbffL & l) != 0L) - { jjCheckNAddTwoStates(1, 2); } - break; - case 2: - if ((0x3400L & l) != 0L && kind > 3) { - kind = 3; - } - break; - case 3: - if ((0x100000200L & l) != 0L && kind > 4) { - kind = 4; - } - break; - case 4: - if ((0x3400L & l) != 0L && kind > 5) { - kind = 5; - } - break; - case 5: - if (curChar == 39) - { jjCheckNAddTwoStates(6, 7); } - break; - case 8: - if ((0x808000000000L & l) != 0L) - { jjCheckNAddStates(12, 14); } - break; - case 9: - if (curChar == 39 && kind > 26) { - kind = 26; - } - break; - case 10: - if (curChar == 34) - { jjCheckNAddTwoStates(11, 12); } - break; - case 13: - if ((0x800400000000L & l) != 0L) - { jjCheckNAddStates(15, 17); } - break; - case 14: - if (curChar == 34 && kind > 27) { - kind = 27; - } - break; - case 15: - if ((0x3ff000000000000L & l) == 0L) { - break; - } - if (kind > 28) { - kind = 28; - } - { jjCheckNAdd(15); } - break; - case 16: - if (curChar == 47) - { jjAddStates(4, 5); } - break; - case 17: - if (curChar == 47) - { jjCheckNAddTwoStates(18, 19); } - break; - case 18: - if ((0xffffffffffffcbffL & l) != 0L) - { jjCheckNAddTwoStates(18, 19); } - break; - case 19: - if ((0x3400L & l) != 0L && kind > 1) { - kind = 1; - } - break; - case 20: - if (curChar == 42) - { jjCheckNAddTwoStates(21, 23); } - break; - case 21: - { jjCheckNAddTwoStates(21, 23); } - break; - case 22: - if (curChar == 47 && kind > 2) { - kind = 2; - } - break; - case 23: - if (curChar == 42) { - jjstateSet[jjnewStateCnt++] = 22; - } - break; - case 24: - if (curChar == 45) - { jjCheckNAddStates(0, 3); } - break; - case 25: - if (curChar != 48) { - break; - } - if (kind > 15) { - kind = 15; - } - { jjCheckNAdd(25); } - break; - case 26: - if ((0x3fe000000000000L & l) == 0L) { - break; - } - if (kind > 15) { - kind = 15; - } - { jjCheckNAdd(27); } - break; - case 27: - if ((0x3ff000000000000L & l) == 0L) { - break; - } - if (kind > 15) { - kind = 15; - } - { jjCheckNAdd(27); } - break; - case 28: - if (curChar == 48) - { jjCheckNAddTwoStates(28, 29); } - break; - case 29: - if (curChar == 46) - { jjCheckNAdd(30); } - break; - case 30: - if ((0x3ff000000000000L & l) == 0L) { - break; - } - if (kind > 16) { - kind = 16; - } - { jjCheckNAddTwoStates(30, 31); } - break; - case 32: - if ((0x280000000000L & l) != 0L) - { jjCheckNAdd(33); } - break; - case 33: - if ((0x3ff000000000000L & l) == 0L) { - break; - } - if (kind > 16) { - kind = 16; - } - { jjCheckNAdd(33); } - break; - case 34: - if ((0x3fe000000000000L & l) != 0L) - { jjCheckNAddTwoStates(35, 29); } - break; - case 35: - if ((0x3ff000000000000L & l) != 0L) - { jjCheckNAddTwoStates(35, 29); } - break; - case 36: - if (curChar != 48) { - break; - } - if (kind > 15) { - kind = 15; - } - { jjCheckNAddStates(9, 11); } - break; - case 37: - if ((0x3fe000000000000L & l) == 0L) { - break; - } - if (kind > 15) { - kind = 15; - } - { jjCheckNAddStates(6, 8); } - break; - default : break; + } while (i != startsAt); } - } while(i != startsAt); - } - else if (curChar < 128) - { - long l = 1L << (curChar & 077); - do - { - switch(jjstateSet[--i]) - { - case 0: - case 15: - if ((0x7fffffe07fffffeL & l) == 0L) { - break; - } - if (kind > 28) { - kind = 28; - } - { jjCheckNAdd(15); } - break; - case 38: - if ((0xffffffffefffffffL & l) != 0L) - { jjCheckNAddStates(12, 14); } - else if (curChar == 92) { - jjstateSet[jjnewStateCnt++] = 8; - } - break; - case 39: - if ((0xffffffffefffffffL & l) != 0L) - { jjCheckNAddStates(15, 17); } - else if (curChar == 92) { - jjstateSet[jjnewStateCnt++] = 13; - } - break; - case 1: - { jjAddStates(18, 19); } - break; - case 6: - if ((0xffffffffefffffffL & l) != 0L) - { jjCheckNAddStates(12, 14); } - break; - case 7: - if (curChar == 92) { - jjstateSet[jjnewStateCnt++] = 8; - } - break; - case 8: - if ((0x14404410144044L & l) != 0L) - { jjCheckNAddStates(12, 14); } - break; - case 11: - if ((0xffffffffefffffffL & l) != 0L) - { jjCheckNAddStates(15, 17); } - break; - case 12: - if (curChar == 92) { - jjstateSet[jjnewStateCnt++] = 13; - } - break; - case 13: - if ((0x14404410144044L & l) != 0L) - { jjCheckNAddStates(15, 17); } - break; - case 18: - { jjAddStates(20, 21); } - break; - case 21: - { jjAddStates(22, 23); } - break; - case 31: - if ((0x2000000020L & l) != 0L) - { jjAddStates(24, 25); } - break; - default : break; + if (kind != 0x7fffffff) { + jjmatchedKind = kind; + jjmatchedPos = curPos; + kind = 0x7fffffff; } - } while(i != startsAt); - } else { - int hiByte = (curChar >> 8); - int i1 = hiByte >> 6; - long l1 = 1L << (hiByte & 077); - int i2 = (curChar & 0xff) >> 6; - long l2 = 1L << (curChar & 077); - do - { - switch(jjstateSet[--i]) - { - case 38: - case 6: - if (jjCanMove_0(hiByte, i1, i2, l1, l2)) - { jjCheckNAddStates(12, 14); } - break; - case 39: - case 11: - if (jjCanMove_0(hiByte, i1, i2, l1, l2)) - { jjCheckNAddStates(15, 17); } - break; - case 1: - if (jjCanMove_0(hiByte, i1, i2, l1, l2)) - { jjAddStates(18, 19); } - break; - case 18: - if (jjCanMove_0(hiByte, i1, i2, l1, l2)) - { jjAddStates(20, 21); } - break; - case 21: - if (jjCanMove_0(hiByte, i1, i2, l1, l2)) - { jjAddStates(22, 23); } - break; - default : if (i1 == 0 || l1 == 0 || i2 == 0 || l2 == 0) { + ++curPos; + if ((i = jjnewStateCnt) == (startsAt = 38 - (jjnewStateCnt = startsAt))) { + return curPos; + } + try { + curChar = input_stream.readChar(); + } catch (java.io.IOException e) { + return curPos; + } + } + } + + /** Token literal values. */ + public static final String[] jjstrLiteralImages = + { "", null, null, null, null, null, "\54", "\173", "\175", "\72", "\133", "\135", null, null, null, null, + null, null, null, null, null, null, "\47\47", "\42\42", null, null, null, null, null, }; + + protected Token jjFillToken() { + final Token t; + final String curTokenImage; + final int beginLine; + final int endLine; + final int beginColumn; + final int endColumn; + String im = jjstrLiteralImages[jjmatchedKind]; + curTokenImage = (im == null) ? input_stream.GetImage() : im; + beginLine = input_stream.getBeginLine(); + beginColumn = input_stream.getBeginColumn(); + endLine = input_stream.getEndLine(); + endColumn = input_stream.getEndColumn(); + t = Token.newToken(jjmatchedKind, curTokenImage); + + t.beginLine = beginLine; + t.endLine = endLine; + t.beginColumn = beginColumn; + t.endColumn = endColumn; + + return t; + } + + static final int[] jjnextStates = + { 25, 26, 28, 34, 17, 20, 27, 35, 29, 25, 28, 29, 6, 7, 9, 11, 12, 14, 1, 2, 18, 19, 21, 23, 32, 33, }; + + private static final boolean jjCanMove_0(int hiByte, int i1, int i2, long l1, long l2) { + switch (hiByte) { + case 0: + return ((jjbitVec2[i2] & l2) != 0L); + default: + if ((jjbitVec0[i1] & l1) != 0L) { + return true; + } + return false; + } + } + + int curLexState = 0; + int defaultLexState = 0; + int jjnewStateCnt; + int jjround; + int jjmatchedPos; + int jjmatchedKind; + + /** Get the next Token. */ + public Token getNextToken() { + Token matchedToken; + int curPos = 0; + + EOFLoop: + for (;;) { + try { + curChar = input_stream.BeginToken(); + } catch (Exception e) { + jjmatchedKind = 0; + jjmatchedPos = -1; + matchedToken = jjFillToken(); + return matchedToken; + } + + jjmatchedKind = 0x7fffffff; + jjmatchedPos = 0; + curPos = jjMoveStringLiteralDfa0_0(); + if (jjmatchedKind != 0x7fffffff) { + if (jjmatchedPos + 1 < curPos) { + input_stream.backup(curPos - jjmatchedPos - 1); + } + if ((jjtoToken[jjmatchedKind >> 6] & (1L << (jjmatchedKind & 077))) != 0L) { + matchedToken = jjFillToken(); + return matchedToken; + } else { + continue EOFLoop; + } + } + int error_line = input_stream.getEndLine(); + int error_column = input_stream.getEndColumn(); + String error_after = null; + boolean EOFSeen = false; + try { + input_stream.readChar(); + input_stream.backup(1); + } catch (java.io.IOException e1) { + EOFSeen = true; + error_after = curPos <= 1 ? "" : input_stream.GetImage(); + if (curChar == '\n' || curChar == '\r') { + error_line++; + error_column = 0; + } else { + error_column++; + } + } + if (!EOFSeen) { + input_stream.backup(1); + error_after = curPos <= 1 ? "" : input_stream.GetImage(); + } + throw new TokenMgrError(EOFSeen, curLexState, error_line, error_column, error_after, curChar, + TokenMgrError.LEXICAL_ERROR); + } + } + + void SkipLexicalActions(Token matchedToken) { + switch (jjmatchedKind) { + default: break; - } else { + } + } + + void MoreLexicalActions() { + jjimageLen += (lengthOfMatch = jjmatchedPos + 1); + switch (jjmatchedKind) { + default: break; - } - } - } while(i != startsAt); - } - if (kind != 0x7fffffff) - { - jjmatchedKind = kind; - jjmatchedPos = curPos; - kind = 0x7fffffff; - } - ++curPos; - if ((i = jjnewStateCnt) == (startsAt = 38 - (jjnewStateCnt = startsAt))) { - return curPos; - } - try { curChar = input_stream.readChar(); } - catch(java.io.IOException e) { return curPos; } - } -} - -/** Token literal values. */ -public static final String[] jjstrLiteralImages = { -"", null, null, null, null, null, "\54", "\173", "\175", "\72", "\133", -"\135", null, null, null, null, null, null, null, null, null, null, "\47\47", -"\42\42", null, null, null, null, null, }; -protected Token jjFillToken() -{ - final Token t; - final String curTokenImage; - final int beginLine; - final int endLine; - final int beginColumn; - final int endColumn; - String im = jjstrLiteralImages[jjmatchedKind]; - curTokenImage = (im == null) ? input_stream.GetImage() : im; - beginLine = input_stream.getBeginLine(); - beginColumn = input_stream.getBeginColumn(); - endLine = input_stream.getEndLine(); - endColumn = input_stream.getEndColumn(); - t = Token.newToken(jjmatchedKind, curTokenImage); - - t.beginLine = beginLine; - t.endLine = endLine; - t.beginColumn = beginColumn; - t.endColumn = endColumn; - - return t; -} -static final int[] jjnextStates = { - 25, 26, 28, 34, 17, 20, 27, 35, 29, 25, 28, 29, 6, 7, 9, 11, - 12, 14, 1, 2, 18, 19, 21, 23, 32, 33, -}; -private static final boolean jjCanMove_0(int hiByte, int i1, int i2, long l1, long l2) -{ - switch(hiByte) - { - case 0: - return ((jjbitVec2[i2] & l2) != 0L); - default : - if ((jjbitVec0[i1] & l1) != 0L) { - return true; - } - return false; - } -} - -int curLexState = 0; -int defaultLexState = 0; -int jjnewStateCnt; -int jjround; -int jjmatchedPos; -int jjmatchedKind; - -/** Get the next Token. */ -public Token getNextToken() -{ - Token matchedToken; - int curPos = 0; - - EOFLoop : - for (;;) - { - try - { - curChar = input_stream.BeginToken(); - } - catch(Exception e) - { - jjmatchedKind = 0; - jjmatchedPos = -1; - matchedToken = jjFillToken(); - return matchedToken; - } - - jjmatchedKind = 0x7fffffff; - jjmatchedPos = 0; - curPos = jjMoveStringLiteralDfa0_0(); - if (jjmatchedKind != 0x7fffffff) - { - if (jjmatchedPos + 1 < curPos) { - input_stream.backup(curPos - jjmatchedPos - 1); - } - if ((jjtoToken[jjmatchedKind >> 6] & (1L << (jjmatchedKind & 077))) != 0L) - { - matchedToken = jjFillToken(); - return matchedToken; - } else { - continue EOFLoop; - } - } - int error_line = input_stream.getEndLine(); - int error_column = input_stream.getEndColumn(); - String error_after = null; - boolean EOFSeen = false; - try { input_stream.readChar(); input_stream.backup(1); } - catch (java.io.IOException e1) { - EOFSeen = true; - error_after = curPos <= 1 ? "" : input_stream.GetImage(); - if (curChar == '\n' || curChar == '\r') { - error_line++; - error_column = 0; - } else { - error_column++; - } - } - if (!EOFSeen) { - input_stream.backup(1); - error_after = curPos <= 1 ? "" : input_stream.GetImage(); - } - throw new TokenMgrError(EOFSeen, curLexState, error_line, error_column, error_after, curChar, TokenMgrError.LEXICAL_ERROR); - } -} - -void SkipLexicalActions(Token matchedToken) -{ - switch(jjmatchedKind) - { - default : - break; - } -} -void MoreLexicalActions() -{ - jjimageLen += (lengthOfMatch = jjmatchedPos + 1); - switch(jjmatchedKind) - { - default : - break; - } -} -void TokenLexicalActions(Token matchedToken) -{ - switch(jjmatchedKind) - { - default : - break; - } -} -private void jjCheckNAdd(int state) -{ - if (jjrounds[state] != jjround) - { - jjstateSet[jjnewStateCnt++] = state; - jjrounds[state] = jjround; - } -} -private void jjAddStates(int start, int end) -{ - do { - jjstateSet[jjnewStateCnt++] = jjnextStates[start]; - } while (start++ != end); -} -private void jjCheckNAddTwoStates(int state1, int state2) -{ - jjCheckNAdd(state1); - jjCheckNAdd(state2); -} - -private void jjCheckNAddStates(int start, int end) -{ - do { - jjCheckNAdd(jjnextStates[start]); - } while (start++ != end); -} + } + } + + void TokenLexicalActions(Token matchedToken) { + switch (jjmatchedKind) { + default: + break; + } + } + + private void jjCheckNAdd(int state) { + if (jjrounds[state] != jjround) { + jjstateSet[jjnewStateCnt++] = state; + jjrounds[state] = jjround; + } + } + + private void jjAddStates(int start, int end) { + do { + jjstateSet[jjnewStateCnt++] = jjnextStates[start]; + } while (start++ != end); + } + + private void jjCheckNAddTwoStates(int state1, int state2) { + jjCheckNAdd(state1); + jjCheckNAdd(state2); + } + + private void jjCheckNAddStates(int start, int end) { + do { + jjCheckNAdd(jjnextStates[start]); + } while (start++ != end); + } /** Constructor. */ - public JSONParserTokenManager(JavaCharStream stream){ + public JSONParserTokenManager(JavaCharStream stream) { + + if (JavaCharStream.staticFlag) { + throw new Error("ERROR: Cannot use a static CharStream class with a non-static lexical analyzer."); + } + + input_stream = stream; + } + + /** Constructor. */ + public JSONParserTokenManager(JavaCharStream stream, int lexState) { + ReInit(stream); + SwitchTo(lexState); + } + + /** Reinitialise parser. */ + public void ReInit(JavaCharStream stream) { + jjmatchedPos = jjnewStateCnt = 0; + curLexState = defaultLexState; + input_stream = stream; + ReInitRounds(); + } + + private void ReInitRounds() { + int i; + jjround = 0x80000001; + for (i = 38; i-- > 0;) { + jjrounds[i] = 0x80000000; + } + } + + /** Reinitialise parser. */ + public void ReInit(JavaCharStream stream, int lexState) { + ReInit(stream); + SwitchTo(lexState); + } + + /** Switch to specified lex state. */ + public void SwitchTo(int lexState) { + if (lexState >= 1 || lexState < 0) { + throw new TokenMgrError("Error: Ignoring invalid lexical state : " + lexState + ". State unchanged.", + TokenMgrError.INVALID_LEXICAL_STATE); + } else { + curLexState = lexState; + } + } + + + /** Lexer state names. */ + public static final String[] lexStateNames = { "DEFAULT", }; - if (JavaCharStream.staticFlag) { - throw new Error("ERROR: Cannot use a static CharStream class with a non-static lexical analyzer."); - } - - input_stream = stream; - } - - /** Constructor. */ - public JSONParserTokenManager (JavaCharStream stream, int lexState){ - ReInit(stream); - SwitchTo(lexState); - } - - /** Reinitialise parser. */ - public void ReInit(JavaCharStream stream) - { - jjmatchedPos = - jjnewStateCnt = - 0; - curLexState = defaultLexState; - input_stream = stream; - ReInitRounds(); - } - - private void ReInitRounds() - { - int i; - jjround = 0x80000001; - for (i = 38; i-- > 0;) { - jjrounds[i] = 0x80000000; - } - } - - /** Reinitialise parser. */ - public void ReInit(JavaCharStream stream, int lexState) - { - ReInit(stream); - SwitchTo(lexState); - } - - /** Switch to specified lex state. */ - public void SwitchTo(int lexState) - { - if (lexState >= 1 || lexState < 0) { - throw new TokenMgrError("Error: Ignoring invalid lexical state : " + lexState + ". State unchanged.", TokenMgrError.INVALID_LEXICAL_STATE); - } else { - curLexState = lexState; - } - } - - -/** Lexer state names. */ -public static final String[] lexStateNames = { - "DEFAULT", -}; - -/** Lex State array. */ -public static final int[] jjnewLexState = { - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -}; -static final long[] jjtoToken = { - 0x1ccf8fc1L, -}; -static final long[] jjtoSkip = { - 0x3eL, -}; -static final long[] jjtoSpecial = { - 0x0L, -}; -static final long[] jjtoMore = { - 0x0L, -}; - protected JavaCharStream input_stream; + /** Lex State array. */ + public static final int[] jjnewLexState = { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, }; + static final long[] jjtoToken = { 0x1ccf8fc1L, }; + static final long[] jjtoSkip = { 0x3eL, }; + static final long[] jjtoSpecial = { 0x0L, }; + static final long[] jjtoMore = { 0x0L, }; + protected JavaCharStream input_stream; private final int[] jjrounds = new int[38]; private final int[] jjstateSet = new int[2 * 38]; diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/json/JavaCharStream.java tomcat10-10.1.52/java/org/apache/tomcat/util/json/JavaCharStream.java --- tomcat10-10.1.40/java/org/apache/tomcat/util/json/JavaCharStream.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/json/JavaCharStream.java 2026-01-23 19:33:36.000000000 +0000 @@ -19,623 +19,570 @@ package org.apache.tomcat.util.json; /** - * An implementation of interface CharStream, where the stream is assumed to - * contain only ASCII characters (with java-like unicode escape processing). + * An implementation of interface CharStream, where the stream is assumed to contain only ASCII characters (with + * java-like unicode escape processing). */ @SuppressWarnings("all") // Ignore warnings in generated code -public -class JavaCharStream -{ - /** Whether parser is static. */ - public static final boolean staticFlag = false; - - static final int hexval(char c) throws java.io.IOException { - switch(c) - { - case '0' : - return 0; - case '1' : - return 1; - case '2' : - return 2; - case '3' : - return 3; - case '4' : - return 4; - case '5' : - return 5; - case '6' : - return 6; - case '7' : - return 7; - case '8' : - return 8; - case '9' : - return 9; - - case 'a' : - case 'A' : - return 10; - case 'b' : - case 'B' : - return 11; - case 'c' : - case 'C' : - return 12; - case 'd' : - case 'D' : - return 13; - case 'e' : - case 'E' : - return 14; - case 'f' : - case 'F' : - return 15; - } - - throw new java.io.IOException(); // Should never come here - } - -/** Position in buffer. */ - public int bufpos = -1; - int bufsize; - int available; - int tokenBegin; - protected int bufline[]; - protected int bufcolumn[]; - - protected int column = 0; - protected int line = 1; - - protected boolean prevCharIsCR = false; - protected boolean prevCharIsLF = false; - - protected java.io.Reader inputStream; - - protected char[] nextCharBuf; - protected char[] buffer; - protected int maxNextCharInd = 0; - protected int nextCharInd = -1; - protected int inBuf = 0; - protected int tabSize = 1; - protected boolean trackLineColumn = true; - - public void setTabSize(int i) { tabSize = i; } - public int getTabSize() { return tabSize; } - - protected void ExpandBuff(boolean wrapAround) - { - char[] newbuffer = new char[bufsize + 2048]; - int newbufline[] = new int[bufsize + 2048]; - int newbufcolumn[] = new int[bufsize + 2048]; - - try - { - if (wrapAround) - { - System.arraycopy(buffer, tokenBegin, newbuffer, 0, bufsize - tokenBegin); - System.arraycopy(buffer, 0, newbuffer, bufsize - tokenBegin, bufpos); - buffer = newbuffer; - - System.arraycopy(bufline, tokenBegin, newbufline, 0, bufsize - tokenBegin); - System.arraycopy(bufline, 0, newbufline, bufsize - tokenBegin, bufpos); - bufline = newbufline; - - System.arraycopy(bufcolumn, tokenBegin, newbufcolumn, 0, bufsize - tokenBegin); - System.arraycopy(bufcolumn, 0, newbufcolumn, bufsize - tokenBegin, bufpos); - bufcolumn = newbufcolumn; - - bufpos += (bufsize - tokenBegin); - } else { - System.arraycopy(buffer, tokenBegin, newbuffer, 0, bufsize - tokenBegin); - buffer = newbuffer; - - System.arraycopy(bufline, tokenBegin, newbufline, 0, bufsize - tokenBegin); - bufline = newbufline; - - System.arraycopy(bufcolumn, tokenBegin, newbufcolumn, 0, bufsize - tokenBegin); - bufcolumn = newbufcolumn; - - bufpos -= tokenBegin; - } - } - catch (Throwable t) - { - throw new Error(t.getMessage()); - } - - available = (bufsize += 2048); - tokenBegin = 0; - } - - protected void FillBuff() throws java.io.IOException - { - int i; - if (maxNextCharInd == 4096) { - maxNextCharInd = nextCharInd = 0; - } - - try { - if ((i = inputStream.read(nextCharBuf, maxNextCharInd, - 4096 - maxNextCharInd)) == -1) - { - inputStream.close(); - throw new java.io.IOException(); - } else { - maxNextCharInd += i; - } - return; - } - catch(java.io.IOException e) { - if (bufpos != 0) - { - --bufpos; - backup(0); - } else { +public class JavaCharStream { + /** Whether parser is static. */ + public static final boolean staticFlag = false; + + static final int hexval(char c) throws java.io.IOException { + switch (c) { + case '0': + return 0; + case '1': + return 1; + case '2': + return 2; + case '3': + return 3; + case '4': + return 4; + case '5': + return 5; + case '6': + return 6; + case '7': + return 7; + case '8': + return 8; + case '9': + return 9; + + case 'a': + case 'A': + return 10; + case 'b': + case 'B': + return 11; + case 'c': + case 'C': + return 12; + case 'd': + case 'D': + return 13; + case 'e': + case 'E': + return 14; + case 'f': + case 'F': + return 15; + } + + throw new java.io.IOException(); // Should never come here + } + + /** Position in buffer. */ + public int bufpos = -1; + int bufsize; + int available; + int tokenBegin; + protected int bufline[]; + protected int bufcolumn[]; + + protected int column = 0; + protected int line = 1; + + protected boolean prevCharIsCR = false; + protected boolean prevCharIsLF = false; + + protected java.io.Reader inputStream; + + protected char[] nextCharBuf; + protected char[] buffer; + protected int maxNextCharInd = 0; + protected int nextCharInd = -1; + protected int inBuf = 0; + protected int tabSize = 1; + protected boolean trackLineColumn = true; + + public void setTabSize(int i) { + tabSize = i; + } + + public int getTabSize() { + return tabSize; + } + + protected void ExpandBuff(boolean wrapAround) { + char[] newbuffer = new char[bufsize + 2048]; + int newbufline[] = new int[bufsize + 2048]; + int newbufcolumn[] = new int[bufsize + 2048]; + + try { + if (wrapAround) { + System.arraycopy(buffer, tokenBegin, newbuffer, 0, bufsize - tokenBegin); + System.arraycopy(buffer, 0, newbuffer, bufsize - tokenBegin, bufpos); + buffer = newbuffer; + + System.arraycopy(bufline, tokenBegin, newbufline, 0, bufsize - tokenBegin); + System.arraycopy(bufline, 0, newbufline, bufsize - tokenBegin, bufpos); + bufline = newbufline; + + System.arraycopy(bufcolumn, tokenBegin, newbufcolumn, 0, bufsize - tokenBegin); + System.arraycopy(bufcolumn, 0, newbufcolumn, bufsize - tokenBegin, bufpos); + bufcolumn = newbufcolumn; + + bufpos += (bufsize - tokenBegin); + } else { + System.arraycopy(buffer, tokenBegin, newbuffer, 0, bufsize - tokenBegin); + buffer = newbuffer; + + System.arraycopy(bufline, tokenBegin, newbufline, 0, bufsize - tokenBegin); + bufline = newbufline; + + System.arraycopy(bufcolumn, tokenBegin, newbufcolumn, 0, bufsize - tokenBegin); + bufcolumn = newbufcolumn; + + bufpos -= tokenBegin; + } + } catch (Throwable t) { + throw new Error(t.getMessage()); + } + + available = (bufsize += 2048); + tokenBegin = 0; + } + + protected void FillBuff() throws java.io.IOException { + int i; + if (maxNextCharInd == 4096) { + maxNextCharInd = nextCharInd = 0; + } + + try { + if ((i = inputStream.read(nextCharBuf, maxNextCharInd, 4096 - maxNextCharInd)) == -1) { + inputStream.close(); + throw new java.io.IOException(); + } else { + maxNextCharInd += i; + } + return; + } catch (java.io.IOException e) { + if (bufpos != 0) { + --bufpos; + backup(0); + } else { + bufline[bufpos] = line; + bufcolumn[bufpos] = column; + } + throw e; + } + } + + protected char ReadByte() throws java.io.IOException { + if (++nextCharInd >= maxNextCharInd) { + FillBuff(); + } + + return nextCharBuf[nextCharInd]; + } + + /** @return starting character for token. */ + public char BeginToken() throws java.io.IOException { + if (inBuf > 0) { + --inBuf; + + if (++bufpos == bufsize) { + bufpos = 0; + } + + tokenBegin = bufpos; + return buffer[bufpos]; + } + + tokenBegin = 0; + bufpos = -1; + + return readChar(); + } + + protected void AdjustBuffSize() { + if (available == bufsize) { + if (tokenBegin > 2048) { + bufpos = 0; + available = tokenBegin; + } else { + ExpandBuff(false); + } + } else if (available > tokenBegin) { + available = bufsize; + } else if ((tokenBegin - available) < 2048) { + ExpandBuff(true); + } else { + available = tokenBegin; + } + } + + protected void UpdateLineColumn(char c) { + column++; + + if (prevCharIsLF) { + prevCharIsLF = false; + line += (column = 1); + } else if (prevCharIsCR) { + prevCharIsCR = false; + if (c == '\n') { + prevCharIsLF = true; + } else { + line += (column = 1); + } + } + + switch (c) { + case '\r': + prevCharIsCR = true; + break; + case '\n': + prevCharIsLF = true; + break; + case '\t': + column--; + column += (tabSize - (column % tabSize)); + break; + default: + break; + } + bufline[bufpos] = line; bufcolumn[bufpos] = column; - } - throw e; } - } - protected char ReadByte() throws java.io.IOException - { - if (++nextCharInd >= maxNextCharInd) { - FillBuff(); - } - - return nextCharBuf[nextCharInd]; - } - -/** @return starting character for token. */ - public char BeginToken() throws java.io.IOException - { - if (inBuf > 0) - { - --inBuf; - - if (++bufpos == bufsize) { - bufpos = 0; - } - - tokenBegin = bufpos; - return buffer[bufpos]; - } - - tokenBegin = 0; - bufpos = -1; - - return readChar(); - } - - protected void AdjustBuffSize() - { - if (available == bufsize) - { - if (tokenBegin > 2048) - { - bufpos = 0; - available = tokenBegin; - } else { - ExpandBuff(false); - } - } - else if (available > tokenBegin) { - available = bufsize; - } else if ((tokenBegin - available) < 2048) { - ExpandBuff(true); - } else { - available = tokenBegin; - } - } - - protected void UpdateLineColumn(char c) - { - column++; - - if (prevCharIsLF) - { - prevCharIsLF = false; - line += (column = 1); - } - else if (prevCharIsCR) - { - prevCharIsCR = false; - if (c == '\n') - { - prevCharIsLF = true; - } else { - line += (column = 1); - } - } - - switch (c) - { - case '\r' : - prevCharIsCR = true; - break; - case '\n' : - prevCharIsLF = true; - break; - case '\t' : - column--; - column += (tabSize - (column % tabSize)); - break; - default : - break; - } - - bufline[bufpos] = line; - bufcolumn[bufpos] = column; - } - -/** Read a character. */ - public char readChar() throws java.io.IOException - { - if (inBuf > 0) - { - --inBuf; - - if (++bufpos == bufsize) { - bufpos = 0; - } - - return buffer[bufpos]; - } - - char c; - - if (++bufpos == available) { - AdjustBuffSize(); - } - - if ((buffer[bufpos] = c = ReadByte()) == '\\') - { - if (trackLineColumn) { UpdateLineColumn(c); } + /** Read a character. */ + public char readChar() throws java.io.IOException { + if (inBuf > 0) { + --inBuf; - int backSlashCnt = 1; + if (++bufpos == bufsize) { + bufpos = 0; + } + + return buffer[bufpos]; + } + + char c; - for (;;) // Read all the backslashes - { if (++bufpos == available) { - AdjustBuffSize(); + AdjustBuffSize(); } - try - { - if ((buffer[bufpos] = c = ReadByte()) != '\\') - { - if (trackLineColumn) { UpdateLineColumn(c); } - // found a non-backslash char. - if ((c == 'u') && ((backSlashCnt & 1) == 1)) + if ((buffer[bufpos] = c = ReadByte()) == '\\') { + if (trackLineColumn) { + UpdateLineColumn(c); + } + + int backSlashCnt = 1; + + for (;;) // Read all the backslashes { - if (--bufpos < 0) { - bufpos = bufsize - 1; - } - - break; - } - - backup(backSlashCnt); - return '\\'; - } - } - catch(java.io.IOException e) - { - // We are returning one backslash so we should only backup (count-1) - if (backSlashCnt > 1) { - backup(backSlashCnt-1); - } - - return '\\'; - } - - if (trackLineColumn) { UpdateLineColumn(c); } - backSlashCnt++; - } - - // Here, we have seen an odd number of backslash's followed by a 'u' - try - { - while ((c = ReadByte()) == 'u') { - ++column; - } - - buffer[bufpos] = c = (char)(hexval(c) << 12 | - hexval(ReadByte()) << 8 | - hexval(ReadByte()) << 4 | - hexval(ReadByte())); - - column += 4; - } - catch(java.io.IOException e) - { - throw new Error("Invalid escape character at line " + line + - " column " + column + "."); - } - - if (backSlashCnt == 1) { - return c; - } else - { - backup(backSlashCnt - 1); - return '\\'; - } - } else { - UpdateLineColumn(c); - return c; - } - } - - @Deprecated - /** - * @deprecated - * @see #getEndColumn - */ - public int getColumn() { - return bufcolumn[bufpos]; - } - - @Deprecated - /** - * @deprecated - * @see #getEndLine - */ - public int getLine() { - return bufline[bufpos]; - } - -/** Get end column. */ - public int getEndColumn() { - return bufcolumn[bufpos]; - } - -/** Get end line. */ - public int getEndLine() { - return bufline[bufpos]; - } - -/** @return column of token start */ - public int getBeginColumn() { - return bufcolumn[tokenBegin]; - } - -/** @return line number of token start */ - public int getBeginLine() { - return bufline[tokenBegin]; - } - -/** Retreat. */ - public void backup(int amount) { - - inBuf += amount; - if ((bufpos -= amount) < 0) { - bufpos += bufsize; - } - } - -/** Constructor. */ - public JavaCharStream(java.io.Reader dstream, - int startline, int startcolumn, int buffersize) - { - inputStream = dstream; - line = startline; - column = startcolumn - 1; - - available = bufsize = buffersize; - buffer = new char[buffersize]; - bufline = new int[buffersize]; - bufcolumn = new int[buffersize]; - nextCharBuf = new char[4096]; - } - -/** Constructor. */ - public JavaCharStream(java.io.Reader dstream, - int startline, int startcolumn) - { - this(dstream, startline, startcolumn, 4096); - } - -/** Constructor. */ - public JavaCharStream(java.io.Reader dstream) - { - this(dstream, 1, 1, 4096); - } -/** Reinitialise. */ - public void ReInit(java.io.Reader dstream, - int startline, int startcolumn, int buffersize) - { - inputStream = dstream; - line = startline; - column = startcolumn - 1; - - if (buffer == null || buffersize != buffer.length) - { - available = bufsize = buffersize; - buffer = new char[buffersize]; - bufline = new int[buffersize]; - bufcolumn = new int[buffersize]; - nextCharBuf = new char[4096]; - } - prevCharIsLF = prevCharIsCR = false; - tokenBegin = inBuf = maxNextCharInd = 0; - nextCharInd = bufpos = -1; - } - -/** Reinitialise. */ - public void ReInit(java.io.Reader dstream, - int startline, int startcolumn) - { - ReInit(dstream, startline, startcolumn, 4096); - } - -/** Reinitialise. */ - public void ReInit(java.io.Reader dstream) - { - ReInit(dstream, 1, 1, 4096); - } -/** Constructor. */ - public JavaCharStream(java.io.InputStream dstream, String encoding, int startline, - int startcolumn, int buffersize) throws java.io.UnsupportedEncodingException - { - this(encoding == null ? new java.io.InputStreamReader(dstream) : new java.io.InputStreamReader(dstream, encoding), startline, startcolumn, buffersize); - } - -/** Constructor. */ - public JavaCharStream(java.io.InputStream dstream, int startline, - int startcolumn, int buffersize) - { - this(new java.io.InputStreamReader(dstream), startline, startcolumn, 4096); - } - -/** Constructor. */ - public JavaCharStream(java.io.InputStream dstream, String encoding, int startline, - int startcolumn) throws java.io.UnsupportedEncodingException - { - this(dstream, encoding, startline, startcolumn, 4096); - } - -/** Constructor. */ - public JavaCharStream(java.io.InputStream dstream, int startline, - int startcolumn) - { - this(dstream, startline, startcolumn, 4096); - } - -/** Constructor. */ - public JavaCharStream(java.io.InputStream dstream, String encoding) throws java.io.UnsupportedEncodingException - { - this(dstream, encoding, 1, 1, 4096); - } - -/** Constructor. */ - public JavaCharStream(java.io.InputStream dstream) - { - this(dstream, 1, 1, 4096); - } - -/** Reinitialise. */ - public void ReInit(java.io.InputStream dstream, String encoding, int startline, - int startcolumn, int buffersize) throws java.io.UnsupportedEncodingException - { - ReInit(encoding == null ? new java.io.InputStreamReader(dstream) : new java.io.InputStreamReader(dstream, encoding), startline, startcolumn, buffersize); - } - -/** Reinitialise. */ - public void ReInit(java.io.InputStream dstream, int startline, - int startcolumn, int buffersize) - { - ReInit(new java.io.InputStreamReader(dstream), startline, startcolumn, buffersize); - } -/** Reinitialise. */ - public void ReInit(java.io.InputStream dstream, String encoding, int startline, - int startcolumn) throws java.io.UnsupportedEncodingException - { - ReInit(dstream, encoding, startline, startcolumn, 4096); - } -/** Reinitialise. */ - public void ReInit(java.io.InputStream dstream, int startline, - int startcolumn) - { - ReInit(dstream, startline, startcolumn, 4096); - } -/** Reinitialise. */ - public void ReInit(java.io.InputStream dstream, String encoding) throws java.io.UnsupportedEncodingException - { - ReInit(dstream, encoding, 1, 1, 4096); - } - -/** Reinitialise. */ - public void ReInit(java.io.InputStream dstream) - { - ReInit(dstream, 1, 1, 4096); - } - - /** @return token image as String */ - public String GetImage() - { - if (bufpos >= tokenBegin) { - return new String(buffer, tokenBegin, bufpos - tokenBegin + 1); - } else { - return new String(buffer, tokenBegin, bufsize - tokenBegin) + - new String(buffer, 0, bufpos + 1); - } - } - - /** @return suffix */ - public char[] GetSuffix(int len) - { - char[] ret = new char[len]; - - if ((bufpos + 1) >= len) { - System.arraycopy(buffer, bufpos - len + 1, ret, 0, len); - } else - { - System.arraycopy(buffer, bufsize - (len - bufpos - 1), ret, 0, - len - bufpos - 1); - System.arraycopy(buffer, 0, ret, len - bufpos - 1, bufpos + 1); - } - - return ret; - } - - /** Set buffers back to null when finished. */ - public void Done() - { - nextCharBuf = null; - buffer = null; - bufline = null; - bufcolumn = null; - } - - /** - * Method to adjust line and column numbers for the start of a token. - */ - public void adjustBeginLineColumn(int newLine, int newCol) - { - int start = tokenBegin; - int len; - - if (bufpos >= tokenBegin) - { - len = bufpos - tokenBegin + inBuf + 1; - } else { - len = bufsize - tokenBegin + bufpos + 1 + inBuf; - } - - int i = 0, j = 0, k = 0; - int nextColDiff = 0, columnDiff = 0; - - while (i < len && bufline[j = start % bufsize] == bufline[k = ++start % bufsize]) - { - bufline[j] = newLine; - nextColDiff = columnDiff + bufcolumn[k] - bufcolumn[j]; - bufcolumn[j] = newCol + columnDiff; - columnDiff = nextColDiff; - i++; - } - - if (i < len) - { - bufline[j] = newLine++; - bufcolumn[j] = newCol + columnDiff; - - while (i++ < len) - { - if (bufline[j = start % bufsize] != bufline[++start % bufsize]) { - bufline[j] = newLine++; + if (++bufpos == available) { + AdjustBuffSize(); + } + + try { + if ((buffer[bufpos] = c = ReadByte()) != '\\') { + if (trackLineColumn) { + UpdateLineColumn(c); + } + // found a non-backslash char. + if ((c == 'u') && ((backSlashCnt & 1) == 1)) { + if (--bufpos < 0) { + bufpos = bufsize - 1; + } + + break; + } + + backup(backSlashCnt); + return '\\'; + } + } catch (java.io.IOException e) { + // We are returning one backslash so we should only backup (count-1) + if (backSlashCnt > 1) { + backup(backSlashCnt - 1); + } + + return '\\'; + } + + if (trackLineColumn) { + UpdateLineColumn(c); + } + backSlashCnt++; + } + + // Here, we have seen an odd number of backslash's followed by a 'u' + try { + while ((c = ReadByte()) == 'u') { + ++column; + } + + buffer[bufpos] = c = (char) (hexval(c) << 12 | hexval(ReadByte()) << 8 | hexval(ReadByte()) << 4 | + hexval(ReadByte())); + + column += 4; + } catch (java.io.IOException e) { + throw new Error("Invalid escape character at line " + line + " column " + column + "."); + } + + if (backSlashCnt == 1) { + return c; + } else { + backup(backSlashCnt - 1); + return '\\'; + } } else { - bufline[j] = newLine; + UpdateLineColumn(c); + return c; } - } } - line = bufline[j]; - column = bufcolumn[j]; - } - boolean getTrackLineColumn() { return trackLineColumn; } - void setTrackLineColumn(boolean tlc) { trackLineColumn = tlc; } + @Deprecated + /** + * @deprecated + * + * @see #getEndColumn + */ + public int getColumn() { + return bufcolumn[bufpos]; + } + + @Deprecated + /** + * @deprecated + * + * @see #getEndLine + */ + public int getLine() { + return bufline[bufpos]; + } + + /** Get end column. */ + public int getEndColumn() { + return bufcolumn[bufpos]; + } + + /** Get end line. */ + public int getEndLine() { + return bufline[bufpos]; + } + + /** @return column of token start */ + public int getBeginColumn() { + return bufcolumn[tokenBegin]; + } + + /** @return line number of token start */ + public int getBeginLine() { + return bufline[tokenBegin]; + } + + /** Retreat. */ + public void backup(int amount) { + + inBuf += amount; + if ((bufpos -= amount) < 0) { + bufpos += bufsize; + } + } + + /** Constructor. */ + public JavaCharStream(java.io.Reader dstream, int startline, int startcolumn, int buffersize) { + inputStream = dstream; + line = startline; + column = startcolumn - 1; + + available = bufsize = buffersize; + buffer = new char[buffersize]; + bufline = new int[buffersize]; + bufcolumn = new int[buffersize]; + nextCharBuf = new char[4096]; + } + + /** Constructor. */ + public JavaCharStream(java.io.Reader dstream, int startline, int startcolumn) { + this(dstream, startline, startcolumn, 4096); + } + + /** Constructor. */ + public JavaCharStream(java.io.Reader dstream) { + this(dstream, 1, 1, 4096); + } + + /** Reinitialise. */ + public void ReInit(java.io.Reader dstream, int startline, int startcolumn, int buffersize) { + inputStream = dstream; + line = startline; + column = startcolumn - 1; + + if (buffer == null || buffersize != buffer.length) { + available = bufsize = buffersize; + buffer = new char[buffersize]; + bufline = new int[buffersize]; + bufcolumn = new int[buffersize]; + nextCharBuf = new char[4096]; + } + prevCharIsLF = prevCharIsCR = false; + tokenBegin = inBuf = maxNextCharInd = 0; + nextCharInd = bufpos = -1; + } + + /** Reinitialise. */ + public void ReInit(java.io.Reader dstream, int startline, int startcolumn) { + ReInit(dstream, startline, startcolumn, 4096); + } + + /** Reinitialise. */ + public void ReInit(java.io.Reader dstream) { + ReInit(dstream, 1, 1, 4096); + } + + /** Constructor. */ + public JavaCharStream(java.io.InputStream dstream, String encoding, int startline, int startcolumn, int buffersize) + throws java.io.UnsupportedEncodingException { + this(encoding == null ? new java.io.InputStreamReader(dstream) : + new java.io.InputStreamReader(dstream, encoding), startline, startcolumn, buffersize); + } + + /** Constructor. */ + public JavaCharStream(java.io.InputStream dstream, int startline, int startcolumn, int buffersize) { + this(new java.io.InputStreamReader(dstream), startline, startcolumn, 4096); + } + + /** Constructor. */ + public JavaCharStream(java.io.InputStream dstream, String encoding, int startline, int startcolumn) + throws java.io.UnsupportedEncodingException { + this(dstream, encoding, startline, startcolumn, 4096); + } + + /** Constructor. */ + public JavaCharStream(java.io.InputStream dstream, int startline, int startcolumn) { + this(dstream, startline, startcolumn, 4096); + } + + /** Constructor. */ + public JavaCharStream(java.io.InputStream dstream, String encoding) throws java.io.UnsupportedEncodingException { + this(dstream, encoding, 1, 1, 4096); + } + + /** Constructor. */ + public JavaCharStream(java.io.InputStream dstream) { + this(dstream, 1, 1, 4096); + } + + /** Reinitialise. */ + public void ReInit(java.io.InputStream dstream, String encoding, int startline, int startcolumn, int buffersize) + throws java.io.UnsupportedEncodingException { + ReInit(encoding == null ? new java.io.InputStreamReader(dstream) : + new java.io.InputStreamReader(dstream, encoding), startline, startcolumn, buffersize); + } + + /** Reinitialise. */ + public void ReInit(java.io.InputStream dstream, int startline, int startcolumn, int buffersize) { + ReInit(new java.io.InputStreamReader(dstream), startline, startcolumn, buffersize); + } + + /** Reinitialise. */ + public void ReInit(java.io.InputStream dstream, String encoding, int startline, int startcolumn) + throws java.io.UnsupportedEncodingException { + ReInit(dstream, encoding, startline, startcolumn, 4096); + } + + /** Reinitialise. */ + public void ReInit(java.io.InputStream dstream, int startline, int startcolumn) { + ReInit(dstream, startline, startcolumn, 4096); + } + + /** Reinitialise. */ + public void ReInit(java.io.InputStream dstream, String encoding) throws java.io.UnsupportedEncodingException { + ReInit(dstream, encoding, 1, 1, 4096); + } + + /** Reinitialise. */ + public void ReInit(java.io.InputStream dstream) { + ReInit(dstream, 1, 1, 4096); + } + + /** @return token image as String */ + public String GetImage() { + if (bufpos >= tokenBegin) { + return new String(buffer, tokenBegin, bufpos - tokenBegin + 1); + } else { + return new String(buffer, tokenBegin, bufsize - tokenBegin) + new String(buffer, 0, bufpos + 1); + } + } + + /** @return suffix */ + public char[] GetSuffix(int len) { + char[] ret = new char[len]; + + if ((bufpos + 1) >= len) { + System.arraycopy(buffer, bufpos - len + 1, ret, 0, len); + } else { + System.arraycopy(buffer, bufsize - (len - bufpos - 1), ret, 0, len - bufpos - 1); + System.arraycopy(buffer, 0, ret, len - bufpos - 1, bufpos + 1); + } + + return ret; + } + + /** Set buffers back to null when finished. */ + public void Done() { + nextCharBuf = null; + buffer = null; + bufline = null; + bufcolumn = null; + } + + /** + * Method to adjust line and column numbers for the start of a token. + */ + public void adjustBeginLineColumn(int newLine, int newCol) { + int start = tokenBegin; + int len; + + if (bufpos >= tokenBegin) { + len = bufpos - tokenBegin + inBuf + 1; + } else { + len = bufsize - tokenBegin + bufpos + 1 + inBuf; + } + + int i = 0, j = 0, k = 0; + int nextColDiff = 0, columnDiff = 0; + + while (i < len && bufline[j = start % bufsize] == bufline[k = ++start % bufsize]) { + bufline[j] = newLine; + nextColDiff = columnDiff + bufcolumn[k] - bufcolumn[j]; + bufcolumn[j] = newCol + columnDiff; + columnDiff = nextColDiff; + i++; + } + + if (i < len) { + bufline[j] = newLine++; + bufcolumn[j] = newCol + columnDiff; + + while (i++ < len) { + if (bufline[j = start % bufsize] != bufline[++start % bufsize]) { + bufline[j] = newLine++; + } else { + bufline[j] = newLine; + } + } + } + + line = bufline[j]; + column = bufcolumn[j]; + } + + boolean getTrackLineColumn() { + return trackLineColumn; + } + + void setTrackLineColumn(boolean tlc) { + trackLineColumn = tlc; + } } /* JavaCC - OriginalChecksum=58f718af3466d6064ba0132bca4fbce2 (do not edit this line) */ diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/json/ParseException.java tomcat10-10.1.52/java/org/apache/tomcat/util/json/ParseException.java --- tomcat10-10.1.40/java/org/apache/tomcat/util/json/ParseException.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/json/ParseException.java 2026-01-23 19:33:36.000000000 +0000 @@ -19,194 +19,172 @@ package org.apache.tomcat.util.json; /** - * This exception is thrown when parse errors are encountered. - * You can explicitly create objects of this exception type by - * calling the method generateParseException in the generated - * parser. - * - * You can modify this class to customize your error reporting - * mechanisms so long as you retain the public fields. + * This exception is thrown when parse errors are encountered. You can explicitly create objects of this exception type + * by calling the method generateParseException in the generated parser. You can modify this class to customize your + * error reporting mechanisms so long as you retain the public fields. */ @SuppressWarnings("all") // Ignore warnings in generated code public class ParseException extends Exception { - /** - * The version identifier for this Serializable class. - * Increment only if the serialized form of the - * class changes. - */ - private static final long serialVersionUID = 1L; - - /** - * The end of line string for this machine. - */ - protected static String EOL = System.getProperty("line.separator", "\n"); - - /** - * This constructor is used by the method "generateParseException" - * in the generated parser. Calling this constructor generates - * a new object of this type with the fields "currentToken", - * "expectedTokenSequences", and "tokenImage" set. - */ - public ParseException(Token currentTokenVal, - int[][] expectedTokenSequencesVal, - String[] tokenImageVal - ) - { - super(initialise(currentTokenVal, expectedTokenSequencesVal, tokenImageVal)); - currentToken = currentTokenVal; - expectedTokenSequences = expectedTokenSequencesVal; - tokenImage = tokenImageVal; - } - - /** - * The following constructors are for use by you for whatever - * purpose you can think of. Constructing the exception in this - * manner makes the exception behave in the normal way - i.e., as - * documented in the class "Throwable". The fields "errorToken", - * "expectedTokenSequences", and "tokenImage" do not contain - * relevant information. The JavaCC generated code does not use - * these constructors. - */ - - public ParseException() { - super(); - } - - /** Constructor with message. */ - public ParseException(String message) { - super(message); - } - - - /** - * This is the last token that has been consumed successfully. If - * this object has been created due to a parse error, the token - * following this token will (therefore) be the first error token. - */ - public Token currentToken; - - /** - * Each entry in this array is an array of integers. Each array - * of integers represents a sequence of tokens (by their ordinal - * values) that is expected at this point of the parse. - */ - public int[][] expectedTokenSequences; - - /** - * This is a reference to the "tokenImage" array of the generated - * parser within which the parse error occurred. This array is - * defined in the generated ...Constants interface. - */ - public String[] tokenImage; - - /** - * It uses "currentToken" and "expectedTokenSequences" to generate a parse - * error message and returns it. If this object has been created - * due to a parse error, and you do not catch it (it gets thrown - * from the parser) the correct error message - * gets displayed. - */ - private static String initialise(Token currentToken, - int[][] expectedTokenSequences, - String[] tokenImage) { - - StringBuffer expected = new StringBuffer(); - int maxSize = 0; - for (int i = 0; i < expectedTokenSequences.length; i++) { - if (maxSize < expectedTokenSequences[i].length) { - maxSize = expectedTokenSequences[i].length; - } - for (int j = 0; j < expectedTokenSequences[i].length; j++) { - expected.append(tokenImage[expectedTokenSequences[i][j]]).append(' '); - } - if (expectedTokenSequences[i][expectedTokenSequences[i].length - 1] != 0) { - expected.append("..."); - } - expected.append(EOL).append(" "); + /** + * The version identifier for this Serializable class. Increment only if the serialized form of the class + * changes. + */ + private static final long serialVersionUID = 1L; + + /** + * The end of line string for this machine. + */ + protected static String EOL = System.getProperty("line.separator", "\n"); + + /** + * This constructor is used by the method "generateParseException" in the generated parser. Calling this constructor + * generates a new object of this type with the fields "currentToken", "expectedTokenSequences", and "tokenImage" + * set. + */ + public ParseException(Token currentTokenVal, int[][] expectedTokenSequencesVal, String[] tokenImageVal) { + super(initialise(currentTokenVal, expectedTokenSequencesVal, tokenImageVal)); + currentToken = currentTokenVal; + expectedTokenSequences = expectedTokenSequencesVal; + tokenImage = tokenImageVal; } - String retval = "Encountered \""; - Token tok = currentToken.next; - for (int i = 0; i < maxSize; i++) { - if (i != 0) { - retval += " "; - } - if (tok.kind == 0) { - retval += tokenImage[0]; - break; - } - retval += " " + tokenImage[tok.kind]; - retval += " \""; - retval += add_escapes(tok.image); - retval += " \""; - tok = tok.next; - } - retval += "\" at line " + currentToken.next.beginLine + ", column " + currentToken.next.beginColumn; - retval += "." + EOL; + /** + * The following constructors are for use by you for whatever purpose you can think of. Constructing the exception + * in this manner makes the exception behave in the normal way - i.e., as documented in the class "Throwable". The + * fields "errorToken", "expectedTokenSequences", and "tokenImage" do not contain relevant information. The JavaCC + * generated code does not use these constructors. + */ + + public ParseException() { + super(); + } - if (expectedTokenSequences.length == 0) { - // Nothing to add here - } else { - if (expectedTokenSequences.length == 1) { - retval += "Was expecting:" + EOL + " "; - } else { - retval += "Was expecting one of:" + EOL + " "; - } - retval += expected.toString(); + /** Constructor with message. */ + public ParseException(String message) { + super(message); } - return retval; - } + + /** + * This is the last token that has been consumed successfully. If this object has been created due to a parse error, + * the token following this token will (therefore) be the first error token. + */ + public Token currentToken; + + /** + * Each entry in this array is an array of integers. Each array of integers represents a sequence of tokens (by + * their ordinal values) that is expected at this point of the parse. + */ + public int[][] expectedTokenSequences; + + /** + * This is a reference to the "tokenImage" array of the generated parser within which the parse error occurred. This + * array is defined in the generated ...Constants interface. + */ + public String[] tokenImage; + + /** + * It uses "currentToken" and "expectedTokenSequences" to generate a parse error message and returns it. If this + * object has been created due to a parse error, and you do not catch it (it gets thrown from the parser) the + * correct error message gets displayed. + */ + private static String initialise(Token currentToken, int[][] expectedTokenSequences, String[] tokenImage) { + + StringBuffer expected = new StringBuffer(); + int maxSize = 0; + for (int i = 0; i < expectedTokenSequences.length; i++) { + if (maxSize < expectedTokenSequences[i].length) { + maxSize = expectedTokenSequences[i].length; + } + for (int j = 0; j < expectedTokenSequences[i].length; j++) { + expected.append(tokenImage[expectedTokenSequences[i][j]]).append(' '); + } + if (expectedTokenSequences[i][expectedTokenSequences[i].length - 1] != 0) { + expected.append("..."); + } + expected.append(EOL).append(" "); + } + String retval = "Encountered \""; + Token tok = currentToken.next; + for (int i = 0; i < maxSize; i++) { + if (i != 0) { + retval += " "; + } + if (tok.kind == 0) { + retval += tokenImage[0]; + break; + } + retval += " " + tokenImage[tok.kind]; + retval += " \""; + retval += add_escapes(tok.image); + retval += " \""; + tok = tok.next; + } + retval += "\" at line " + currentToken.next.beginLine + ", column " + currentToken.next.beginColumn; + retval += "." + EOL; + + + if (expectedTokenSequences.length == 0) { + // Nothing to add here + } else { + if (expectedTokenSequences.length == 1) { + retval += "Was expecting:" + EOL + " "; + } else { + retval += "Was expecting one of:" + EOL + " "; + } + retval += expected.toString(); + } + + return retval; + } - /** - * Used to convert raw characters to their escaped version - * when these raw version cannot be used as part of an ASCII - * string literal. - */ - static String add_escapes(String str) { - StringBuffer retval = new StringBuffer(); - char ch; - for (int i = 0; i < str.length(); i++) { - switch (str.charAt(i)) - { - case '\b': - retval.append("\\b"); - continue; - case '\t': - retval.append("\\t"); - continue; - case '\n': - retval.append("\\n"); - continue; - case '\f': - retval.append("\\f"); - continue; - case '\r': - retval.append("\\r"); - continue; - case '\"': - retval.append("\\\""); - continue; - case '\'': - retval.append("\\\'"); - continue; - case '\\': - retval.append("\\\\"); - continue; - default: - if ((ch = str.charAt(i)) < 0x20 || ch > 0x7e) { - String s = "0000" + Integer.toString(ch, 16); - retval.append("\\u" + s.substring(s.length() - 4, s.length())); - } else { - retval.append(ch); - } - continue; + /** + * Used to convert raw characters to their escaped version when these raw version cannot be used as part of an ASCII + * string literal. + */ + static String add_escapes(String str) { + StringBuffer retval = new StringBuffer(); + char ch; + for (int i = 0; i < str.length(); i++) { + switch (str.charAt(i)) { + case '\b': + retval.append("\\b"); + continue; + case '\t': + retval.append("\\t"); + continue; + case '\n': + retval.append("\\n"); + continue; + case '\f': + retval.append("\\f"); + continue; + case '\r': + retval.append("\\r"); + continue; + case '\"': + retval.append("\\\""); + continue; + case '\'': + retval.append("\\\'"); + continue; + case '\\': + retval.append("\\\\"); + continue; + default: + if ((ch = str.charAt(i)) < 0x20 || ch > 0x7e) { + String s = "0000" + Integer.toString(ch, 16); + retval.append("\\u" + s.substring(s.length() - 4, s.length())); + } else { + retval.append(ch); + } + continue; + } } - } - return retval.toString(); - } + return retval.toString(); + } } /* JavaCC - OriginalChecksum=1ccce09e6dc04d17e33b6d15b9c1f0c3 (do not edit this line) */ diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/json/Token.java tomcat10-10.1.52/java/org/apache/tomcat/util/json/Token.java --- tomcat10-10.1.40/java/org/apache/tomcat/util/json/Token.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/json/Token.java 2026-01-23 19:33:36.000000000 +0000 @@ -24,124 +24,105 @@ @SuppressWarnings("all") // Ignore warnings in generated code public class Token implements java.io.Serializable { - /** - * The version identifier for this Serializable class. - * Increment only if the serialized form of the - * class changes. - */ - private static final long serialVersionUID = 1L; - - /** - * An integer that describes the kind of this token. This numbering - * system is determined by JavaCCParser, and a table of these numbers is - * stored in the file ...Constants.java. - */ - public int kind; - - /** The line number of the first character of this Token. */ - public int beginLine; - /** The column number of the first character of this Token. */ - public int beginColumn; - /** The line number of the last character of this Token. */ - public int endLine; - /** The column number of the last character of this Token. */ - public int endColumn; - - /** - * The string image of the token. - */ - public String image; - - /** - * A reference to the next regular (non-special) token from the input - * stream. If this is the last token from the input stream, or if the - * token manager has not read tokens beyond this one, this field is - * set to null. This is true only if this token is also a regular - * token. Otherwise, see below for a description of the contents of - * this field. - */ - public Token next; - - /** - * This field is used to access special tokens that occur prior to this - * token, but after the immediately preceding regular (non-special) token. - * If there are no such special tokens, this field is set to null. - * When there are more than one such special token, this field refers - * to the last of these special tokens, which in turn refers to the next - * previous special token through its specialToken field, and so on - * until the first special token (whose specialToken field is null). - * The next fields of special tokens refer to other special tokens that - * immediately follow it (without an intervening regular token). If there - * is no such token, this field is null. - */ - public Token specialToken; - - /** - * An optional attribute value of the Token. - * Tokens which are not used as syntactic sugar will often contain - * meaningful values that will be used later on by the compiler or - * interpreter. This attribute value is often different from the image. - * Any subclass of Token that actually wants to return a non-null value can - * override this method as appropriate. - */ - public Object getValue() { - return null; - } - - /** - * No-argument constructor - */ - public Token() {} - - /** - * Constructs a new token for the specified Image. - */ - public Token(int kind) - { - this(kind, null); - } - - /** - * Constructs a new token for the specified Image and Kind. - */ - public Token(int kind, String image) - { - this.kind = kind; - this.image = image; - } - - /** - * Returns the image. - */ - public String toString() - { - return image; - } - - /** - * Returns a new Token object, by default. However, if you want, you - * can create and return subclass objects based on the value of ofKind. - * Simply add the cases to the switch for all those special cases. - * For example, if you have a subclass of Token called IDToken that - * you want to create if ofKind is ID, simply add something like : - * - * case MyParserConstants.ID : return new IDToken(ofKind, image); - * - * to the following switch statement. Then you can cast matchedToken - * variable to the appropriate type and use sit in your lexical actions. - */ - public static Token newToken(int ofKind, String image) - { - switch(ofKind) - { - default : return new Token(ofKind, image); - } - } - - public static Token newToken(int ofKind) - { - return newToken(ofKind, null); - } + /** + * The version identifier for this Serializable class. Increment only if the serialized form of the class + * changes. + */ + private static final long serialVersionUID = 1L; + + /** + * An integer that describes the kind of this token. This numbering system is determined by JavaCCParser, and a + * table of these numbers is stored in the file ...Constants.java. + */ + public int kind; + + /** The line number of the first character of this Token. */ + public int beginLine; + /** The column number of the first character of this Token. */ + public int beginColumn; + /** The line number of the last character of this Token. */ + public int endLine; + /** The column number of the last character of this Token. */ + public int endColumn; + + /** + * The string image of the token. + */ + public String image; + + /** + * A reference to the next regular (non-special) token from the input stream. If this is the last token from the + * input stream, or if the token manager has not read tokens beyond this one, this field is set to null. This is + * true only if this token is also a regular token. Otherwise, see below for a description of the contents of this + * field. + */ + public Token next; + + /** + * This field is used to access special tokens that occur prior to this token, but after the immediately preceding + * regular (non-special) token. If there are no such special tokens, this field is set to null. When there are more + * than one such special token, this field refers to the last of these special tokens, which in turn refers to the + * next previous special token through its specialToken field, and so on until the first special token (whose + * specialToken field is null). The next fields of special tokens refer to other special tokens that immediately + * follow it (without an intervening regular token). If there is no such token, this field is null. + */ + public Token specialToken; + + /** + * An optional attribute value of the Token. Tokens which are not used as syntactic sugar will often contain + * meaningful values that will be used later on by the compiler or interpreter. This attribute value is often + * different from the image. Any subclass of Token that actually wants to return a non-null value can override this + * method as appropriate. + */ + public Object getValue() { + return null; + } + + /** + * No-argument constructor + */ + public Token() { + } + + /** + * Constructs a new token for the specified Image. + */ + public Token(int kind) { + this(kind, null); + } + + /** + * Constructs a new token for the specified Image and Kind. + */ + public Token(int kind, String image) { + this.kind = kind; + this.image = image; + } + + /** + * Returns the image. + */ + public String toString() { + return image; + } + + /** + * Returns a new Token object, by default. However, if you want, you can create and return subclass objects based on + * the value of ofKind. Simply add the cases to the switch for all those special cases. For example, if you have a + * subclass of Token called IDToken that you want to create if ofKind is ID, simply add something like : case + * MyParserConstants.ID : return new IDToken(ofKind, image); to the following switch statement. Then you can cast + * matchedToken variable to the appropriate type and use sit in your lexical actions. + */ + public static Token newToken(int ofKind, String image) { + switch (ofKind) { + default: + return new Token(ofKind, image); + } + } + + public static Token newToken(int ofKind) { + return newToken(ofKind, null); + } } /* JavaCC - OriginalChecksum=3fa555852689f4df3b05452671ed7031 (do not edit this line) */ diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/json/TokenMgrError.java tomcat10-10.1.52/java/org/apache/tomcat/util/json/TokenMgrError.java --- tomcat10-10.1.40/java/org/apache/tomcat/util/json/TokenMgrError.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/json/TokenMgrError.java 2026-01-23 19:33:36.000000000 +0000 @@ -20,144 +20,132 @@ /** Token Manager Error. */ @SuppressWarnings("all") // Ignore warnings in generated code -public class TokenMgrError extends Error -{ +public class TokenMgrError extends Error { - /** - * The version identifier for this Serializable class. - * Increment only if the serialized form of the - * class changes. - */ - private static final long serialVersionUID = 1L; - - /* - * Ordinals for various reasons why an Error of this type can be thrown. - */ - - /** - * Lexical error occurred. - */ - public static final int LEXICAL_ERROR = 0; - - /** - * An attempt was made to create a second instance of a static token manager. - */ - public static final int STATIC_LEXER_ERROR = 1; - - /** - * Tried to change to an invalid lexical state. - */ - public static final int INVALID_LEXICAL_STATE = 2; - - /** - * Detected (and bailed out of) an infinite loop in the token manager. - */ - public static final int LOOP_DETECTED = 3; - - /** - * Indicates the reason why the exception is thrown. It will have - * one of the above 4 values. - */ - int errorCode; - - /** - * Replaces unprintable characters by their escaped (or unicode escaped) - * equivalents in the given string - */ - protected static final String addEscapes(String str) { - StringBuffer retval = new StringBuffer(); - char ch; - for (int i = 0; i < str.length(); i++) { - switch (str.charAt(i)) - { - case '\b': - retval.append("\\b"); - continue; - case '\t': - retval.append("\\t"); - continue; - case '\n': - retval.append("\\n"); - continue; - case '\f': - retval.append("\\f"); - continue; - case '\r': - retval.append("\\r"); - continue; - case '\"': - retval.append("\\\""); - continue; - case '\'': - retval.append("\\\'"); - continue; - case '\\': - retval.append("\\\\"); - continue; - default: - if ((ch = str.charAt(i)) < 0x20 || ch > 0x7e) { - String s = "0000" + Integer.toString(ch, 16); - retval.append("\\u" + s.substring(s.length() - 4, s.length())); - } else { - retval.append(ch); - } - continue; - } - } - return retval.toString(); - } - - /** - * Returns a detailed message for the Error when it is thrown by the - * token manager to indicate a lexical error. - * Parameters : - * EOFSeen : indicates if EOF caused the lexical error - * curLexState : lexical state in which this error occurred - * errorLine : line number when the error occurred - * errorColumn : column number when the error occurred - * errorAfter : prefix that was seen before this error occurred - * curchar : the offending character - * Note: You can customize the lexical error message by modifying this method. - */ - protected static String LexicalErr(boolean EOFSeen, int lexState, int errorLine, int errorColumn, String errorAfter, int curChar) { - char curChar1 = (char)curChar; - return("Lexical error at line " + - errorLine + ", column " + - errorColumn + ". Encountered: " + - (EOFSeen ? " " : ("\"" + addEscapes(String.valueOf(curChar1)) + "\"") + " (" + (int)curChar + "), ") + - "after : \"" + addEscapes(errorAfter) + "\""); - } - - /** - * You can also modify the body of this method to customize your error messages. - * For example, cases like LOOP_DETECTED and INVALID_LEXICAL_STATE are not - * of end-users concern, so you can return something like : - * - * "Internal Error : Please file a bug report .... " - * - * from this method for such cases in the release version of your parser. - */ - public String getMessage() { - return super.getMessage(); - } - - /* - * Constructors of various flavors follow. - */ - - /** No arg constructor. */ - public TokenMgrError() { - } - - /** Constructor with message and reason. */ - public TokenMgrError(String message, int reason) { - super(message); - errorCode = reason; - } - - /** Full Constructor. */ - public TokenMgrError(boolean EOFSeen, int lexState, int errorLine, int errorColumn, String errorAfter, int curChar, int reason) { - this(LexicalErr(EOFSeen, lexState, errorLine, errorColumn, errorAfter, curChar), reason); - } + /** + * The version identifier for this Serializable class. Increment only if the serialized form of the class + * changes. + */ + private static final long serialVersionUID = 1L; + + /* + * Ordinals for various reasons why an Error of this type can be thrown. + */ + + /** + * Lexical error occurred. + */ + public static final int LEXICAL_ERROR = 0; + + /** + * An attempt was made to create a second instance of a static token manager. + */ + public static final int STATIC_LEXER_ERROR = 1; + + /** + * Tried to change to an invalid lexical state. + */ + public static final int INVALID_LEXICAL_STATE = 2; + + /** + * Detected (and bailed out of) an infinite loop in the token manager. + */ + public static final int LOOP_DETECTED = 3; + + /** + * Indicates the reason why the exception is thrown. It will have one of the above 4 values. + */ + int errorCode; + + /** + * Replaces unprintable characters by their escaped (or unicode escaped) equivalents in the given string + */ + protected static final String addEscapes(String str) { + StringBuffer retval = new StringBuffer(); + char ch; + for (int i = 0; i < str.length(); i++) { + switch (str.charAt(i)) { + case '\b': + retval.append("\\b"); + continue; + case '\t': + retval.append("\\t"); + continue; + case '\n': + retval.append("\\n"); + continue; + case '\f': + retval.append("\\f"); + continue; + case '\r': + retval.append("\\r"); + continue; + case '\"': + retval.append("\\\""); + continue; + case '\'': + retval.append("\\\'"); + continue; + case '\\': + retval.append("\\\\"); + continue; + default: + if ((ch = str.charAt(i)) < 0x20 || ch > 0x7e) { + String s = "0000" + Integer.toString(ch, 16); + retval.append("\\u" + s.substring(s.length() - 4, s.length())); + } else { + retval.append(ch); + } + continue; + } + } + return retval.toString(); + } + + /** + * Returns a detailed message for the Error when it is thrown by the token manager to indicate a lexical error. + * Parameters : EOFSeen : indicates if EOF caused the lexical error curLexState : lexical state in which this error + * occurred errorLine : line number when the error occurred errorColumn : column number when the error occurred + * errorAfter : prefix that was seen before this error occurred curchar : the offending character Note: You can + * customize the lexical error message by modifying this method. + */ + protected static String LexicalErr(boolean EOFSeen, int lexState, int errorLine, int errorColumn, String errorAfter, + int curChar) { + char curChar1 = (char) curChar; + return ("Lexical error at line " + errorLine + ", column " + errorColumn + ". Encountered: " + + (EOFSeen ? " " : + ("\"" + addEscapes(String.valueOf(curChar1)) + "\"") + " (" + (int) curChar + "), ") + + "after : \"" + addEscapes(errorAfter) + "\""); + } + + /** + * You can also modify the body of this method to customize your error messages. For example, cases like + * LOOP_DETECTED and INVALID_LEXICAL_STATE are not of end-users concern, so you can return something like : + * "Internal Error : Please file a bug report .... " from this method for such cases in the release version of your + * parser. + */ + public String getMessage() { + return super.getMessage(); + } + + /* + * Constructors of various flavors follow. + */ + + /** No arg constructor. */ + public TokenMgrError() { + } + + /** Constructor with message and reason. */ + public TokenMgrError(String message, int reason) { + super(message); + errorCode = reason; + } + + /** Full Constructor. */ + public TokenMgrError(boolean EOFSeen, int lexState, int errorLine, int errorColumn, String errorAfter, int curChar, + int reason) { + this(LexicalErr(EOFSeen, lexState, errorLine, errorColumn, errorAfter, curChar), reason); + } } /* JavaCC - OriginalChecksum=7da4e668c47dee63e10c9b008699a2ca (do not edit this line) */ diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/log/CaptureLog.java tomcat10-10.1.52/java/org/apache/tomcat/util/log/CaptureLog.java --- tomcat10-10.1.40/java/org/apache/tomcat/util/log/CaptureLog.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/log/CaptureLog.java 2026-01-23 19:33:36.000000000 +0000 @@ -21,8 +21,6 @@ /** * Per Thread System.err and System.out log capture data. - * - * @author Glenn L. Nielsen */ class CaptureLog { diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/log/SystemLogHandler.java tomcat10-10.1.52/java/org/apache/tomcat/util/log/SystemLogHandler.java --- tomcat10-10.1.40/java/org/apache/tomcat/util/log/SystemLogHandler.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/log/SystemLogHandler.java 2026-01-23 19:33:36.000000000 +0000 @@ -25,13 +25,8 @@ import java.util.concurrent.ConcurrentLinkedQueue; /** - * This helper class may be used to do sophisticated redirection of - * System.out and System.err on a per Thread basis. - * A stack is implemented per Thread so that nested startCapture - * and stopCapture can be used. - * - * @author Remy Maucherat - * @author Glenn L. Nielsen + * This helper class may be used to do sophisticated redirection of System.out and System.err on a per Thread basis. A + * stack is implemented per Thread so that nested startCapture and stopCapture can be used. */ public class SystemLogHandler extends PrintStream { @@ -123,6 +118,7 @@ /** * Find PrintStream to which the output must be written to. + * * @return the print stream */ protected PrintStream findStream() { @@ -160,7 +156,7 @@ @Override protected void setError() { - //findStream().setError(); + // findStream().setError(); } @Override @@ -169,8 +165,7 @@ } @Override - public void write(byte[] b) - throws IOException { + public void write(byte[] b) throws IOException { findStream().write(b); } diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/log/UserDataHelper.java tomcat10-10.1.52/java/org/apache/tomcat/util/log/UserDataHelper.java --- tomcat10-10.1.40/java/org/apache/tomcat/util/log/UserDataHelper.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/log/UserDataHelper.java 2026-01-23 19:33:36.000000000 +0000 @@ -19,22 +19,20 @@ import org.apache.juli.logging.Log; /** - * This helper class assists with the logging associated with invalid input - * data. A developer may want all instances of invalid input data logged to - * assist with debugging whereas in production it is likely to be desirable not - * to log anything for invalid data. The following settings may be used: + * This helper class assists with the logging associated with invalid input data. A developer may want all instances of + * invalid input data logged to assist with debugging whereas in production it is likely to be desirable not to log + * anything for invalid data. The following settings may be used: *
        *
      • NOTHING: Log nothing.
      • *
      • DEBUG_ALL: Log all problems at DEBUG log level.
      • - *
      • INFO_THEN_DEBUG: Log first problem at INFO log level and any further - * issues in the following TBD (configurable) seconds at DEBUG level
      • + *
      • INFO_THEN_DEBUG: Log first problem at INFO log level and any further issues in the following TBD (configurable) + * seconds at DEBUG level
      • *
      • INFO_ALL: Log all problems at INFO log level.
      • *
      * By default, INFO_THEN_DEBUG is used with a suppression time of 24 hours. *

      - * NOTE: This class is not completely thread-safe. When using INFO_THEN_DEBUG it - * is possible that several INFO messages will be logged before dropping to - * DEBUG. + * NOTE: This class is not completely thread-safe. When using INFO_THEN_DEBUG it is possible that several INFO messages + * will be logged before dropping to DEBUG. */ public class UserDataHelper { @@ -54,8 +52,7 @@ this.log = log; Config tempConfig; - String configString = System.getProperty( - "org.apache.juli.logging.UserDataHelper.CONFIG"); + String configString = System.getProperty("org.apache.juli.logging.UserDataHelper.CONFIG"); if (configString == null) { tempConfig = Config.INFO_THEN_DEBUG; } else { @@ -68,9 +65,9 @@ } // Default suppression time of 1 day. - suppressionTime = Integer.getInteger( - "org.apache.juli.logging.UserDataHelper.SUPPRESSION_TIME", - 60 * 60 * 24).intValue() * 1000L; + suppressionTime = + Integer.getInteger("org.apache.juli.logging.UserDataHelper.SUPPRESSION_TIME", 60 * 60 * 24).intValue() * + 1000L; if (suppressionTime == 0) { tempConfig = Config.INFO_ALL; @@ -81,12 +78,10 @@ /** - * Returns log mode for the next log message, or null if the - * message should not be logged. - * + * Returns log mode for the next log message, or null if the message should not be logged. *

      - * If INFO_THEN_DEBUG configuration option is enabled, this - * method might change internal state of this object. + * If INFO_THEN_DEBUG configuration option is enabled, this method might change internal state of this + * object. * * @return Log mode, or null */ @@ -110,9 +105,8 @@ /* - * Not completely thread-safe but good enough for this use case. I couldn't - * see a simple enough way to make it completely thread-safe that was not - * likely to compromise performance. + * Not completely thread-safe but good enough for this use case. I couldn't see a simple enough way to make it + * completely thread-safe that was not likely to compromise performance. */ private boolean logAtInfo() { diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/modeler/AttributeInfo.java tomcat10-10.1.52/java/org/apache/tomcat/util/modeler/AttributeInfo.java --- tomcat10-10.1.40/java/org/apache/tomcat/util/modeler/AttributeInfo.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/modeler/AttributeInfo.java 2026-01-23 19:33:36.000000000 +0000 @@ -19,10 +19,9 @@ import javax.management.MBeanAttributeInfo; /** - *

      Internal configuration information for an Attribute - * descriptor.

      - * - * @author Craig R. McClanahan + *

      + * Internal configuration information for an Attribute descriptor. + *

      */ public class AttributeInfo extends FeatureInfo { private static final long serialVersionUID = -2511626862303972143L; @@ -54,7 +53,7 @@ * @return the name of the property getter method, if non-standard. */ public String getGetMethod() { - if(getMethod == null) { + if (getMethod == null) { getMethod = getMethodName(getName(), true, isIs()); } return this.getMethod; @@ -66,8 +65,8 @@ /** * Is this a boolean attribute with an "is" getter? - * @return true if this is a boolean attribute - * with an "is" getter + * + * @return true if this is a boolean attribute with an "is" getter */ public boolean isIs() { return this.is; @@ -80,6 +79,7 @@ /** * Is this attribute readable by management applications? + * * @return true if readable */ public boolean isReadable() { @@ -95,7 +95,7 @@ * @return the name of the property setter method, if non-standard. */ public String getSetMethod() { - if( setMethod == null ) { + if (setMethod == null) { setMethod = getMethodName(getName(), false, false); } return this.setMethod; @@ -107,6 +107,7 @@ /** * Is this attribute writable by management applications? + * * @return true if writable */ public boolean isWriteable() { @@ -121,29 +122,29 @@ /** - * Create and return a ModelMBeanAttributeInfo object that - * corresponds to the attribute described by this instance. + * Create and return a ModelMBeanAttributeInfo object that corresponds to the attribute described by + * this instance. + * * @return the attribute info */ MBeanAttributeInfo createAttributeInfo() { // Return our cached information (if any) if (info == null) { - info = new MBeanAttributeInfo(getName(), getType(), getDescription(), - isReadable(), isWriteable(), false); + info = new MBeanAttributeInfo(getName(), getType(), getDescription(), isReadable(), isWriteable(), false); } - return (MBeanAttributeInfo)info; + return (MBeanAttributeInfo) info; } // -------------------------------------------------------- Private Methods /** - * Create and return the name of a default property getter or setter - * method, according to the specified values. + * Create and return the name of a default property getter or setter method, according to the specified values. * - * @param name Name of the property itself + * @param name Name of the property itself * @param getter Do we want a get method (versus a set method)? - * @param is If returning a getter, do we want the "is" form? + * @param is If returning a getter, do we want the "is" form? + * * @return the method name */ private String getMethodName(String name, boolean getter, boolean is) { diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/modeler/BaseAttributeFilter.java tomcat10-10.1.52/java/org/apache/tomcat/util/modeler/BaseAttributeFilter.java --- tomcat10-10.1.40/java/org/apache/tomcat/util/modeler/BaseAttributeFilter.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/modeler/BaseAttributeFilter.java 2026-01-23 19:33:36.000000000 +0000 @@ -26,12 +26,11 @@ /** - *

      Implementation of NotificationFilter for attribute change - * notifications. This class is used by BaseModelMBean to - * construct attribute change notification event filters when a filter is not - * supplied by the application.

      - * - * @author Craig R. McClanahan + *

      + * Implementation of NotificationFilter for attribute change notifications. This class is used by + * BaseModelMBean to construct attribute change notification event filters when a filter is not supplied by + * the application. + *

      */ public class BaseAttributeFilter implements NotificationFilter { @@ -40,11 +39,10 @@ // ----------------------------------------------------------- Constructors /** - * Construct a new filter that accepts only the specified attribute - * name. + * Construct a new filter that accepts only the specified attribute name. * - * @param name Name of the attribute to be accepted by this filter, or - * null to accept all attribute names + * @param name Name of the attribute to be accepted by this filter, or null to accept all attribute + * names */ public BaseAttributeFilter(String name) { @@ -60,8 +58,8 @@ /** - * The set of attribute names that are accepted by this filter. If this - * list is empty, all attribute names are accepted. + * The set of attribute names that are accepted by this filter. If this list is empty, all attribute names are + * accepted. */ private final Set names = new HashSet<>(); @@ -84,8 +82,7 @@ /** - * Clear all accepted names from this filter, so that it will accept - * all attribute names. + * Clear all accepted names from this filter, so that it will accept all attribute names. */ public void clear() { @@ -97,9 +94,9 @@ /** - * Return the set of names that are accepted by this filter. If this - * filter accepts all attribute names, a zero length array will be - * returned. + * Return the set of names that are accepted by this filter. If this filter accepts all attribute names, a zero + * length array will be returned. + * * @return the array of names */ public String[] getNames() { @@ -112,13 +109,13 @@ /** - *

      Test whether notification enabled for this event. - * Return true if:

      + *

      + * Test whether notification enabled for this event. Return true if: + *

      *
        *
      • This is an attribute change notification
      • - *
      • Either the set of accepted names is empty (implying that all - * attribute names are of interest) or the set of accepted names - * includes the name of the attribute in this notification
      • + *
      • Either the set of accepted names is empty (implying that all attribute names are of interest) or the set of + * accepted names includes the name of the attribute in this notification
      • *
      */ @Override @@ -130,8 +127,7 @@ if (!(notification instanceof AttributeChangeNotification)) { return false; } - AttributeChangeNotification acn = - (AttributeChangeNotification) notification; + AttributeChangeNotification acn = (AttributeChangeNotification) notification; if (!AttributeChangeNotification.ATTRIBUTE_CHANGE.equals(acn.getType())) { return false; } @@ -147,8 +143,7 @@ /** - * Remove an attribute name from the set of names accepted by this - * filter. + * Remove an attribute name from the set of names accepted by this filter. * * @param name Name of the attribute to be removed */ diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/modeler/BaseModelMBean.java tomcat10-10.1.52/java/org/apache/tomcat/util/modeler/BaseModelMBean.java --- tomcat10-10.1.40/java/org/apache/tomcat/util/modeler/BaseModelMBean.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/modeler/BaseModelMBean.java 2026-01-23 19:33:36.000000000 +0000 @@ -70,43 +70,37 @@ */ /** - *

      Basic implementation of the DynamicMBean interface, which - * supports the minimal requirements of the interface contract.

      - * - *

      This can be used directly to wrap an existing java bean, or inside - * a mlet or anywhere an MBean would be used. + *

      + * Basic implementation of the DynamicMBean interface, which supports the minimal requirements of the + * interface contract. + *

      + *

      + * This can be used directly to wrap an existing java bean, or inside a mlet or anywhere an MBean would be used. *

      * Limitations: *

        - *
      • Only managed resources of type objectReference are - * supported.
      • - *
      • Caching of attribute values and operation results is not supported. - * All calls to invoke() are immediately executed.
      • + *
      • Only managed resources of type objectReference are supported.
      • + *
      • Caching of attribute values and operation results is not supported. All calls to invoke() are + * immediately executed.
      • *
      • Persistence of MBean attributes and operations is not supported.
      • - *
      • All classes referenced as attribute types, operation parameters, or - * operation return values must be one of the following: - *
          - *
        • One of the Java primitive types (boolean, byte, char, double, - * float, integer, long, short). Corresponding value will be wrapped - * in the appropriate wrapper class automatically.
        • - *
        • Operations that return no value should declare a return type of - * void.
        • - *
        + *
      • All classes referenced as attribute types, operation parameters, or operation return values must be one of the + * following: + *
          + *
        • One of the Java primitive types (boolean, byte, char, double, float, integer, long, short). Corresponding value + * will be wrapped in the appropriate wrapper class automatically.
        • + *
        • Operations that return no value should declare a return type of void.
        • + *
        *
      • Attribute caching is not supported
      • *
      - * - * @author Craig R. McClanahan - * @author Costin Manolache */ -public class BaseModelMBean implements DynamicMBean, MBeanRegistration, - ModelMBeanNotificationBroadcaster { +public class BaseModelMBean implements DynamicMBean, MBeanRegistration, ModelMBeanNotificationBroadcaster { private static final Log log = LogFactory.getLog(BaseModelMBean.class); private static final StringManager sm = StringManager.getManager(BaseModelMBean.class); // ----------------------------------------------------- Instance Variables - protected ObjectName oname=null; + protected ObjectName oname = null; /** * Notification broadcaster for attribute changes. @@ -135,34 +129,31 @@ protected String resourceType = null; // key: operation val: invoke method - //private Hashtable invokeAttMap=new Hashtable(); + // private Hashtable invokeAttMap=new Hashtable(); @Override - public Object getAttribute(String name) - throws AttributeNotFoundException, MBeanException, - ReflectionException { + public Object getAttribute(String name) throws AttributeNotFoundException, MBeanException, ReflectionException { // Validate the input parameters if (name == null) { - throw new RuntimeOperationsException - (new IllegalArgumentException(sm.getString("baseModelMBean.nullAttributeName")), - sm.getString("baseModelMBean.nullAttributeName")); + throw new RuntimeOperationsException( + new IllegalArgumentException(sm.getString("baseModelMBean.nullAttributeName")), + sm.getString("baseModelMBean.nullAttributeName")); } - if( (resource instanceof DynamicMBean) && - ! ( resource instanceof BaseModelMBean )) { - return ((DynamicMBean)resource).getAttribute(name); + if ((resource instanceof DynamicMBean) && !(resource instanceof BaseModelMBean)) { + return ((DynamicMBean) resource).getAttribute(name); } - Method m=managedBean.getGetter(name, this, resource); + Method m = managedBean.getGetter(name, this, resource); Object result; try { Class declaring = m.getDeclaringClass(); // workaround for catalina weird mbeans - the declaring class is BaseModelMBean. // but this is the catalina class. - if( declaring.isAssignableFrom(this.getClass()) ) { - result = m.invoke(this, NO_ARGS_PARAM ); + if (declaring.isAssignableFrom(this.getClass())) { + result = m.invoke(this, NO_ARGS_PARAM); } else { - result = m.invoke(resource, NO_ARGS_PARAM ); + result = m.invoke(resource, NO_ARGS_PARAM); } } catch (InvocationTargetException e) { Throwable t = e.getTargetException(); @@ -170,18 +161,15 @@ t = e; } if (t instanceof RuntimeException) { - throw new RuntimeOperationsException - ((RuntimeException) t, sm.getString("baseModelMBean.invokeError", name)); + throw new RuntimeOperationsException((RuntimeException) t, + sm.getString("baseModelMBean.invokeError", name)); } else if (t instanceof Error) { - throw new RuntimeErrorException - ((Error) t, sm.getString("baseModelMBean.invokeError", name)); + throw new RuntimeErrorException((Error) t, sm.getString("baseModelMBean.invokeError", name)); } else { - throw new MBeanException - (e, sm.getString("baseModelMBean.invokeError", name)); + throw new MBeanException(e, sm.getString("baseModelMBean.invokeError", name)); } } catch (Exception e) { - throw new MBeanException - (e, sm.getString("baseModelMBean.invokeError", name)); + throw new MBeanException(e, sm.getString("baseModelMBean.invokeError", name)); } // Return the results of this method invocation @@ -194,9 +182,9 @@ // Validate the input parameters if (names == null) { - throw new RuntimeOperationsException - (new IllegalArgumentException(sm.getString("baseModelMBean.nullAttributeNameList")), - sm.getString("baseModelMBean.nullAttributeNameList")); + throw new RuntimeOperationsException( + new IllegalArgumentException(sm.getString("baseModelMBean.nullAttributeNameList")), + sm.getString("baseModelMBean.nullAttributeNameList")); } // Prepare our response, eating all exceptions @@ -228,27 +216,25 @@ /** * {@inheritDoc} - *

      IMPLEMENTATION NOTE - This implementation will - * attempt to invoke this method on the MBean itself, or (if not - * available) on the managed resource object associated with this - * MBean.

      + *

      + * IMPLEMENTATION NOTE - This implementation will attempt to invoke this method on the MBean + * itself, or (if not available) on the managed resource object associated with this MBean. + *

      */ @Override - public Object invoke(String name, Object[] params, String[] signature) - throws MBeanException, ReflectionException { - if ((resource instanceof DynamicMBean) && - ! (resource instanceof BaseModelMBean)) { - return ((DynamicMBean)resource).invoke(name, params, signature); + public Object invoke(String name, Object[] params, String[] signature) throws MBeanException, ReflectionException { + if ((resource instanceof DynamicMBean) && !(resource instanceof BaseModelMBean)) { + return ((DynamicMBean) resource).invoke(name, params, signature); } // Validate the input parameters if (name == null) { - throw new RuntimeOperationsException - (new IllegalArgumentException(sm.getString("baseModelMBean.nullMethodName")), - sm.getString("baseModelMBean.nullMethodName")); + throw new RuntimeOperationsException( + new IllegalArgumentException(sm.getString("baseModelMBean.nullMethodName")), + sm.getString("baseModelMBean.nullMethodName")); } - if( log.isTraceEnabled()) { + if (log.isTraceEnabled()) { log.trace("Invoke " + name); } @@ -257,31 +243,28 @@ // Invoke the selected method on the appropriate object Object result; try { - if (method.getDeclaringClass().isAssignableFrom( this.getClass())) { + if (method.getDeclaringClass().isAssignableFrom(this.getClass())) { result = method.invoke(this, params); } else { result = method.invoke(resource, params); } } catch (InvocationTargetException e) { Throwable t = e.getTargetException(); - log.error(sm.getString("baseModelMBean.invokeError", name), t ); + log.error(sm.getString("baseModelMBean.invokeError", name), t); if (t == null) { t = e; } if (t instanceof RuntimeException) { - throw new RuntimeOperationsException - ((RuntimeException) t, sm.getString("baseModelMBean.invokeError", name)); + throw new RuntimeOperationsException((RuntimeException) t, + sm.getString("baseModelMBean.invokeError", name)); } else if (t instanceof Error) { - throw new RuntimeErrorException - ((Error) t, sm.getString("baseModelMBean.invokeError", name)); + throw new RuntimeErrorException((Error) t, sm.getString("baseModelMBean.invokeError", name)); } else { - throw new MBeanException - ((Exception)t, sm.getString("baseModelMBean.invokeError", name)); + throw new MBeanException((Exception) t, sm.getString("baseModelMBean.invokeError", name)); } } catch (Exception e) { - log.error(sm.getString("baseModelMBean.invokeError", name), e ); - throw new MBeanException - (e, sm.getString("baseModelMBean.invokeError", name)); + log.error(sm.getString("baseModelMBean.invokeError", name), e); + throw new MBeanException(e, sm.getString("baseModelMBean.invokeError", name)); } // Return the results of this method invocation @@ -289,8 +272,7 @@ } - static Class getAttributeClass(String signature) - throws ReflectionException { + static Class getAttributeClass(String signature) throws ReflectionException { if (signature.equals(Boolean.TYPE.getName())) { return Boolean.TYPE; } else if (signature.equals(Byte.TYPE.getName())) { @@ -310,10 +292,10 @@ } else { try { ClassLoader cl = Thread.currentThread().getContextClassLoader(); - if (cl!=null) { + if (cl != null) { return cl.loadClass(signature); } - } catch(ClassNotFoundException e) { + } catch (ClassNotFoundException ignore) { // Ignore } try { @@ -326,16 +308,14 @@ @Override public void setAttribute(Attribute attribute) - throws AttributeNotFoundException, MBeanException, - ReflectionException { - if( log.isTraceEnabled() ) { - log.trace("Setting attribute " + this + " " + attribute ); + throws AttributeNotFoundException, MBeanException, ReflectionException { + if (log.isTraceEnabled()) { + log.trace("Setting attribute " + this + " " + attribute); } - if( (resource instanceof DynamicMBean) && - ! ( resource instanceof BaseModelMBean )) { + if ((resource instanceof DynamicMBean) && !(resource instanceof BaseModelMBean)) { try { - ((DynamicMBean)resource).setAttribute(attribute); + ((DynamicMBean) resource).setAttribute(attribute); } catch (InvalidAttributeValueException e) { throw new MBeanException(e); } @@ -344,28 +324,28 @@ // Validate the input parameters if (attribute == null) { - throw new RuntimeOperationsException - (new IllegalArgumentException(sm.getString("baseModelMBean.nullAttribute")), - sm.getString("baseModelMBean.nullAttribute")); + throw new RuntimeOperationsException( + new IllegalArgumentException(sm.getString("baseModelMBean.nullAttribute")), + sm.getString("baseModelMBean.nullAttribute")); } String name = attribute.getName(); Object value = attribute.getValue(); if (name == null) { - throw new RuntimeOperationsException - (new IllegalArgumentException(sm.getString("baseModelMBean.nullAttributeName")), - sm.getString("baseModelMBean.nullAttributeName")); + throw new RuntimeOperationsException( + new IllegalArgumentException(sm.getString("baseModelMBean.nullAttributeName")), + sm.getString("baseModelMBean.nullAttributeName")); } - Object oldValue=null; - //if( getAttMap.get(name) != null ) - // oldValue=getAttribute( name ); + Object oldValue = null; + // if( getAttMap.get(name) != null ) + // oldValue=getAttribute( name ); - Method m=managedBean.getSetter(name,this,resource); + Method m = managedBean.getSetter(name, this, resource); try { - if( m.getDeclaringClass().isAssignableFrom( this.getClass()) ) { + if (m.getDeclaringClass().isAssignableFrom(this.getClass())) { m.invoke(this, value); } else { m.invoke(resource, value); @@ -376,36 +356,32 @@ t = e; } if (t instanceof RuntimeException) { - throw new RuntimeOperationsException - ((RuntimeException) t, sm.getString("baseModelMBean.invokeError", name)); + throw new RuntimeOperationsException((RuntimeException) t, + sm.getString("baseModelMBean.invokeError", name)); } else if (t instanceof Error) { - throw new RuntimeErrorException - ((Error) t, sm.getString("baseModelMBean.invokeError", name)); + throw new RuntimeErrorException((Error) t, sm.getString("baseModelMBean.invokeError", name)); } else { - throw new MBeanException - (e, sm.getString("baseModelMBean.invokeError", name)); + throw new MBeanException(e, sm.getString("baseModelMBean.invokeError", name)); } } catch (Exception e) { - log.error(sm.getString("baseModelMBean.invokeError", name) , e ); - throw new MBeanException - (e, sm.getString("baseModelMBean.invokeError", name)); + log.error(sm.getString("baseModelMBean.invokeError", name), e); + throw new MBeanException(e, sm.getString("baseModelMBean.invokeError", name)); } try { - sendAttributeChangeNotification(new Attribute( name, oldValue), - attribute); - } catch(Exception ex) { - log.error(sm.getString("baseModelMBean.notificationError", name), ex); - } - //attributes.put( name, value ); -// if( source != null ) { -// // this mbean is associated with a source - maybe we want to persist -// source.updateField(oname, name, value); -// } + sendAttributeChangeNotification(new Attribute(name, oldValue), attribute); + } catch (Exception e) { + log.error(sm.getString("baseModelMBean.notificationError", name), e); + } + // attributes.put( name, value ); + // if( source != null ) { + // // this mbean is associated with a source - maybe we want to persist + // source.updateField(oname, name, value); + // } } @Override public String toString() { - if( resource==null ) { + if (resource == null) { return "BaseModelMbean[" + resourceType + "]"; } return resource.toString(); @@ -428,7 +404,7 @@ names[n++] = item.getName(); try { setAttribute(item); - } catch (Exception e) { + } catch (Exception ignore) { // Ignore all exceptions } } @@ -442,27 +418,24 @@ /** - * Get the instance handle of the object against which we execute - * all methods in this ModelMBean management interface. + * Get the instance handle of the object against which we execute all methods in this ModelMBean management + * interface. * * @return the backend managed object - * @exception InstanceNotFoundException if the managed resource object - * cannot be found - * @exception InvalidTargetObjectTypeException if the managed resource - * object is of the wrong type - * @exception MBeanException if the initializer of the object throws - * an exception - * @exception RuntimeOperationsException if the managed resource or the - * resource type is null or invalid + * + * @exception InstanceNotFoundException if the managed resource object cannot be found + * @exception InvalidTargetObjectTypeException if the managed resource object is of the wrong type + * @exception MBeanException if the initializer of the object throws an exception + * @exception RuntimeOperationsException if the managed resource or the resource type is null or + * invalid */ - public Object getManagedResource() - throws InstanceNotFoundException, InvalidTargetObjectTypeException, - MBeanException, RuntimeOperationsException { + public Object getManagedResource() throws InstanceNotFoundException, InvalidTargetObjectTypeException, + MBeanException, RuntimeOperationsException { if (resource == null) { - throw new RuntimeOperationsException - (new IllegalArgumentException(sm.getString("baseModelMBean.nullResource")), - sm.getString("baseModelMBean.nullResource")); + throw new RuntimeOperationsException( + new IllegalArgumentException(sm.getString("baseModelMBean.nullResource")), + sm.getString("baseModelMBean.nullResource")); } return resource; @@ -471,61 +444,36 @@ /** - * Set the instance handle of the object against which we will execute - * all methods in this ModelMBean management interface. - * The caller can provide the mbean instance or the object name to - * the resource, if needed. + * Set the instance handle of the object against which we will execute all methods in this ModelMBean management + * interface. The caller can provide the mbean instance or the object name to the resource, if needed. * * @param resource The resource object to be managed - * @param type The type of reference for the managed resource - * ("ObjectReference", "Handle", "IOR", "EJBHandle", or - * "RMIReference") + * @param type The type of reference for the managed resource ("ObjectReference", "Handle", "IOR", "EJBHandle", + * or "RMIReference") * - * @exception InstanceNotFoundException if the managed resource object - * cannot be found - * @exception MBeanException if the initializer of the object throws - * an exception - * @exception RuntimeOperationsException if the managed resource or the - * resource type is null or invalid + * @exception InstanceNotFoundException if the managed resource object cannot be found + * @exception MBeanException if the initializer of the object throws an exception + * @exception RuntimeOperationsException if the managed resource or the resource type is null or + * invalid */ public void setManagedResource(Object resource, String type) - throws InstanceNotFoundException, - MBeanException, RuntimeOperationsException - { + throws InstanceNotFoundException, MBeanException, RuntimeOperationsException { if (resource == null) { - throw new RuntimeOperationsException - (new IllegalArgumentException(sm.getString("baseModelMBean.nullResource")), - sm.getString("baseModelMBean.nullResource")); + throw new RuntimeOperationsException( + new IllegalArgumentException(sm.getString("baseModelMBean.nullResource")), + sm.getString("baseModelMBean.nullResource")); } -// if (!"objectreference".equalsIgnoreCase(type)) -// throw new InvalidTargetObjectTypeException(type); - this.resource = resource; this.resourceType = resource.getClass().getName(); - -// // Make the resource aware of the model mbean. -// try { -// Method m=resource.getClass().getMethod("setModelMBean", -// new Class[] {ModelMBean.class}); -// if( m!= null ) { -// m.invoke(resource, new Object[] {this}); -// } -// } catch( NoSuchMethodException t ) { -// // ignore -// } catch( Throwable t ) { -// log.error( "Can't set model mbean ", t ); -// } } // ------------------------------ ModelMBeanNotificationBroadcaster Methods - @Override - public void addAttributeChangeNotificationListener - (NotificationListener listener, String name, Object handback) - throws IllegalArgumentException { + public void addAttributeChangeNotificationListener(NotificationListener listener, String name, Object handback) + throws IllegalArgumentException { if (listener == null) { throw new IllegalArgumentException(sm.getString("baseModelMBean.nullListener")); @@ -534,21 +482,19 @@ attributeBroadcaster = new BaseNotificationBroadcaster(); } - if( log.isTraceEnabled() ) { + if (log.isTraceEnabled()) { log.trace("addAttributeNotificationListener " + listener); } BaseAttributeFilter filter = new BaseAttributeFilter(name); - attributeBroadcaster.addNotificationListener - (listener, filter, handback); + attributeBroadcaster.addNotificationListener(listener, filter, handback); } @Override - public void removeAttributeChangeNotificationListener - (NotificationListener listener, String name) - throws ListenerNotFoundException { + public void removeAttributeChangeNotificationListener(NotificationListener listener, String name) + throws ListenerNotFoundException { if (listener == null) { throw new IllegalArgumentException(sm.getString("baseModelMBean.nullListener")); @@ -563,21 +509,19 @@ @Override - public void sendAttributeChangeNotification - (AttributeChangeNotification notification) - throws MBeanException, RuntimeOperationsException { + public void sendAttributeChangeNotification(AttributeChangeNotification notification) + throws MBeanException, RuntimeOperationsException { if (notification == null) { - throw new RuntimeOperationsException - (new IllegalArgumentException(sm.getString("baseModelMBean.nullNotification")), - sm.getString("baseModelMBean.nullNotification")); + throw new RuntimeOperationsException( + new IllegalArgumentException(sm.getString("baseModelMBean.nullNotification")), + sm.getString("baseModelMBean.nullNotification")); } - if (attributeBroadcaster == null) - { + if (attributeBroadcaster == null) { return; // This means there are no registered listeners } - if( log.isTraceEnabled() ) { - log.trace( "AttributeChangeNotification " + notification ); + if (log.isTraceEnabled()) { + log.trace("AttributeChangeNotification " + notification); } attributeBroadcaster.sendNotification(notification); @@ -585,9 +529,8 @@ @Override - public void sendAttributeChangeNotification - (Attribute oldValue, Attribute newValue) - throws MBeanException, RuntimeOperationsException { + public void sendAttributeChangeNotification(Attribute oldValue, Attribute newValue) + throws MBeanException, RuntimeOperationsException { // Calculate the class name for the change notification String type; @@ -595,33 +538,26 @@ type = newValue.getValue().getClass().getName(); } else if (oldValue.getValue() != null) { type = oldValue.getValue().getClass().getName(); - } - else { - return; // Old and new are both null == no change + } else { + return; // Old and new are both null == no change } - AttributeChangeNotification notification = - new AttributeChangeNotification - (this, 1, System.currentTimeMillis(), - "Attribute value has changed", - oldValue.getName(), type, - oldValue.getValue(), newValue.getValue()); + AttributeChangeNotification notification = new AttributeChangeNotification(this, 1, System.currentTimeMillis(), + "Attribute value has changed", oldValue.getName(), type, oldValue.getValue(), newValue.getValue()); sendAttributeChangeNotification(notification); } @Override - public void sendNotification(Notification notification) - throws MBeanException, RuntimeOperationsException { + public void sendNotification(Notification notification) throws MBeanException, RuntimeOperationsException { if (notification == null) { - throw new RuntimeOperationsException - (new IllegalArgumentException(sm.getString("baseModelMBean.nullNotification")), - sm.getString("baseModelMBean.nullNotification")); + throw new RuntimeOperationsException( + new IllegalArgumentException(sm.getString("baseModelMBean.nullNotification")), + sm.getString("baseModelMBean.nullNotification")); } - if (generalBroadcaster == null) - { + if (generalBroadcaster == null) { return; // This means there are no registered listeners } generalBroadcaster.sendNotification(notification); @@ -630,16 +566,14 @@ @Override - public void sendNotification(String message) - throws MBeanException, RuntimeOperationsException { + public void sendNotification(String message) throws MBeanException, RuntimeOperationsException { if (message == null) { - throw new RuntimeOperationsException - (new IllegalArgumentException(sm.getString("baseModelMBean.nullMessage")), - sm.getString("baseModelMBean.nullMessage")); + throw new RuntimeOperationsException( + new IllegalArgumentException(sm.getString("baseModelMBean.nullMessage")), + sm.getString("baseModelMBean.nullMessage")); } - Notification notification = new Notification - ("jmx.modelmbean.generic", this, 1, message); + Notification notification = new Notification("jmx.modelmbean.generic", this, 1, message); sendNotification(notification); } @@ -649,24 +583,21 @@ @Override - public void addNotificationListener(NotificationListener listener, - NotificationFilter filter, - Object handback) - throws IllegalArgumentException { + public void addNotificationListener(NotificationListener listener, NotificationFilter filter, Object handback) + throws IllegalArgumentException { if (listener == null) { throw new IllegalArgumentException(sm.getString("baseModelMBean.nullListener")); } - if( log.isTraceEnabled() ) { + if (log.isTraceEnabled()) { log.trace("addNotificationListener " + listener); } if (generalBroadcaster == null) { generalBroadcaster = new BaseNotificationBroadcaster(); } - generalBroadcaster.addNotificationListener - (listener, filter, handback); + generalBroadcaster.addNotificationListener(listener, filter, handback); // We'll send the attribute change notifications to all listeners ( who care ) // The normal filtering can be used. @@ -676,12 +607,11 @@ attributeBroadcaster = new BaseNotificationBroadcaster(); } - if( log.isTraceEnabled() ) { + if (log.isTraceEnabled()) { log.trace("addAttributeNotificationListener " + listener); } - attributeBroadcaster.addNotificationListener - (listener, filter, handback); + attributeBroadcaster.addNotificationListener(listener, filter, handback); } @@ -690,35 +620,30 @@ // Acquire the set of application notifications MBeanNotificationInfo[] current = getMBeanInfo().getNotifications(); - MBeanNotificationInfo[] response = - new MBeanNotificationInfo[current.length + 2]; - // Descriptor descriptor = null; + MBeanNotificationInfo[] response = new MBeanNotificationInfo[current.length + 2]; + // Descriptor descriptor = null; // Fill in entry for general notifications -// descriptor = new DescriptorSupport -// (new String[] { "name=GENERIC", -// "descriptorType=notification", -// "log=T", -// "severity=5", -// "displayName=jmx.modelmbean.generic" }); - response[0] = new MBeanNotificationInfo - (new String[] { "jmx.modelmbean.generic" }, - "GENERIC", - "Text message notification from the managed resource"); - //descriptor); + // descriptor = new DescriptorSupport + // (new String[] { "name=GENERIC", + // "descriptorType=notification", + // "log=T", + // "severity=5", + // "displayName=jmx.modelmbean.generic" }); + response[0] = new MBeanNotificationInfo(new String[] { "jmx.modelmbean.generic" }, "GENERIC", + "Text message notification from the managed resource"); + // descriptor); // Fill in entry for attribute change notifications -// descriptor = new DescriptorSupport -// (new String[] { "name=ATTRIBUTE_CHANGE", -// "descriptorType=notification", -// "log=T", -// "severity=5", -// "displayName=jmx.attribute.change" }); - response[1] = new MBeanNotificationInfo - (new String[] { "jmx.attribute.change" }, - "ATTRIBUTE_CHANGE", - "Observed MBean attribute value has changed"); - //descriptor); + // descriptor = new DescriptorSupport + // (new String[] { "name=ATTRIBUTE_CHANGE", + // "descriptorType=notification", + // "log=T", + // "severity=5", + // "displayName=jmx.attribute.change" }); + response[1] = new MBeanNotificationInfo(new String[] { "jmx.attribute.change" }, "ATTRIBUTE_CHANGE", + "Observed MBean attribute value has changed"); + // descriptor); // Copy remaining notifications as reported by the application System.arraycopy(current, 0, response, 2, current.length); @@ -728,8 +653,7 @@ @Override - public void removeNotificationListener(NotificationListener listener) - throws ListenerNotFoundException { + public void removeNotificationListener(NotificationListener listener) throws ListenerNotFoundException { if (listener == null) { throw new IllegalArgumentException(sm.getString("baseModelMBean.nullListener")); @@ -742,7 +666,7 @@ if (attributeBroadcaster != null) { attributeBroadcaster.removeNotificationListener(listener); } - } + } public String getModelerType() { @@ -769,43 +693,40 @@ } - // -------------------- Registration -------------------- + // -------------------- Registration -------------------- // XXX We can add some method patterns here- like setName() and // setDomain() for code that doesn't implement the Registration @Override - public ObjectName preRegister(MBeanServer server, - ObjectName name) - throws Exception - { - if( log.isTraceEnabled()) { - log.trace("preRegister " + resource + " " + name ); - } - oname=name; - if( resource instanceof MBeanRegistration ) { - oname = ((MBeanRegistration)resource).preRegister(server, name ); + public ObjectName preRegister(MBeanServer server, ObjectName name) throws Exception { + if (log.isTraceEnabled()) { + log.trace("preRegister " + resource + " " + name); + } + oname = name; + if (resource instanceof MBeanRegistration) { + oname = ((MBeanRegistration) resource).preRegister(server, name); } return oname; } @Override public void postRegister(Boolean registrationDone) { - if( resource instanceof MBeanRegistration ) { - ((MBeanRegistration)resource).postRegister(registrationDone); + if (resource instanceof MBeanRegistration) { + ((MBeanRegistration) resource).postRegister(registrationDone); } } @Override public void preDeregister() throws Exception { - if( resource instanceof MBeanRegistration ) { - ((MBeanRegistration)resource).preDeregister(); + if (resource instanceof MBeanRegistration) { + ((MBeanRegistration) resource).preDeregister(); } } @Override public void postDeregister() { - if( resource instanceof MBeanRegistration ) { - ((MBeanRegistration)resource).postDeregister(); + if (resource instanceof MBeanRegistration) { + ((MBeanRegistration) resource).postDeregister(); } } } diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/modeler/BaseNotificationBroadcaster.java tomcat10-10.1.52/java/org/apache/tomcat/util/modeler/BaseNotificationBroadcaster.java --- tomcat10-10.1.40/java/org/apache/tomcat/util/modeler/BaseNotificationBroadcaster.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/modeler/BaseNotificationBroadcaster.java 2026-01-23 19:33:36.000000000 +0000 @@ -28,12 +28,8 @@ /** - * Implementation of NotificationBroadcaster for attribute - * change notifications. This class is used by BaseModelMBean to - * handle notifications of attribute change events to interested listeners. - * - * @author Craig R. McClanahan - * @author Costin Manolache + * Implementation of NotificationBroadcaster for attribute change notifications. This class is used by + * BaseModelMBean to handle notifications of attribute change events to interested listeners. */ public class BaseNotificationBroadcaster implements NotificationBroadcaster { @@ -46,11 +42,9 @@ /** - * The set of registered BaseNotificationBroadcasterEntry - * entries. + * The set of registered BaseNotificationBroadcasterEntry entries. */ - final ArrayList entries = - new ArrayList<>(); + final ArrayList entries = new ArrayList<>(); // --------------------------------------------------------- Public Methods @@ -60,18 +54,15 @@ * Add a notification event listener to this MBean. * * @param listener Listener that will receive event notifications - * @param filter Filter object used to filter event notifications - * actually delivered, or null for no filtering - * @param handback object to be sent along with event - * notifications + * @param filter Filter object used to filter event notifications actually delivered, or null for no + * filtering + * @param handback object to be sent along with event notifications * * @exception IllegalArgumentException if the listener parameter is null */ @Override - public void addNotificationListener(NotificationListener listener, - NotificationFilter filter, - Object handback) - throws IllegalArgumentException { + public void addNotificationListener(NotificationListener listener, NotificationFilter filter, Object handback) + throws IllegalArgumentException { synchronized (entries) { @@ -79,11 +70,9 @@ if (filter instanceof BaseAttributeFilter) { BaseAttributeFilter newFilter = (BaseAttributeFilter) filter; for (BaseNotificationBroadcasterEntry item : entries) { - if ((item.listener == listener) && - (item.filter instanceof BaseAttributeFilter) && - (item.handback == handback)) { - BaseAttributeFilter oldFilter = - (BaseAttributeFilter) item.filter; + if ((item.listener == listener) && (item.filter instanceof BaseAttributeFilter) && + (item.handback == handback)) { + BaseAttributeFilter oldFilter = (BaseAttributeFilter) item.filter; String[] newNames = newFilter.getNames(); String[] oldNames = oldFilter.getNames(); if (newNames.length == 0) { @@ -101,16 +90,14 @@ } // General purpose addition of a new entry - entries.add(new BaseNotificationBroadcasterEntry - (listener, filter, handback)); + entries.add(new BaseNotificationBroadcasterEntry(listener, filter, handback)); } } /** - * Return an MBeanNotificationInfo object describing the - * notifications sent by this MBean. + * Return an MBeanNotificationInfo object describing the notifications sent by this MBean. */ @Override public MBeanNotificationInfo[] getNotificationInfo() { @@ -121,15 +108,12 @@ /** * Remove a notification event listener from this MBean. * - * @param listener The listener to be removed (any and all registrations - * for this listener will be eliminated) + * @param listener The listener to be removed (any and all registrations for this listener will be eliminated) * - * @exception ListenerNotFoundException if this listener is not - * registered in the MBean + * @exception ListenerNotFoundException if this listener is not registered in the MBean */ @Override - public void removeNotificationListener(NotificationListener listener) - throws ListenerNotFoundException { + public void removeNotificationListener(NotificationListener listener) throws ListenerNotFoundException { synchronized (entries) { entries.removeIf(item -> item.listener == listener); @@ -147,8 +131,7 @@ synchronized (entries) { for (BaseNotificationBroadcasterEntry item : entries) { - if ((item.filter != null) && - (!item.filter.isNotificationEnabled(notification))) { + if ((item.filter != null) && (!item.filter.isNotificationEnabled(notification))) { continue; } item.listener.handleNotification(notification, item.handback); @@ -166,9 +149,7 @@ class BaseNotificationBroadcasterEntry { - BaseNotificationBroadcasterEntry(NotificationListener listener, - NotificationFilter filter, - Object handback) { + BaseNotificationBroadcasterEntry(NotificationListener listener, NotificationFilter filter, Object handback) { this.listener = listener; this.filter = filter; this.handback = handback; diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/modeler/FeatureInfo.java tomcat10-10.1.52/java/org/apache/tomcat/util/modeler/FeatureInfo.java --- tomcat10-10.1.40/java/org/apache/tomcat/util/modeler/FeatureInfo.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/modeler/FeatureInfo.java 2026-01-23 19:33:36.000000000 +0000 @@ -23,11 +23,10 @@ /** - *

      Convenience base class for AttributeInfo and - * OperationInfo classes that will be used to collect configuration - * information for the ModelMBean beans exposed for management.

      - * - * @author Craig R. McClanahan + *

      + * Convenience base class for AttributeInfo and OperationInfo classes that will be used to + * collect configuration information for the ModelMBean beans exposed for management. + *

      */ public class FeatureInfo implements Serializable { private static final long serialVersionUID = -911529176124712296L; @@ -55,8 +54,7 @@ /** - * @return the name of this feature, which must be unique among features - * in the same collection. + * @return the name of this feature, which must be unique among features in the same collection. */ public String getName() { return this.name; diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/modeler/LocalStrings_fr.properties tomcat10-10.1.52/java/org/apache/tomcat/util/modeler/LocalStrings_fr.properties --- tomcat10-10.1.40/java/org/apache/tomcat/util/modeler/LocalStrings_fr.properties 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/modeler/LocalStrings_fr.properties 2026-01-23 19:33:36.000000000 +0000 @@ -40,6 +40,7 @@ modules.digesterParseError=Erreur lors de l'analyse des données du registre modules.readDescriptorsError=Erreur lors de la lecture des descripteurs +registry.cannotAccessRegistry=L''objet garde [{0}] ne permet pas l''accès au registre registry.createdServer=Le MBeanServer a été crée registry.existingServer=Le MBeanServer existant est utilisé registry.initError=Erreur lors de l''initialisation [{0}] diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/modeler/LocalStrings_ja.properties tomcat10-10.1.52/java/org/apache/tomcat/util/modeler/LocalStrings_ja.properties --- tomcat10-10.1.40/java/org/apache/tomcat/util/modeler/LocalStrings_ja.properties 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/modeler/LocalStrings_ja.properties 2026-01-23 19:33:36.000000000 +0000 @@ -40,6 +40,7 @@ modules.digesterParseError=レジストリデータ解析中のエラー modules.readDescriptorsError=記述子読み取り中のエラー +registry.cannotAccessRegistry=ガードオブジェクト [{0}] はレジストリへのアクセスを許可していません registry.createdServer=作成された MBeanServer registry.existingServer=既存の MBeanServer を使用する registry.initError=[{0}]初期化中のエラー diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/modeler/ManagedBean.java tomcat10-10.1.52/java/org/apache/tomcat/util/modeler/ManagedBean.java --- tomcat10-10.1.40/java/org/apache/tomcat/util/modeler/ManagedBean.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/modeler/ManagedBean.java 2026-01-23 19:33:36.000000000 +0000 @@ -41,10 +41,9 @@ /** - *

      Internal configuration information for a managed bean (MBean) - * descriptor.

      - * - * @author Craig R. McClanahan + *

      + * Internal configuration information for a managed bean (MBean) descriptor. + *

      */ public class ManagedBean implements java.io.Serializable { @@ -58,8 +57,7 @@ private final ReadWriteLock mBeanInfoLock = new ReentrantReadWriteLock(); /** - * The ModelMBeanInfo object that corresponds - * to this ManagedBean instance. + * The ModelMBeanInfo object that corresponds to this ManagedBean instance. */ private transient volatile MBeanInfo info = null; @@ -80,7 +78,7 @@ * Constructor. Will add default attributes. */ public ManagedBean() { - AttributeInfo ai=new AttributeInfo(); + AttributeInfo ai = new AttributeInfo(); ai.setName("modelerType"); ai.setDescription("Type of the modeled resource. Can be set only once"); ai.setType("java.lang.String"); @@ -100,10 +98,9 @@ /** - * The fully qualified name of the Java class of the MBean - * described by this descriptor. If not specified, the standard JMX - * class (javax.management.modelmbean.RequiredModeLMBean) - * will be utilized. + * The fully qualified name of the Java class of the MBean described by this descriptor. If not specified, the + * standard JMX class (javax.management.modelmbean.RequiredModeLMBean) will be utilized. + * * @return the class name */ public String getClassName() { @@ -140,8 +137,8 @@ /** - * @return the (optional) ObjectName domain in which - * this MBean should be registered in the MBeanServer. + * @return the (optional) ObjectName domain in which this MBean should be registered in the + * MBeanServer. */ public String getDomain() { return this.domain; @@ -165,8 +162,8 @@ /** - * @return the name of this managed bean, which must be unique - * among all MBeans managed by a particular MBeans server. + * @return the name of this managed bean, which must be unique among all MBeans managed by a particular MBeans + * server. */ public String getName() { return this.name; @@ -200,9 +197,8 @@ /** - * @return the fully qualified name of the Java class of the resource - * implementation class described by the managed bean described - * by this descriptor. + * @return the fully qualified name of the Java class of the resource implementation class described by the managed + * bean described by this descriptor. */ public String getType() { return this.type; @@ -240,10 +236,8 @@ public void addNotification(NotificationInfo notification) { mBeanInfoLock.writeLock().lock(); try { - NotificationInfo[] results = - new NotificationInfo[notifications.length + 1]; - System.arraycopy(notifications, 0, results, 0, - notifications.length); + NotificationInfo[] results = new NotificationInfo[notifications.length + 1]; + System.arraycopy(notifications, 0, results, 0, notifications.length); results[notifications.length] = notification; notifications = results; this.info = null; @@ -264,30 +258,25 @@ /** - * Create and return a ModelMBean that has been - * preconfigured with the ModelMBeanInfo information - * for this managed bean, and is associated with the specified - * managed object instance. The returned ModelMBean - * will NOT have been registered with our - * MBeanServer. + * Create and return a ModelMBean that has been preconfigured with the ModelMBeanInfo + * information for this managed bean, and is associated with the specified managed object instance. The returned + * ModelMBean will NOT have been registered with our MBeanServer. + * + * @param instance Instanced of the managed object, or null for no associated instance * - * @param instance Instanced of the managed object, or null - * for no associated instance * @return the MBean - * @exception InstanceNotFoundException if the managed resource - * object cannot be found - * @exception MBeanException if a problem occurs instantiating the - * ModelMBean instance + * + * @exception InstanceNotFoundException if the managed resource object cannot be found + * @exception MBeanException if a problem occurs instantiating the ModelMBean instance * @exception RuntimeOperationsException if a JMX runtime error occurs */ public DynamicMBean createMBean(Object instance) - throws InstanceNotFoundException, - MBeanException, RuntimeOperationsException { + throws InstanceNotFoundException, MBeanException, RuntimeOperationsException { BaseModelMBean mbean; // Load the ModelMBean implementation class - if(getClassName().equals(BASE_MBEAN)) { + if (getClassName().equals(BASE_MBEAN)) { // Skip introspection mbean = new BaseModelMBean(); } else { @@ -299,20 +288,19 @@ // Ignore } - if( clazz==null ) { + if (clazz == null) { try { - ClassLoader cl= Thread.currentThread().getContextClassLoader(); - if ( cl != null) { - clazz= cl.loadClass(getClassName()); + ClassLoader cl = Thread.currentThread().getContextClassLoader(); + if (cl != null) { + clazz = cl.loadClass(getClassName()); } } catch (Exception e) { - ex=e; + ex = e; } } - if( clazz==null) { - throw new MBeanException - (ex, sm.getString("managedMBean.cannotLoadClass", getClassName())); + if (clazz == null) { + throw new MBeanException(ex, sm.getString("managedMBean.cannotLoadClass", getClassName())); } try { // Stupid - this will set the default minfo first.... @@ -320,8 +308,7 @@ } catch (RuntimeOperationsException e) { throw e; } catch (Exception e) { - throw new MBeanException - (e, sm.getString("managedMBean.cannotInstantiateClass", getClassName())); + throw new MBeanException(e, sm.getString("managedMBean.cannotInstantiateClass", getClassName())); } } @@ -337,8 +324,8 @@ /** - * Create and return a ModelMBeanInfo object that - * describes this entire managed bean. + * Create and return a ModelMBeanInfo object that describes this entire managed bean. + * * @return the MBean info */ MBeanInfo getMBeanInfo() { @@ -358,35 +345,28 @@ if (info == null) { // Create subordinate information descriptors as required AttributeInfo[] attrs = getAttributes(); - MBeanAttributeInfo[] attributes = - new MBeanAttributeInfo[attrs.length]; + MBeanAttributeInfo[] attributes = new MBeanAttributeInfo[attrs.length]; for (int i = 0; i < attrs.length; i++) { attributes[i] = attrs[i].createAttributeInfo(); } OperationInfo[] opers = getOperations(); - MBeanOperationInfo[] operations = - new MBeanOperationInfo[opers.length]; + MBeanOperationInfo[] operations = new MBeanOperationInfo[opers.length]; for (int i = 0; i < opers.length; i++) { operations[i] = opers[i].createOperationInfo(); } NotificationInfo[] notifs = getNotifications(); - MBeanNotificationInfo[] notifications = - new MBeanNotificationInfo[notifs.length]; + MBeanNotificationInfo[] notifications = new MBeanNotificationInfo[notifs.length]; for (int i = 0; i < notifs.length; i++) { notifications[i] = notifs[i].createNotificationInfo(); } // Construct and return a new ModelMBeanInfo object - info = new MBeanInfo(getClassName(), - getDescription(), - attributes, - new MBeanConstructorInfo[] {}, - operations, - notifications); + info = new MBeanInfo(getClassName(), getDescription(), attributes, new MBeanConstructorInfo[] {}, + operations, notifications); } return info; @@ -445,7 +425,7 @@ try { object = resource; m = object.getClass().getMethod(getMethod, NO_ARGS_PARAM_SIG); - exception=null; + exception = null; } catch (NoSuchMethodException e) { exception = e; } @@ -469,9 +449,9 @@ // Look up the actual operation to be used String setMethod = attrInfo.getSetMethod(); - String argType=attrInfo.getType(); + String argType = attrInfo.getType(); - Class[] signature = new Class[] { BaseModelMBean.getAttributeClass( argType ) }; + Class[] signature = new Class[] { BaseModelMBean.getAttributeClass(argType) }; Object object; NoSuchMethodException exception = null; @@ -485,7 +465,7 @@ try { object = resource; m = object.getClass().getMethod(setMethod, signature); - exception=null; + exception = null; } catch (NoSuchMethodException e) { exception = e; } @@ -516,8 +496,7 @@ // Acquire the ModelMBeanOperationInfo information for // the requested operation - OperationInfo opInfo = - operations.get(createOperationKey(aname, signature)); + OperationInfo opInfo = operations.get(createOperationKey(aname, signature)); if (opInfo == null) { throw new MBeanException(new ServiceNotFoundException(sm.getString("managedMBean.noOperation", aname)), sm.getString("managedMBean.noOperation", aname)); diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/modeler/NoDescriptorRegistry.java tomcat10-10.1.52/java/org/apache/tomcat/util/modeler/NoDescriptorRegistry.java --- tomcat10-10.1.40/java/org/apache/tomcat/util/modeler/NoDescriptorRegistry.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/modeler/NoDescriptorRegistry.java 2026-01-23 19:33:36.000000000 +0000 @@ -45,9 +45,8 @@ import javax.management.loading.ClassLoaderRepository; /** - * An implementation of the MBean registry that effectively disables MBean - * registration. This is typically used when low memory footprint is a primary - * concern. + * An implementation of the MBean registry that effectively disables MBean registration. This is typically used when low + * memory footprint is a primary concern. */ public class NoDescriptorRegistry extends Registry { @@ -56,8 +55,7 @@ @Override - public void registerComponent(final Object bean, final String oname, final String type) - throws Exception { + public void registerComponent(final Object bean, final String oname, final String type) throws Exception { // no-op } @@ -69,8 +67,8 @@ @Override - public void invoke(final List mbeans, final String operation, - final boolean failFirst) throws Exception { + public void invoke(final List mbeans, final String operation, final boolean failFirst) + throws Exception { // no-op } @@ -107,15 +105,14 @@ @Override - public ManagedBean findManagedBean(final Object bean, final Class beanClass, - final String type) throws Exception { + public ManagedBean findManagedBean(final Object bean, final Class beanClass, final String type) + throws Exception { return null; } @Override - public List load(final String sourceType, final Object source, final String param) - throws Exception { + public List load(final String sourceType, final Object source, final String param) throws Exception { return Collections.emptyList(); } @@ -127,8 +124,7 @@ @Override - public void registerComponent(final Object bean, final ObjectName oname, final String type) - throws Exception { + public void registerComponent(final Object bean, final ObjectName oname, final String type) throws Exception { // no-op } @@ -147,49 +143,45 @@ private static class NoJmxMBeanServer implements MBeanServer { @Override - public ObjectInstance createMBean(String className, ObjectName name) - throws ReflectionException, InstanceAlreadyExistsException, - MBeanRegistrationException, NotCompliantMBeanException { + public ObjectInstance createMBean(String className, ObjectName name) throws ReflectionException, + InstanceAlreadyExistsException, MBeanRegistrationException, NotCompliantMBeanException { return null; } @Override public ObjectInstance createMBean(String className, ObjectName name, ObjectName loaderName) - throws ReflectionException, InstanceAlreadyExistsException, - MBeanRegistrationException, NotCompliantMBeanException, InstanceNotFoundException { + throws ReflectionException, InstanceAlreadyExistsException, MBeanRegistrationException, + NotCompliantMBeanException, InstanceNotFoundException { return null; } @Override - public ObjectInstance createMBean(String className, ObjectName name, Object[] params, - String[] signature) throws ReflectionException, InstanceAlreadyExistsException, - MBeanRegistrationException, NotCompliantMBeanException { + public ObjectInstance createMBean(String className, ObjectName name, Object[] params, String[] signature) + throws ReflectionException, InstanceAlreadyExistsException, MBeanRegistrationException, + NotCompliantMBeanException { return null; } @Override - public ObjectInstance createMBean(String className, ObjectName name, ObjectName loaderName, - Object[] params, String[] signature) throws ReflectionException, - InstanceAlreadyExistsException, MBeanRegistrationException, - NotCompliantMBeanException, InstanceNotFoundException { + public ObjectInstance createMBean(String className, ObjectName name, ObjectName loaderName, Object[] params, + String[] signature) throws ReflectionException, InstanceAlreadyExistsException, + MBeanRegistrationException, NotCompliantMBeanException, InstanceNotFoundException { return null; } @Override public ObjectInstance registerMBean(Object object, ObjectName name) - throws InstanceAlreadyExistsException, MBeanRegistrationException, - NotCompliantMBeanException { + throws InstanceAlreadyExistsException, MBeanRegistrationException, NotCompliantMBeanException { return null; } @Override - public void unregisterMBean(ObjectName name) - throws InstanceNotFoundException, MBeanRegistrationException { + public void unregisterMBean(ObjectName name) throws InstanceNotFoundException, MBeanRegistrationException { } @@ -225,8 +217,8 @@ @Override - public Object getAttribute(ObjectName name, String attribute) throws MBeanException, - AttributeNotFoundException, InstanceNotFoundException, ReflectionException { + public Object getAttribute(ObjectName name, String attribute) + throws MBeanException, AttributeNotFoundException, InstanceNotFoundException, ReflectionException { return null; } @@ -239,9 +231,8 @@ @Override - public void setAttribute(ObjectName name, Attribute attribute) - throws InstanceNotFoundException, AttributeNotFoundException, - InvalidAttributeValueException, MBeanException, ReflectionException { + public void setAttribute(ObjectName name, Attribute attribute) throws InstanceNotFoundException, + AttributeNotFoundException, InvalidAttributeValueException, MBeanException, ReflectionException { } @@ -254,8 +245,7 @@ @Override - public Object invoke(ObjectName name, String operationName, Object[] params, - String[] signature) + public Object invoke(ObjectName name, String operationName, Object[] params, String[] signature) throws InstanceNotFoundException, MBeanException, ReflectionException { return null; } @@ -274,15 +264,15 @@ @Override - public void addNotificationListener(ObjectName name, NotificationListener listener, - NotificationFilter filter, Object handback) throws InstanceNotFoundException { + public void addNotificationListener(ObjectName name, NotificationListener listener, NotificationFilter filter, + Object handback) throws InstanceNotFoundException { } @Override - public void addNotificationListener(ObjectName name, ObjectName listener, - NotificationFilter filter, Object handback) throws InstanceNotFoundException { + public void addNotificationListener(ObjectName name, ObjectName listener, NotificationFilter filter, + Object handback) throws InstanceNotFoundException { } @@ -295,9 +285,8 @@ @Override - public void removeNotificationListener(ObjectName name, ObjectName listener, - NotificationFilter filter, Object handback) - throws InstanceNotFoundException, ListenerNotFoundException { + public void removeNotificationListener(ObjectName name, ObjectName listener, NotificationFilter filter, + Object handback) throws InstanceNotFoundException, ListenerNotFoundException { } @@ -325,8 +314,7 @@ @Override - public boolean isInstanceOf(ObjectName name, String className) - throws InstanceNotFoundException { + public boolean isInstanceOf(ObjectName name, String className) throws InstanceNotFoundException { return false; } @@ -352,8 +340,7 @@ @Override - public Object instantiate(String className, ObjectName loaderName, Object[] params, - String[] signature) + public Object instantiate(String className, ObjectName loaderName, Object[] params, String[] signature) throws ReflectionException, MBeanException, InstanceNotFoundException { return null; } @@ -381,8 +368,7 @@ @Override - public ClassLoader getClassLoaderFor(ObjectName mbeanName) - throws InstanceNotFoundException { + public ClassLoader getClassLoaderFor(ObjectName mbeanName) throws InstanceNotFoundException { return null; } diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/modeler/NotificationInfo.java tomcat10-10.1.52/java/org/apache/tomcat/util/modeler/NotificationInfo.java --- tomcat10-10.1.40/java/org/apache/tomcat/util/modeler/NotificationInfo.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/modeler/NotificationInfo.java 2026-01-23 19:33:36.000000000 +0000 @@ -23,10 +23,9 @@ import javax.management.MBeanNotificationInfo; /** - *

      Internal configuration information for a Notification - * descriptor.

      - * - * @author Craig R. McClanahan + *

      + * Internal configuration information for a Notification descriptor. + *

      */ public class NotificationInfo extends FeatureInfo { @@ -36,8 +35,8 @@ /** - * The ModelMBeanNotificationInfo object that corresponds - * to this NotificationInfo instance. + * The ModelMBeanNotificationInfo object that corresponds to this NotificationInfo + * instance. */ transient MBeanNotificationInfo info = null; protected String[] notifTypes = new String[0]; @@ -110,8 +109,9 @@ /** - * Create and return a ModelMBeanNotificationInfo object that - * corresponds to the attribute described by this instance. + * Create and return a ModelMBeanNotificationInfo object that corresponds to the attribute described by + * this instance. + * * @return the notification info */ public MBeanNotificationInfo createNotificationInfo() { @@ -122,11 +122,10 @@ } // Create and return a new information object - info = new MBeanNotificationInfo - (getNotifTypes(), getName(), getDescription()); - //Descriptor descriptor = info.getDescriptor(); - //addFields(descriptor); - //info.setDescriptor(descriptor); + info = new MBeanNotificationInfo(getNotifTypes(), getName(), getDescription()); + // Descriptor descriptor = info.getDescriptor(); + // addFields(descriptor); + // info.setDescriptor(descriptor); return info; } diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/modeler/OperationInfo.java tomcat10-10.1.52/java/org/apache/tomcat/util/modeler/OperationInfo.java --- tomcat10-10.1.40/java/org/apache/tomcat/util/modeler/OperationInfo.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/modeler/OperationInfo.java 2026-01-23 19:33:36.000000000 +0000 @@ -25,10 +25,9 @@ import javax.management.MBeanParameterInfo; /** - *

      Internal configuration information for an Operation - * descriptor.

      - * - * @author Craig R. McClanahan + *

      + * Internal configuration information for an Operation descriptor. + *

      */ public class OperationInfo extends FeatureInfo { @@ -55,9 +54,8 @@ // ------------------------------------------------------------- Properties /** - * @return the "impact" of this operation, which should be - * a (case-insensitive) string value "ACTION", "ACTION_INFO", - * "INFO", or "UNKNOWN". + * @return the "impact" of this operation, which should be a (case-insensitive) string value "ACTION", + * "ACTION_INFO", "INFO", or "UNKNOWN". */ public String getImpact() { return this.impact; @@ -73,8 +71,7 @@ /** - * @return the role of this operation ("getter", "setter", "operation", or - * "constructor"). + * @return the role of this operation ("getter", "setter", "operation", or "constructor"). */ public String getRole() { return this.role; @@ -86,11 +83,10 @@ /** - * @return the fully qualified Java class name of the return type for this - * operation. + * @return the fully qualified Java class name of the return type for this operation. */ public String getReturnType() { - if(type == null) { + if (type == null) { type = "void"; } return type; @@ -138,8 +134,9 @@ /** - * Create and return a ModelMBeanOperationInfo object that - * corresponds to the attribute described by this instance. + * Create and return a ModelMBeanOperationInfo object that corresponds to the attribute described by + * this instance. + * * @return the operation info */ MBeanOperationInfo createOperationInfo() { @@ -156,17 +153,15 @@ impact = MBeanOperationInfo.INFO; } - info = new MBeanOperationInfo(getName(), getDescription(), - getMBeanParameterInfo(), - getReturnType(), impact); + info = new MBeanOperationInfo(getName(), getDescription(), getMBeanParameterInfo(), getReturnType(), + impact); } - return (MBeanOperationInfo)info; + return (MBeanOperationInfo) info; } protected MBeanParameterInfo[] getMBeanParameterInfo() { ParameterInfo[] params = getSignature(); - MBeanParameterInfo[] parameters = - new MBeanParameterInfo[params.length]; + MBeanParameterInfo[] parameters = new MBeanParameterInfo[params.length]; for (int i = 0; i < params.length; i++) { parameters[i] = params[i].createParameterInfo(); } diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/modeler/ParameterInfo.java tomcat10-10.1.52/java/org/apache/tomcat/util/modeler/ParameterInfo.java --- tomcat10-10.1.40/java/org/apache/tomcat/util/modeler/ParameterInfo.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/modeler/ParameterInfo.java 2026-01-23 19:33:36.000000000 +0000 @@ -20,10 +20,9 @@ import javax.management.MBeanParameterInfo; /** - *

      Internal configuration information for a Parameter - * descriptor.

      - * - * @author Craig R. McClanahan + *

      + * Internal configuration information for a Parameter descriptor. + *

      */ public class ParameterInfo extends FeatureInfo { private static final long serialVersionUID = 2222796006787664020L; @@ -38,17 +37,17 @@ } /** - * Create and return a MBeanParameterInfo object that - * corresponds to the parameter described by this instance. + * Create and return a MBeanParameterInfo object that corresponds to the parameter described by this + * instance. + * * @return a parameter info */ public MBeanParameterInfo createParameterInfo() { // Return our cached information (if any) if (info == null) { - info = new MBeanParameterInfo - (getName(), getType(), getDescription()); + info = new MBeanParameterInfo(getName(), getType(), getDescription()); } - return (MBeanParameterInfo)info; + return (MBeanParameterInfo) info; } } diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/modeler/Registry.java tomcat10-10.1.52/java/org/apache/tomcat/util/modeler/Registry.java --- tomcat10-10.1.40/java/org/apache/tomcat/util/modeler/Registry.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/modeler/Registry.java 2026-01-23 19:33:36.000000000 +0000 @@ -43,13 +43,8 @@ import org.apache.tomcat.util.res.StringManager; /** - * Registry for modeler MBeans. - * This is the main entry point into modeler. It provides methods to create and - * manipulate model mbeans and simplify their use. - * This class is itself a mbean. - * - * @author Craig R. McClanahan - * @author Costin Manolache + * Registry for modeler MBeans. This is the main entry point into modeler. It provides methods to create and manipulate + * model mbeans and simplify their use. This class is itself a mbean. */ public class Registry implements RegistryMBean, MBeanRegistration { @@ -62,40 +57,37 @@ // Support for the factory methods /** - * The registry instance created by our factory method the first time it is - * called. + * The registry instance created by our factory method the first time it is called. */ private static Registry registry = null; // Per registry fields /** - * The MBeanServer instance that we will use to register - * management beans. + * The MBeanServer instance that we will use to register management beans. */ private volatile MBeanServer server = null; private final Object serverLock = new Object(); /** - * The set of ManagedBean instances for the beans this registry knows about, - * keyed by name. + * The set of ManagedBean instances for the beans this registry knows about, keyed by name. */ - private Map descriptors = new HashMap<>(); + private Map descriptors = new HashMap<>(); /** * List of managed beans, keyed by class name */ - private Map descriptorsByClass = new HashMap<>(); + private Map descriptorsByClass = new HashMap<>(); // map to avoid duplicated searching or loading descriptors - private Map searchedPaths = new HashMap<>(); + private Map searchedPaths = new HashMap<>(); private Object guard; // Id - small ints to use array access. No reset on stop() // Used for notifications - private final Hashtable> idDomains = new Hashtable<>(); - private final Hashtable ids = new Hashtable<>(); + private final Hashtable> idDomains = new Hashtable<>(); + private final Hashtable ids = new Hashtable<>(); // ----------------------------------------------------------- Constructors @@ -109,13 +101,13 @@ // Factories /** - * Factory method to create (if necessary) and return our - * Registry instance. + * Factory method to create (if necessary) and return our Registry instance. * - * @param key Unused + * @param key Unused * @param guard Prevent access to the registry by untrusted components * * @return the registry + * * @since 1.1 */ public static synchronized Registry getRegistry(Object key, Object guard) { @@ -131,11 +123,12 @@ /** - * Factory method to create (if necessary) and return our - * Registry instance. + * Factory method to create (if necessary) and return our Registry instance. * * @param guard Prevent access to the registry by untrusted components + * * @return the registry + * * @throws IllegalArgumentException if the guard object does not allow access */ public static synchronized Registry getRegistry(Object guard) { @@ -162,8 +155,7 @@ // -------------------- Generic methods -------------------- /** - * Lifecycle method - clean up the registry metadata. Called from - * resetMetadata(). + * Lifecycle method - clean up the registry metadata. Called from resetMetadata(). * * @since 1.1 */ @@ -176,28 +168,21 @@ /** - * Register a bean by creating a modeler mbean and adding it to the - * MBeanServer. - * If metadata is not loaded, we'll look up and read a file named - * "mbeans-descriptors.ser" or "mbeans-descriptors.xml" in the same package - * or parent. - * If the bean is an instance of DynamicMBean. its metadata will be - * converted to a model mbean, and we'll wrap it so modeler services are - * supported. - * If the metadata is still not found, introspection will be used to extract - * it automatically. - * If a mbean is already registered under this name, it'll be first - * unregistered. - * If the component implements MBeanRegistration, the methods will be - * called. If the method has a method "setRegistry" that takes a + * Register a bean by creating a modeler mbean and adding it to the MBeanServer. If metadata is not loaded, we'll + * look up and read a file named "mbeans-descriptors.ser" or "mbeans-descriptors.xml" in the same package or parent. + * If the bean is an instance of DynamicMBean. its metadata will be converted to a model mbean, and we'll wrap it so + * modeler services are supported. If the metadata is still not found, introspection will be used to extract it + * automatically. If a mbean is already registered under this name, it'll be first unregistered. If the component + * implements MBeanRegistration, the methods will be called. If the method has a method "setRegistry" that takes a * RegistryMBean as parameter, it'll be called with the current registry. * - * @param bean Object to be registered + * @param bean Object to be registered * @param oname Name used for registration - * @param type The type of the mbean, as declared in mbeans-descriptors. If - * null, the name of the class will be used. This can be used as - * a hint or by subclasses. + * @param type The type of the mbean, as declared in mbeans-descriptors. If null, the name of the class will be + * used. This can be used as a hint or by subclasses. + * * @throws Exception if a registration error occurred + * * @since 1.1 */ @Override @@ -207,8 +192,7 @@ /** - * Unregister a component. We'll first check if it is registered, and mask - * all errors. This is mostly a helper. + * Unregister a component. We'll first check if it is registered, and mask all errors. This is mostly a helper. * * @param oname Name used for unregistration * @@ -225,18 +209,18 @@ /** - * Invoke an operation on a list of mbeans. Can be used to implement - * lifecycle operations. + * Invoke an operation on a list of mbeans. Can be used to implement lifecycle operations. + * + * @param mbeans list of ObjectName on which we'll invoke the operations + * @param operation Name of the operation ( init, start, stop, etc) + * @param failFirst If false, exceptions will be ignored * - * @param mbeans list of ObjectName on which we'll invoke the operations - * @param operation Name of the operation ( init, start, stop, etc) - * @param failFirst If false, exceptions will be ignored * @throws Exception Error invoking operation + * * @since 1.1 */ @Override - public void invoke(List mbeans, String operation, boolean failFirst) - throws Exception { + public void invoke(List mbeans, String operation, boolean failFirst) throws Exception { if (mbeans == null) { return; @@ -251,11 +235,11 @@ } getMBeanServer().invoke(current, operation, new Object[] {}, new String[] {}); - } catch (Exception t) { + } catch (Exception e) { if (failFirst) { - throw t; + throw e; } - log.info(sm.getString("registry.initError"), t); + log.info(sm.getString("registry.initError"), e); } } } @@ -263,12 +247,13 @@ // -------------------- ID registry -------------------- /** - * Return an int ID for faster access. Will be used for notifications and - * for other operations we want to optimize. + * Return an int ID for faster access. Will be used for notifications and for other operations we want to optimize. * * @param domain Namespace - * @param name Type of the notification + * @param name Type of the notification + * * @return A unique id for the domain:name combination + * * @since 1.1 */ @Override @@ -276,7 +261,7 @@ if (domain == null) { domain = ""; } - Hashtable domainTable = idDomains.computeIfAbsent(domain, k -> new Hashtable<>()); + Hashtable domainTable = idDomains.computeIfAbsent(domain, k -> new Hashtable<>()); if (name == null) { name = ""; } @@ -297,10 +282,10 @@ // methods from 1.0 /** - * Add a new bean metadata to the set of beans known to this registry. This - * is used by internal components. + * Add a new bean metadata to the set of beans known to this registry. This is used by internal components. * * @param bean The managed bean to be added + * * @since 1.0 */ public void addManagedBean(ManagedBean bean) { @@ -313,12 +298,14 @@ /** - * Find and return the managed bean definition for the specified bean name, - * if any; otherwise return null. + * Find and return the managed bean definition for the specified bean name, if any; otherwise return + * null. + * + * @param name Name of the managed bean to be returned. Since 1.1, both short names or the full name of the class + * can be used. * - * @param name Name of the managed bean to be returned. Since 1.1, both - * short names or the full name of the class can be used. * @return the managed bean + * * @since 1.0 */ public ManagedBean findManagedBean(String name) { @@ -336,9 +323,11 @@ /** * Get the type of an attribute of the object, from the metadata. * - * @param oname The bean name + * @param oname The bean name * @param attName The attribute name + * * @return null if metadata about the attribute is not found + * * @since 1.1 */ public String getType(ObjectName oname, String attName) { @@ -346,9 +335,12 @@ MBeanInfo info; try { info = getMBeanServer().getMBeanInfo(oname); - } catch (Exception e) { + } catch (InstanceNotFoundException e) { log.info(sm.getString("registry.noMetadata", oname)); return null; + } catch (Exception e) { + log.warn(sm.getString("registry.noMetadata", oname), e); + return null; } MBeanAttributeInfo[] attInfo = info.getAttributes(); @@ -365,17 +357,21 @@ /** * Find the operation info for a method * - * @param oname The bean name + * @param oname The bean name * @param opName The operation name + * * @return the operation info for the specified operation */ public MBeanOperationInfo getMethodInfo(ObjectName oname, String opName) { MBeanInfo info; try { info = getMBeanServer().getMBeanInfo(oname); - } catch (Exception e) { + } catch (InstanceNotFoundException e) { log.info(sm.getString("registry.noMetadata", oname)); return null; + } catch (Exception e) { + log.warn(sm.getString("registry.noMetadata", oname), e); + return null; } MBeanOperationInfo[] attInfo = info.getOperations(); for (MBeanOperationInfo mBeanOperationInfo : attInfo) { @@ -389,15 +385,16 @@ /** * Find the operation info for a method. * - * @param oname The bean name - * @param opName The operation name + * @param oname The bean name + * @param opName The operation name * @param argCount The number of arguments to the method + * * @return the operation info for the specified operation + * * @throws InstanceNotFoundException If the object name is not bound to an MBean */ public MBeanOperationInfo getMethodInfo(ObjectName oname, String opName, int argCount) - throws InstanceNotFoundException - { + throws InstanceNotFoundException { MBeanInfo info; try { info = getMBeanServer().getMBeanInfo(oname); @@ -409,8 +406,7 @@ } MBeanOperationInfo[] attInfo = info.getOperations(); for (MBeanOperationInfo mBeanOperationInfo : attInfo) { - if (opName.equals(mBeanOperationInfo.getName()) - && argCount == mBeanOperationInfo.getSignature().length) { + if (opName.equals(mBeanOperationInfo.getName()) && argCount == mBeanOperationInfo.getSignature().length) { return mBeanOperationInfo; } } @@ -418,8 +414,8 @@ } /** - * Unregister a component. This is just a helper that avoids exceptions by - * checking if the mbean is already registered + * Unregister a component. This is just a helper that avoids exceptions by checking if the mbean is already + * registered * * @param oname The bean name */ @@ -435,8 +431,7 @@ /** - * Factory method to create (if necessary) and return our - * MBeanServer instance. + * Factory method to create (if necessary) and return our MBeanServer instance. * * @return the MBean server */ @@ -465,14 +460,15 @@ /** * Find or load metadata. * - * @param bean The bean + * @param bean The bean * @param beanClass The bean class - * @param type The registry type + * @param type The registry type + * * @return the managed bean + * * @throws Exception An error occurred */ - public ManagedBean findManagedBean(Object bean, Class beanClass, String type) - throws Exception { + public ManagedBean findManagedBean(Object bean, Class beanClass, String type) throws Exception { if (bean != null && beanClass == null) { beanClass = bean.getClass(); @@ -518,12 +514,12 @@ /** - * Convert a string to object, based on type. Used by several - * components. We could provide some pluggability. It is here to keep things - * consistent and avoid duplication in other tasks + * Convert a string to object, based on type. Used by several components. We could provide some pluggability. It is + * here to keep things consistent and avoid duplication in other tasks * - * @param type Fully qualified class name of the resulting value + * @param type Fully qualified class name of the resulting value * @param value String value to be converted + * * @return Converted value */ public Object convertValue(String type, String value) { @@ -552,9 +548,11 @@ * Load descriptors. * * @param sourceType The source type - * @param source The bean - * @param param A type to load + * @param source The bean + * @param param A type to load + * * @return List of descriptors + * * @throws Exception Error loading descriptors */ public List load(String sourceType, Object source, String param) throws Exception { @@ -606,9 +604,10 @@ /** * Register a component * - * @param bean The bean + * @param bean The bean * @param oname The object name - * @param type The registry type + * @param type The registry type + * * @throws Exception Error registering component */ public void registerComponent(Object bean, ObjectName oname, String type) throws Exception { @@ -639,16 +638,15 @@ } getMBeanServer().registerMBean(mbean, oname); - } catch (Exception ex) { - log.error(sm.getString("registry.registerError", oname), ex); - throw ex; + } catch (Exception e) { + log.error(sm.getString("registry.registerError", oname), e); + throw e; } } /** - * Lookup the component descriptor in the package and in the parent - * packages. + * Lookup the component descriptor in the package and in the parent packages. * * @param packageName The package name * @param classLoader The class loader @@ -677,15 +675,14 @@ searchedPaths.put(packageName, dURL); try { load("MbeansDescriptorsDigesterSource", dURL, null); - } catch (Exception ex) { + } catch (Exception e) { log.error(sm.getString("registry.loadError", dURL)); } } /** - * Lookup the component descriptor in the package and in the parent - * packages. + * Lookup the component descriptor in the package and in the parent packages. */ private void findDescriptor(Class beanClass, String type) { if (type == null) { diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/modeler/RegistryMBean.java tomcat10-10.1.52/java/org/apache/tomcat/util/modeler/RegistryMBean.java --- tomcat10-10.1.40/java/org/apache/tomcat/util/modeler/RegistryMBean.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/modeler/RegistryMBean.java 2026-01-23 19:33:36.000000000 +0000 @@ -22,64 +22,45 @@ import javax.management.ObjectName; /** - * Interface for modeler MBeans. - * This is the main entry point into modeler. It provides methods to create - * and manipulate model mbeans and simplify their use. - * Starting with version 1.1, this is no longer a singleton and the static - * methods are strongly deprecated. In a container environment we can expect - * different applications to use different registries. - * - * @author Craig R. McClanahan - * @author Costin Manolache - * - * @since 1.1 + * Interface for modeler MBeans. This is the main entry point into modeler. It provides methods to create and manipulate + * model mbeans and simplify their use. Starting with version 1.1, this is no longer a singleton and the static methods + * are strongly deprecated. In a container environment we can expect different applications to use different registries. */ public interface RegistryMBean { /** * Invoke an operation on a set of mbeans. * - * @param mbeans List of ObjectNames + * @param mbeans List of ObjectNames * @param operation Operation to perform. Typically "init" "start" "stop" or "destroy" - * @param failFirst Behavior in case of exceptions - if false we'll ignore - * errors + * @param failFirst Behavior in case of exceptions - if false we'll ignore errors + * * @throws Exception Error invoking operation */ - void invoke(List mbeans, String operation, boolean failFirst) - throws Exception; + void invoke(List mbeans, String operation, boolean failFirst) throws Exception; /** - * Register a bean by creating a modeler mbean and adding it to the - * MBeanServer. - * If metadata is not loaded, we'll look up and read a file named - * "mbeans-descriptors.ser" or "mbeans-descriptors.xml" in the same package - * or parent. - * If the bean is an instance of DynamicMBean. it's metadata will be converted - * to a model mbean, and we'll wrap it - so modeler services will be supported - * If the metadata is still not found, introspection will be used to extract - * it automatically. - * If a mbean is already registered under this name, it'll be first - * unregistered. - * If the component implements MBeanRegistration, the methods will be called. - * If the method has a method "setRegistry" that takes a RegistryMBean as - * parameter, it'll be called with the current registry. - * + * Register a bean by creating a modeler mbean and adding it to the MBeanServer. If metadata is not loaded, we'll + * look up and read a file named "mbeans-descriptors.ser" or "mbeans-descriptors.xml" in the same package or parent. + * If the bean is an instance of DynamicMBean. it's metadata will be converted to a model mbean, and we'll wrap it - + * so modeler services will be supported If the metadata is still not found, introspection will be used to extract + * it automatically. If a mbean is already registered under this name, it'll be first unregistered. If the component + * implements MBeanRegistration, the methods will be called. If the method has a method "setRegistry" that takes a + * RegistryMBean as parameter, it'll be called with the current registry. * - * @param bean Object to be registered + * @param bean Object to be registered * @param oname Name used for registration - * @param type The type of the mbean, as declared in mbeans-descriptors. If - * null, the name of the class will be used. This can be used as a hint or - * by subclasses. + * @param type The type of the mbean, as declared in mbeans-descriptors. If null, the name of the class will be + * used. This can be used as a hint or by subclasses. + * * @throws Exception Error registering MBean * * @since 1.1 */ - void registerComponent(Object bean, String oname, String type) - throws Exception; + void registerComponent(Object bean, String oname, String type) throws Exception; /** - * Unregister a component. We'll first check if it is registered, - * and mask all errors. This is mostly a helper. + * Unregister a component. We'll first check if it is registered, and mask all errors. This is mostly a helper. * * @param oname The name used by the bean * @@ -88,22 +69,23 @@ void unregisterComponent(String oname); - /** - * Return an int ID for faster access. Will be used for notifications - * and for other operations we want to optimize. - * - * @param domain Namespace - * @param name Type of the notification - * @return A unique id for the domain:name combination - * @since 1.1 - */ + /** + * Return an int ID for faster access. Will be used for notifications and for other operations we want to optimize. + * + * @param domain Namespace + * @param name Type of the notification + * + * @return A unique id for the domain:name combination + * + * @since 1.1 + */ int getId(String domain, String name); /** - * Reset all metadata cached by this registry. Should be called - * to support reloading. Existing mbeans will not be affected or modified. - * It will be called automatically if the Registry is unregistered. + * Reset all metadata cached by this registry. Should be called to support reloading. Existing mbeans will not be + * affected or modified. It will be called automatically if the Registry is unregistered. + * * @since 1.1 */ void stop(); diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/modeler/modules/MbeansDescriptorsDigesterSource.java tomcat10-10.1.52/java/org/apache/tomcat/util/modeler/modules/MbeansDescriptorsDigesterSource.java --- tomcat10-10.1.40/java/org/apache/tomcat/util/modeler/modules/MbeansDescriptorsDigesterSource.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/modeler/modules/MbeansDescriptorsDigesterSource.java 2026-01-23 19:33:36.000000000 +0000 @@ -29,10 +29,8 @@ import org.apache.tomcat.util.modeler.ManagedBean; import org.apache.tomcat.util.modeler.Registry; -public class MbeansDescriptorsDigesterSource extends ModelerSource -{ - private static final Log log = - LogFactory.getLog(MbeansDescriptorsDigesterSource.class); +public class MbeansDescriptorsDigesterSource extends ModelerSource { + private static final Log log = LogFactory.getLog(MbeansDescriptorsDigesterSource.class); private static final Object dLock = new Object(); private Registry registry; @@ -44,105 +42,68 @@ Digester digester = new Digester(); digester.setNamespaceAware(false); digester.setValidating(false); - URL url = Registry.getRegistry(null).getClass().getResource - ("/org/apache/tomcat/util/modeler/mbeans-descriptors.dtd"); + URL url = Registry.getRegistry(null).getClass() + .getResource("/org/apache/tomcat/util/modeler/mbeans-descriptors.dtd"); if (url != null) { - digester.register - ("-//Apache Software Foundation//DTD Model MBeans Configuration File", - url.toString()); + digester.register("-//Apache Software Foundation//DTD Model MBeans Configuration File", url.toString()); } // Configure the parsing rules - digester.addObjectCreate - ("mbeans-descriptors/mbean", - "org.apache.tomcat.util.modeler.ManagedBean"); - digester.addSetProperties - ("mbeans-descriptors/mbean"); - digester.addSetNext - ("mbeans-descriptors/mbean", - "add", - "java.lang.Object"); - - digester.addObjectCreate - ("mbeans-descriptors/mbean/attribute", - "org.apache.tomcat.util.modeler.AttributeInfo"); - digester.addSetProperties - ("mbeans-descriptors/mbean/attribute"); - digester.addSetNext - ("mbeans-descriptors/mbean/attribute", - "addAttribute", - "org.apache.tomcat.util.modeler.AttributeInfo"); - - digester.addObjectCreate - ("mbeans-descriptors/mbean/notification", - "org.apache.tomcat.util.modeler.NotificationInfo"); - digester.addSetProperties - ("mbeans-descriptors/mbean/notification"); - digester.addSetNext - ("mbeans-descriptors/mbean/notification", - "addNotification", - "org.apache.tomcat.util.modeler.NotificationInfo"); - - digester.addObjectCreate - ("mbeans-descriptors/mbean/notification/descriptor/field", - "org.apache.tomcat.util.modeler.FieldInfo"); - digester.addSetProperties - ("mbeans-descriptors/mbean/notification/descriptor/field"); - digester.addSetNext - ("mbeans-descriptors/mbean/notification/descriptor/field", - "addField", - "org.apache.tomcat.util.modeler.FieldInfo"); - - digester.addCallMethod - ("mbeans-descriptors/mbean/notification/notification-type", - "addNotifType", 0); - - digester.addObjectCreate - ("mbeans-descriptors/mbean/operation", - "org.apache.tomcat.util.modeler.OperationInfo"); - digester.addSetProperties - ("mbeans-descriptors/mbean/operation"); - digester.addSetNext - ("mbeans-descriptors/mbean/operation", - "addOperation", - "org.apache.tomcat.util.modeler.OperationInfo"); - - digester.addObjectCreate - ("mbeans-descriptors/mbean/operation/descriptor/field", - "org.apache.tomcat.util.modeler.FieldInfo"); - digester.addSetProperties - ("mbeans-descriptors/mbean/operation/descriptor/field"); - digester.addSetNext - ("mbeans-descriptors/mbean/operation/descriptor/field", - "addField", - "org.apache.tomcat.util.modeler.FieldInfo"); - - digester.addObjectCreate - ("mbeans-descriptors/mbean/operation/parameter", - "org.apache.tomcat.util.modeler.ParameterInfo"); - digester.addSetProperties - ("mbeans-descriptors/mbean/operation/parameter"); - digester.addSetNext - ("mbeans-descriptors/mbean/operation/parameter", - "addParameter", - "org.apache.tomcat.util.modeler.ParameterInfo"); + digester.addObjectCreate("mbeans-descriptors/mbean", "org.apache.tomcat.util.modeler.ManagedBean"); + digester.addSetProperties("mbeans-descriptors/mbean"); + digester.addSetNext("mbeans-descriptors/mbean", "add", "java.lang.Object"); + + digester.addObjectCreate("mbeans-descriptors/mbean/attribute", "org.apache.tomcat.util.modeler.AttributeInfo"); + digester.addSetProperties("mbeans-descriptors/mbean/attribute"); + digester.addSetNext("mbeans-descriptors/mbean/attribute", "addAttribute", + "org.apache.tomcat.util.modeler.AttributeInfo"); + + digester.addObjectCreate("mbeans-descriptors/mbean/notification", + "org.apache.tomcat.util.modeler.NotificationInfo"); + digester.addSetProperties("mbeans-descriptors/mbean/notification"); + digester.addSetNext("mbeans-descriptors/mbean/notification", "addNotification", + "org.apache.tomcat.util.modeler.NotificationInfo"); + + digester.addObjectCreate("mbeans-descriptors/mbean/notification/descriptor/field", + "org.apache.tomcat.util.modeler.FieldInfo"); + digester.addSetProperties("mbeans-descriptors/mbean/notification/descriptor/field"); + digester.addSetNext("mbeans-descriptors/mbean/notification/descriptor/field", "addField", + "org.apache.tomcat.util.modeler.FieldInfo"); + + digester.addCallMethod("mbeans-descriptors/mbean/notification/notification-type", "addNotifType", 0); + + digester.addObjectCreate("mbeans-descriptors/mbean/operation", "org.apache.tomcat.util.modeler.OperationInfo"); + digester.addSetProperties("mbeans-descriptors/mbean/operation"); + digester.addSetNext("mbeans-descriptors/mbean/operation", "addOperation", + "org.apache.tomcat.util.modeler.OperationInfo"); + + digester.addObjectCreate("mbeans-descriptors/mbean/operation/descriptor/field", + "org.apache.tomcat.util.modeler.FieldInfo"); + digester.addSetProperties("mbeans-descriptors/mbean/operation/descriptor/field"); + digester.addSetNext("mbeans-descriptors/mbean/operation/descriptor/field", "addField", + "org.apache.tomcat.util.modeler.FieldInfo"); + + digester.addObjectCreate("mbeans-descriptors/mbean/operation/parameter", + "org.apache.tomcat.util.modeler.ParameterInfo"); + digester.addSetProperties("mbeans-descriptors/mbean/operation/parameter"); + digester.addSetNext("mbeans-descriptors/mbean/operation/parameter", "addParameter", + "org.apache.tomcat.util.modeler.ParameterInfo"); return digester; } public void setRegistry(Registry reg) { - this.registry=reg; + this.registry = reg; } - public void setSource( Object source ) { - this.source=source; + public void setSource(Object source) { + this.source = source; } @Override - public List loadDescriptors( Registry registry, String type, - Object source) throws Exception { + public List loadDescriptors(Registry registry, String type, Object source) throws Exception { setRegistry(registry); setSource(source); execute(); @@ -157,7 +118,7 @@ InputStream stream = (InputStream) source; List loadedMbeans = new ArrayList<>(); - synchronized(dLock) { + synchronized (dLock) { if (digester == null) { digester = createDigester(); } diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/modeler/modules/MbeansDescriptorsIntrospectionSource.java tomcat10-10.1.52/java/org/apache/tomcat/util/modeler/modules/MbeansDescriptorsIntrospectionSource.java --- tomcat10-10.1.40/java/org/apache/tomcat/util/modeler/modules/MbeansDescriptorsIntrospectionSource.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/modeler/modules/MbeansDescriptorsIntrospectionSource.java 2026-01-23 19:33:36.000000000 +0000 @@ -38,8 +38,7 @@ import org.apache.tomcat.util.modeler.Registry; import org.apache.tomcat.util.res.StringManager; -public class MbeansDescriptorsIntrospectionSource extends ModelerSource -{ +public class MbeansDescriptorsIntrospectionSource extends ModelerSource { private static final Log log = LogFactory.getLog(MbeansDescriptorsIntrospectionSource.class); private static final StringManager sm = StringManager.getManager(MbeansDescriptorsIntrospectionSource.class); @@ -48,7 +47,7 @@ private final List mbeans = new ArrayList<>(); public void setRegistry(Registry reg) { - this.registry=reg; + this.registry = reg; } /** @@ -56,17 +55,16 @@ * * @param type The type */ - public void setType( String type ) { - this.type=type; + public void setType(String type) { + this.type = type; } - public void setSource( Object source ) { - this.source=source; + public void setSource(Object source) { + this.source = source; } @Override - public List loadDescriptors(Registry registry, String type, - Object source) throws Exception { + public List loadDescriptors(Registry registry, String type, Object source) throws Exception { setRegistry(registry); setType(type); setSource(source); @@ -75,65 +73,43 @@ } public void execute() throws Exception { - if( registry==null ) { - registry=Registry.getRegistry(null); + if (registry == null) { + registry = Registry.getRegistry(null); } try { - ManagedBean managed = createManagedBean(registry, null, - (Class)source, type); - if( managed==null ) { + ManagedBean managed = createManagedBean(registry, null, (Class) source, type); + if (managed == null) { return; } - managed.setName( type ); + managed.setName(type); registry.addManagedBean(managed); - } catch( Exception ex ) { - log.error(sm.getString("modules.readDescriptorsError"), ex); + } catch (Exception e) { + log.error(sm.getString("modules.readDescriptorsError"), e); } } - // ------------ Implementation for non-declared introspection classes private static final Map specialMethods = new HashMap<>(); static { - specialMethods.put( "preDeregister", ""); - specialMethods.put( "postDeregister", ""); + specialMethods.put("preDeregister", ""); + specialMethods.put("postDeregister", ""); } - private static final Class[] supportedTypes = new Class[] { - Boolean.class, - Boolean.TYPE, - Byte.class, - Byte.TYPE, - Character.class, - Character.TYPE, - Short.class, - Short.TYPE, - Integer.class, - Integer.TYPE, - Long.class, - Long.TYPE, - Float.class, - Float.TYPE, - Double.class, - Double.TYPE, - String.class, - String[].class, - BigDecimal.class, - BigInteger.class, - ObjectName.class, - Object[].class, - java.io.File.class, - }; + private static final Class[] supportedTypes = new Class[] { Boolean.class, Boolean.TYPE, Byte.class, Byte.TYPE, + Character.class, Character.TYPE, Short.class, Short.TYPE, Integer.class, Integer.TYPE, Long.class, + Long.TYPE, Float.class, Float.TYPE, Double.class, Double.TYPE, String.class, String[].class, + BigDecimal.class, BigInteger.class, ObjectName.class, Object[].class, java.io.File.class, }; /** - * Check if this class is one of the supported types. - * If the class is supported, returns true. Otherwise, - * returns false. + * Check if this class is one of the supported types. If the class is supported, returns true. Otherwise, returns + * false. + * * @param ret The class to check + * * @return boolean True if class is supported */ private boolean supportedType(Class ret) { @@ -146,10 +122,10 @@ } /** - * Check if this class conforms to JavaBeans specifications. - * If the class is conformant, returns true. + * Check if this class conforms to JavaBeans specifications. If the class is conformant, returns true. * * @param javaType The class to check + * * @return boolean True if the class is compatible. */ private boolean isBeanCompatible(Class javaType) { @@ -160,8 +136,7 @@ // Anything in the java or javax package that // does not have a defined mapping is excluded. - if (javaType.getName().startsWith("java.") || - javaType.getName().startsWith("javax.")) { + if (javaType.getName().startsWith("java.") || javaType.getName().startsWith("javax.")) { return false; } @@ -173,10 +148,8 @@ // Make sure superclass is compatible Class superClass = javaType.getSuperclass(); - if (superClass != null && - superClass != Object.class && - superClass != Exception.class && - superClass != Throwable.class) { + if (superClass != null && superClass != Object.class && superClass != Exception.class && + superClass != Throwable.class) { return isBeanCompatible(superClass); } return true; @@ -185,15 +158,14 @@ /** * Process the methods and extract 'attributes', methods, etc. * - * @param realClass The class to process - * @param attNames The attribute name (complete) - * @param getAttMap The readable attributes map - * @param setAttMap The settable attributes map + * @param realClass The class to process + * @param attNames The attribute name (complete) + * @param getAttMap The readable attributes map + * @param setAttMap The settable attributes map * @param invokeAttList The invokable attributes list */ - private void initMethods(Class realClass, Set attNames, - Map getAttMap, Map setAttMap, - List invokeAttList) { + private void initMethods(Class realClass, Set attNames, Map getAttMap, + Map setAttMap, List invokeAttList) { Method[] methods = realClass.getMethods(); for (Method method : methods) { @@ -271,29 +243,25 @@ } /** - * XXX Find if the 'className' is the name of the MBean or - * the real class ( I suppose first ) - * XXX Read (optional) descriptions from a .properties, generated - * from source - * XXX Deal with constructors + * XXX Find if the 'className' is the name of the MBean or the real class ( I suppose first ) XXX Read (optional) + * descriptions from a .properties, generated from source XXX Deal with constructors * - * @param registry The Bean registry (not used) - * @param domain The bean domain (not used) + * @param registry The Bean registry (not used) + * @param domain The bean domain (not used) * @param realClass The class to analyze - * @param type The bean type + * @param type The bean type + * * @return ManagedBean The create MBean */ - public ManagedBean createManagedBean(Registry registry, String domain, - Class realClass, String type) - { + public ManagedBean createManagedBean(Registry registry, String domain, Class realClass, String type) { ManagedBean mbean = new ManagedBean(); Set attrNames = new HashSet<>(); // key: attribute val: getter method - Map getAttMap = new HashMap<>(); + Map getAttMap = new HashMap<>(); // key: attribute val: setter method - Map setAttMap = new HashMap<>(); + Map setAttMap = new HashMap<>(); // key: operation val: invoke method List invokeAttList = new ArrayList<>(); @@ -353,8 +321,8 @@ mbean.setName(type); return mbean; - } catch (Exception ex) { - log.error(sm.getString("source.introspectionError", realClass.getName()), ex); + } catch (Exception e) { + log.error(sm.getString("source.introspectionError", realClass.getName()), e); return null; } } @@ -362,10 +330,10 @@ // -------------------- Utils -------------------- /** - * Converts the first character of the given - * String into lower-case. + * Converts the first character of the given String into lower-case. * * @param name The string to convert + * * @return String */ private static String unCapitalize(String name) { diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/modeler/modules/ModelerSource.java tomcat10-10.1.52/java/org/apache/tomcat/util/modeler/modules/ModelerSource.java --- tomcat10-10.1.40/java/org/apache/tomcat/util/modeler/modules/ModelerSource.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/modeler/modules/ModelerSource.java 2026-01-23 19:33:36.000000000 +0000 @@ -34,11 +34,12 @@ * Load data, returns a list of items. * * @param registry The registry - * @param type The bean registry type - * @param source Introspected object or some other source + * @param type The bean registry type + * @param source Introspected object or some other source + * * @return a list of object names + * * @throws Exception Error loading descriptors */ - public abstract List loadDescriptors(Registry registry, - String type, Object source) throws Exception; + public abstract List loadDescriptors(Registry registry, String type, Object source) throws Exception; } diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/net/AbstractEndpoint.java tomcat10-10.1.52/java/org/apache/tomcat/util/net/AbstractEndpoint.java --- tomcat10-10.1.40/java/org/apache/tomcat/util/net/AbstractEndpoint.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/net/AbstractEndpoint.java 2026-01-23 19:33:36.000000000 +0000 @@ -61,15 +61,10 @@ import org.apache.tomcat.util.threads.VirtualThreadExecutor; /** - * @param The type used by the socket wrapper associated with this endpoint. - * Might be the same as U. - * @param The type of the underlying socket used by this endpoint. Might be - * the same as S. - * - * @author Mladen Turk - * @author Remy Maucherat + * @param The type used by the socket wrapper associated with this endpoint. Might be the same as U. + * @param The type of the underlying socket used by this endpoint. Might be the same as S. */ -public abstract class AbstractEndpoint { +public abstract class AbstractEndpoint { // -------------------------------------------------------------- Constants @@ -82,8 +77,16 @@ */ enum SocketState { // TODO Add a new state to the AsyncStateMachine and remove - // ASYNC_END (if possible) - OPEN, CLOSED, LONG, ASYNC_END, SENDFILE, UPGRADING, UPGRADED, ASYNC_IO, SUSPENDED + // ASYNC_END (if possible) + OPEN, + CLOSED, + LONG, + ASYNC_END, + SENDFILE, + UPGRADING, + UPGRADED, + ASYNC_IO, + SUSPENDED } @@ -95,8 +98,7 @@ * * @return The state of the socket after processing */ - SocketState process(SocketWrapperBase socket, - SocketEvent status); + SocketState process(SocketWrapperBase socket, SocketEvent status); /** @@ -116,10 +118,9 @@ /** - * Inform the handler that the endpoint has stopped accepting any new - * connections. Typically, the endpoint will be stopped shortly - * afterwards but it is possible that the endpoint will be resumed so - * the handler should not assume that a stop will follow. + * Inform the handler that the endpoint has stopped accepting any new connections. Typically, the endpoint will + * be stopped shortly afterwards but it is possible that the endpoint will be resumed so the handler should not + * assume that a stop will follow. */ void pause(); @@ -187,6 +188,7 @@ * Socket properties */ protected final SocketProperties socketProperties = new SocketProperties(); + public SocketProperties getSocketProperties() { return socketProperties; } @@ -206,10 +208,11 @@ /** * Map holding all current connections keyed with the sockets. */ - protected Map> connections = new ConcurrentHashMap<>(); + protected Map> connections = new ConcurrentHashMap<>(); /** * Get a set with the current open connections. + * * @return A set with the open socket wrappers */ public Set> getConnections() { @@ -218,53 +221,61 @@ // ----------------------------------------------------------------- Properties + private boolean strictSni = true; + + public boolean getStrictSni() { + return strictSni; + } + + public void setStrictSni(boolean strictSni) { + this.strictSni = strictSni; + } + + private String defaultSSLHostConfigName = SSLHostConfig.DEFAULT_SSL_HOST_NAME; + /** - * @return The host name for the default SSL configuration for this endpoint - * - always in lower case. + * @return The host name for the default SSL configuration for this endpoint - always in lower case. */ public String getDefaultSSLHostConfigName() { return defaultSSLHostConfigName; } + public void setDefaultSSLHostConfigName(String defaultSSLHostConfigName) { this.defaultSSLHostConfigName = defaultSSLHostConfigName.toLowerCase(Locale.ENGLISH); } protected ConcurrentMap sslHostConfigs = new ConcurrentHashMap<>(); + /** * Add the given SSL Host configuration. * * @param sslHostConfig The configuration to add * - * @throws IllegalArgumentException If the host name is not valid or if a - * configuration has already been provided - * for that host + * @throws IllegalArgumentException If the host name is not valid or if a configuration has already been provided + * for that host */ public void addSslHostConfig(SSLHostConfig sslHostConfig) throws IllegalArgumentException { addSslHostConfig(sslHostConfig, false); } + /** - * Add the given SSL Host configuration, optionally replacing the existing - * configuration for the given host. + * Add the given SSL Host configuration, optionally replacing the existing configuration for the given host. * * @param sslHostConfig The configuration to add - * @param replace If {@code true} replacement of an existing - * configuration is permitted, otherwise any such - * attempted replacement will trigger an exception - * - * @throws IllegalArgumentException If the host name is not valid or if a - * configuration has already been provided - * for that host and replacement is not - * allowed + * @param replace If {@code true} replacement of an existing configuration is permitted, otherwise any such + * attempted replacement will trigger an exception + * + * @throws IllegalArgumentException If the host name is not valid or if a configuration has already been provided + * for that host and replacement is not allowed */ public void addSslHostConfig(SSLHostConfig sslHostConfig, boolean replace) throws IllegalArgumentException { String key = sslHostConfig.getHostName(); if (key == null || key.isEmpty()) { throw new IllegalArgumentException(sm.getString("endpoint.noSslHostName")); } - if (bindState != BindState.UNBOUND && bindState != BindState.SOCKET_CLOSED_ON_STOP && - isSSLEnabled()) { + if (bindState != BindState.UNBOUND && bindState != BindState.SOCKET_CLOSED_ON_STOP && isSSLEnabled()) { try { createSSLContext(sslHostConfig); } catch (IllegalArgumentException e) { @@ -293,14 +304,13 @@ registerJmx(sslHostConfig); } } + /** - * Removes the SSL host configuration for the given host name, if such a - * configuration exists. + * Removes the SSL host configuration for the given host name, if such a configuration exists. * - * @param hostName The host name associated with the SSL host configuration - * to remove + * @param hostName The host name associated with the SSL host configuration to remove * - * @return The SSL host configuration that was removed, if any + * @return The SSL host configuration that was removed, if any */ public SSLHostConfig removeSslHostConfig(String hostName) { if (hostName == null) { @@ -311,20 +321,18 @@ // keys are compared in a case-sensitive manner. String hostNameLower = hostName.toLowerCase(Locale.ENGLISH); if (hostNameLower.equals(getDefaultSSLHostConfigName())) { - throw new IllegalArgumentException( - sm.getString("endpoint.removeDefaultSslHostConfig", hostName)); + throw new IllegalArgumentException(sm.getString("endpoint.removeDefaultSslHostConfig", hostName)); } SSLHostConfig sslHostConfig = sslHostConfigs.remove(hostNameLower); unregisterJmx(sslHostConfig); return sslHostConfig; } + /** - * Re-read the configuration files for the SSL host and replace the existing - * SSL configuration with the updated settings. Note this replacement will - * happen even if the settings remain unchanged. + * Re-read the configuration files for the SSL host and replace the existing SSL configuration with the updated + * settings. Note this replacement will happen even if the settings remain unchanged. * - * @param hostName The SSL host for which the configuration should be - * reloaded. This must match a current SSL host + * @param hostName The SSL host for which the configuration should be reloaded. This must match a current SSL host */ public void reloadSslHostConfig(String hostName) { // Host names are case-insensitive but stored/processed in lower case @@ -335,21 +343,21 @@ // the call path. SSLHostConfig sslHostConfig = sslHostConfigs.get(hostName.toLowerCase(Locale.ENGLISH)); if (sslHostConfig == null) { - throw new IllegalArgumentException( - sm.getString("endpoint.unknownSslHostName", hostName)); + throw new IllegalArgumentException(sm.getString("endpoint.unknownSslHostName", hostName)); } addSslHostConfig(sslHostConfig, true); } + /** - * Re-read the configuration files for all SSL hosts and replace the - * existing SSL configuration with the updated settings. Note this - * replacement will happen even if the settings remain unchanged. + * Re-read the configuration files for all SSL hosts and replace the existing SSL configuration with the updated + * settings. Note this replacement will happen even if the settings remain unchanged. */ public void reloadSslHostConfigs() { for (String hostName : sslHostConfigs.keySet()) { reloadSslHostConfig(hostName); } } + public SSLHostConfig[] findSslHostConfigs() { return sslHostConfigs.values().toArray(new SSLHostConfig[0]); } @@ -357,10 +365,9 @@ /** * Create the SSLContext for the given SSLHostConfig. * - * @param sslHostConfig The SSLHostConfig for which the SSLContext should be - * created - * @throws Exception If the SSLContext cannot be created for the given - * SSLHostConfig + * @param sslHostConfig The SSLHostConfig for which the SSLContext should be created + * + * @throws Exception If the SSLContext cannot be created for the given SSLHostConfig */ protected abstract void createSSLContext(SSLHostConfig sslHostConfig) throws Exception; @@ -380,8 +387,14 @@ if (keyAlias == null) { keyAlias = SSLUtilBase.DEFAULT_KEY_ALIAS; } - certificateInfo = - sm.getString("endpoint.tls.info.cert.keystore", certificate.getCertificateKeystoreFile(), keyAlias); + String keystoreFile; + if (certificate.getCertificateKeystoreInternal() != null) { + // Keystore was set directly. Original location is unknown. + keystoreFile = sm.getString("endpoint.tls.info.cert.keystore.direct"); + } else { + keystoreFile = certificate.getCertificateKeystoreFile(); + } + certificateInfo = sm.getString("endpoint.tls.info.cert.keystore", keystoreFile, keyAlias); } String trustStoreSource = sslHostConfig.getTruststoreFile(); @@ -451,8 +464,7 @@ /** * Release the SSLContext, if any, associated with the SSLHostConfig. * - * @param sslHostConfig The SSLHostConfig for which the SSLContext should be - * released + * @param sslHostConfig The SSLHostConfig for which the SSLContext should be released */ protected void releaseSSLContext(SSLHostConfig sslHostConfig) { for (SSLHostConfigCertificate certificate : sslHostConfig.getCertificates()) { @@ -475,7 +487,7 @@ *
    • default SSLHostConfig
    • * * - * @param sniHostName Host name - must be in lower case + * @param sniHostName Host name - must be in lower case * * @return The SSLHostConfig for the given host name. */ @@ -508,20 +520,38 @@ /** + * Check if two host names share the same SSLHostConfig. + * + * @param sniHostName the host name from SNI, null if SNI is not in use + * @param protocolHostName the host name from the protocol + * @return true if SNI is not checked, if the SNI host name matches the protocol host name, + * if both host names use the same SSLHostConfig configuration, if there is no SNI and the + * protocol host name uses the default SSLHostConfig configuration, and false otherwise + */ + public boolean checkSni(String sniHostName, String protocolHostName) { + return (!strictSni || !isSSLEnabled() + || (sniHostName != null && sniHostName.equalsIgnoreCase(protocolHostName)) + || getSSLHostConfig(sniHostName) == getSSLHostConfig(protocolHostName)); + } + + + /** * Has the user requested that send file be used where possible? */ private boolean useSendfile = true; + public boolean getUseSendfile() { return useSendfile; } + public void setUseSendfile(boolean useSendfile) { this.useSendfile = useSendfile; } /** - * Time to wait for the internal executor (if used) to terminate when the - * endpoint is stopped in milliseconds. Defaults to 5000 (5 seconds). + * Time to wait for the internal executor (if used) to terminate when the endpoint is stopped in milliseconds. + * Defaults to 5000 (5 seconds). */ private long executorTerminationTimeoutMillis = 5000; @@ -529,8 +559,7 @@ return executorTerminationTimeoutMillis; } - public void setExecutorTerminationTimeoutMillis( - long executorTerminationTimeoutMillis) { + public void setExecutorTerminationTimeoutMillis(long executorTerminationTimeoutMillis) { this.executorTerminationTimeoutMillis = executorTerminationTimeoutMillis; } @@ -539,13 +568,18 @@ * Priority of the acceptor threads. */ protected int acceptorThreadPriority = Thread.NORM_PRIORITY; + public void setAcceptorThreadPriority(int acceptorThreadPriority) { this.acceptorThreadPriority = acceptorThreadPriority; } - public int getAcceptorThreadPriority() { return acceptorThreadPriority; } + + public int getAcceptorThreadPriority() { + return acceptorThreadPriority; + } - private int maxConnections = 8*1024; + private int maxConnections = 8 * 1024; + public void setMaxConnections(int maxCon) { this.maxConnections = maxCon; LimitLatch latch = this.connectionLimitLatch; @@ -560,19 +594,19 @@ initializeConnectionLatch(); } } - public int getMaxConnections() { return this.maxConnections; } + + public int getMaxConnections() { + return this.maxConnections; + } /** - * Return the current count of connections handled by this endpoint, if the - * connections are counted (which happens when the maximum count of - * connections is limited), or -1 if they are not. This - * property is added here so that this value can be inspected through JMX. - * It is visible on "ThreadPool" MBean. - * - *

      The count is incremented by the Acceptor before it tries to accept a - * new connection. Until the limit is reached and thus the count cannot be - * incremented, this value is more by 1 (the count of acceptors) than the - * actual count of connections that are being served. + * Return the current count of connections handled by this endpoint, if the connections are counted (which happens + * when the maximum count of connections is limited), or -1 if they are not. This property is added + * here so that this value can be inspected through JMX. It is visible on "ThreadPool" MBean. + *

      + * The count is incremented by the Acceptor before it tries to accept a new connection. Until the limit is reached + * and thus the count cannot be incremented, this value is more by 1 (the count of acceptors) than the actual count + * of connections that are being served. * * @return The count */ @@ -588,17 +622,23 @@ * External Executor based thread pool. */ private Executor executor = null; + public void setExecutor(Executor executor) { this.executor = executor; this.internalExecutor = (executor == null); } - public Executor getExecutor() { return executor; } + + public Executor getExecutor() { + return executor; + } private boolean useVirtualThreads = false; + public void setUseVirtualThreads(boolean useVirtualThreads) { this.useVirtualThreads = useVirtualThreads; } + public boolean getUseVirtualThreads() { return useVirtualThreads; } @@ -608,9 +648,11 @@ * External Executor based thread pool for utility tasks. */ private ScheduledExecutorService utilityExecutor = null; + public void setUtilityExecutor(ScheduledExecutorService utilityExecutor) { this.utilityExecutor = utilityExecutor; } + public ScheduledExecutorService getUtilityExecutor() { if (utilityExecutor == null) { getLog().warn(sm.getString("endpoint.warn.noUtilityExecutor")); @@ -624,13 +666,23 @@ * Server socket port. */ private int port = -1; - public int getPort() { return port; } - public void setPort(int port ) { this.port=port; } + + public int getPort() { + return port; + } + + public void setPort(int port) { + this.port = port; + } private int portOffset = 0; - public int getPortOffset() { return portOffset; } - public void setPortOffset(int portOffset ) { + + public int getPortOffset() { + return portOffset; + } + + public void setPortOffset(int portOffset) { if (portOffset < 0) { throw new IllegalArgumentException( sm.getString("endpoint.portOffset.invalid", Integer.valueOf(portOffset))); @@ -666,46 +718,62 @@ * Address for the server socket. */ private InetAddress address; - public InetAddress getAddress() { return address; } - public void setAddress(InetAddress address) { this.address = address; } + + public InetAddress getAddress() { + return address; + } + + public void setAddress(InetAddress address) { + this.address = address; + } /** - * Obtain the network address the server socket is bound to. This primarily - * exists to enable the correct address to be used when unlocking the server - * socket since it removes the guess-work involved if no address is - * specifically set. + * Obtain the network address the server socket is bound to. This primarily exists to enable the correct address to + * be used when unlocking the server socket since it removes the guess-work involved if no address is specifically + * set. * - * @return The network address that the server socket is listening on or - * null if the server socket is not currently bound. + * @return The network address that the server socket is listening on or null if the server socket is not currently + * bound. * - * @throws IOException If there is a problem determining the currently bound - * socket + * @throws IOException If there is a problem determining the currently bound socket */ protected abstract InetSocketAddress getLocalAddress() throws IOException; /** - * Allows the server developer to specify the acceptCount (backlog) that - * should be used for server sockets. By default, this value - * is 100. + * Allows the server developer to specify the acceptCount (backlog) that should be used for server sockets. By + * default, this value is 100. */ private int acceptCount = 100; - public void setAcceptCount(int acceptCount) { if (acceptCount > 0) { - this.acceptCount = acceptCount; - } } - public int getAcceptCount() { return acceptCount; } + + public void setAcceptCount(int acceptCount) { + if (acceptCount > 0) { + this.acceptCount = acceptCount; + } + } + + public int getAcceptCount() { + return acceptCount; + } /** - * Controls when the Endpoint binds the port. true, the default - * binds the port on {@link #init()} and unbinds it on {@link #destroy()}. - * If set to false the port is bound on {@link #start()} and - * unbound on {@link #stop()}. + * Controls when the Endpoint binds the port. true, the default binds the port on {@link #init()} and + * unbinds it on {@link #destroy()}. If set to false the port is bound on {@link #start()} and unbound + * on {@link #stop()}. */ private boolean bindOnInit = true; - public boolean getBindOnInit() { return bindOnInit; } - public void setBindOnInit(boolean b) { this.bindOnInit = b; } + + public boolean getBindOnInit() { + return bindOnInit; + } + + public void setBindOnInit(boolean b) { + this.bindOnInit = b; + } + private volatile BindState bindState = BindState.UNBOUND; + protected BindState getBindState() { return bindState; } @@ -714,6 +782,7 @@ * Keepalive timeout, if not set the soTimeout is used. */ private Integer keepAliveTimeout = null; + public int getKeepAliveTimeout() { if (keepAliveTimeout == null) { return getConnectionTimeout(); @@ -721,6 +790,7 @@ return keepAliveTimeout.intValue(); } } + public void setKeepAliveTimeout(int keepAliveTimeout) { this.keepAliveTimeout = Integer.valueOf(keepAliveTimeout); } @@ -729,23 +799,29 @@ /** * Socket TCP no delay. * - * @return The current TCP no delay setting for sockets created by this - * endpoint + * @return The current TCP no delay setting for sockets created by this endpoint */ - public boolean getTcpNoDelay() { return socketProperties.getTcpNoDelay();} - public void setTcpNoDelay(boolean tcpNoDelay) { socketProperties.setTcpNoDelay(tcpNoDelay); } + public boolean getTcpNoDelay() { + return socketProperties.getTcpNoDelay(); + } + + public void setTcpNoDelay(boolean tcpNoDelay) { + socketProperties.setTcpNoDelay(tcpNoDelay); + } /** * Socket linger. * - * @return The current socket linger time for sockets created by this - * endpoint + * @return The current socket linger time for sockets created by this endpoint */ - public int getConnectionLinger() { return socketProperties.getSoLingerTime(); } + public int getConnectionLinger() { + return socketProperties.getSoLingerTime(); + } + public void setConnectionLinger(int connectionLinger) { socketProperties.setSoLingerTime(connectionLinger); - socketProperties.setSoLingerOn(connectionLinger>=0); + socketProperties.setSoLingerOn(connectionLinger >= 0); } @@ -754,17 +830,29 @@ * * @return The current socket timeout for sockets created by this endpoint */ - public int getConnectionTimeout() { return socketProperties.getSoTimeout(); } - public void setConnectionTimeout(int soTimeout) { socketProperties.setSoTimeout(soTimeout); } + public int getConnectionTimeout() { + return socketProperties.getSoTimeout(); + } + + public void setConnectionTimeout(int soTimeout) { + socketProperties.setSoTimeout(soTimeout); + } /** * SSL engine. */ private boolean SSLEnabled = false; - public boolean isSSLEnabled() { return SSLEnabled; } - public void setSSLEnabled(boolean SSLEnabled) { this.SSLEnabled = SSLEnabled; } + + public boolean isSSLEnabled() { + return SSLEnabled; + } + + public void setSSLEnabled(boolean SSLEnabled) { + this.SSLEnabled = SSLEnabled; + } private int minSpareThreads = 10; + public void setMinSpareThreads(int minSpareThreads) { this.minSpareThreads = minSpareThreads; Executor executor = this.executor; @@ -776,9 +864,11 @@ ((ThreadPoolExecutor) executor).setCorePoolSize(minSpareThreads); } } + public int getMinSpareThreads() { return Math.min(getMinSpareThreadsInternal(), getMaxThreads()); } + private int getMinSpareThreadsInternal() { if (internalExecutor) { return minSpareThreads; @@ -792,6 +882,7 @@ * Maximum amount of worker threads. */ private int maxThreads = 200; + public void setMaxThreads(int maxThreads) { this.maxThreads = maxThreads; Executor executor = this.executor; @@ -803,6 +894,7 @@ ((ThreadPoolExecutor) executor).setMaximumPoolSize(maxThreads); } } + public int getMaxThreads() { if (internalExecutor) { return maxThreads; @@ -816,9 +908,11 @@ * Task queue capacity for the thread pool. */ private int maxQueueSize = Integer.MAX_VALUE; + public void setMaxQueueSize(int maxQueueSize) { this.maxQueueSize = maxQueueSize; } + public int getMaxQueueSize() { if (internalExecutor) { return maxQueueSize; @@ -829,10 +923,11 @@ /** - * Amount of time in milliseconds before the internal thread pool stops any idle threads - * if the amount of thread is greater than the minimum amount of spare threads. + * Amount of time in milliseconds before the internal thread pool stops any idle threads if the amount of thread is + * greater than the minimum amount of spare threads. */ private int threadsMaxIdleTime = 60000; + public void setThreadsMaxIdleTime(int threadsMaxIdleTime) { this.threadsMaxIdleTime = threadsMaxIdleTime; Executor executor = this.executor; @@ -844,6 +939,7 @@ ((ThreadPoolExecutor) executor).setKeepAliveTime(threadsMaxIdleTime, TimeUnit.MILLISECONDS); } } + public int getThreadsMaxIdleTime() { if (internalExecutor) { return threadsMaxIdleTime; @@ -856,10 +952,12 @@ * Priority of the worker threads. */ protected int threadPriority = Thread.NORM_PRIORITY; + public void setThreadPriority(int threadPriority) { // Can't change this once the executor has started this.threadPriority = threadPriority; } + public int getThreadPriority() { if (internalExecutor) { return threadPriority; @@ -872,7 +970,8 @@ /** * Max keep alive requests */ - private int maxKeepAliveRequests=100; // as in Apache HTTPD server + private int maxKeepAliveRequests = 100; // as in Apache HTTPD server + public int getMaxKeepAliveRequests() { // Disable keep-alive if the server socket is not bound if (bindState.isBound()) { @@ -881,6 +980,7 @@ return 1; } } + public void setMaxKeepAliveRequests(int maxKeepAliveRequests) { this.maxKeepAliveRequests = maxKeepAliveRequests; } @@ -890,34 +990,57 @@ * Name of the thread pool, which will be used for naming child threads. */ private String name = "TP"; - public void setName(String name) { this.name = name; } - public String getName() { return name; } + + public void setName(String name) { + this.name = name; + } + + public String getName() { + return name; + } /** * Name of domain to use for JMX registration. */ private String domain; - public void setDomain(String domain) { this.domain = domain; } - public String getDomain() { return domain; } + + public void setDomain(String domain) { + this.domain = domain; + } + + public String getDomain() { + return domain; + } /** - * The default is true - the created threads will be - * in daemon mode. If set to false, the control thread - * will not be daemon - and will keep the process alive. + * The default is true - the created threads will be in daemon mode. If set to false, the control thread will not be + * daemon - and will keep the process alive. */ private boolean daemon = true; - public void setDaemon(boolean b) { daemon = b; } - public boolean getDaemon() { return daemon; } + + public void setDaemon(boolean b) { + daemon = b; + } + + public boolean getDaemon() { + return daemon; + } /** * Expose asynchronous IO capability. */ private boolean useAsyncIO = true; - public void setUseAsyncIO(boolean useAsyncIO) { this.useAsyncIO = useAsyncIO; } - public boolean getUseAsyncIO() { return useAsyncIO; } + + public void setUseAsyncIO(boolean useAsyncIO) { + this.useAsyncIO = useAsyncIO; + } + + public boolean getUseAsyncIO() { + return useAsyncIO; + } /** @@ -928,15 +1051,15 @@ * @deprecated This code will be removed in Tomcat 11 onwards */ @Deprecated - protected boolean getDeferAccept() { + public boolean getDeferAccept() { return false; } /** - * The default behavior is to identify connectors uniquely with address - * and port. However, certain connectors are not using that and need - * some other identifier, which then can be used as a replacement. + * The default behavior is to identify connectors uniquely with address and port. However, certain connectors are + * not using that and need some other identifier, which then can be used as a replacement. + * * @return the id */ public String getId() { @@ -945,9 +1068,11 @@ protected final List negotiableProtocols = new ArrayList<>(); + public void addNegotiatedProtocol(String negotiableProtocol) { negotiableProtocols.add(negotiableProtocol); } + public boolean hasNegotiableProtocols() { return (!negotiableProtocols.isEmpty()); } @@ -957,23 +1082,26 @@ * Handling of accepted sockets. */ private Handler handler = null; - public void setHandler(Handler handler ) { this.handler = handler; } - public Handler getHandler() { return handler; } + + public void setHandler(Handler handler) { + this.handler = handler; + } + + public Handler getHandler() { + return handler; + } /** - * Attributes provide a way for configuration to be passed to subcomponents - * without the {@link org.apache.coyote.ProtocolHandler} being aware of the - * properties available on those subcomponents. + * Attributes provide a way for configuration to be passed to subcomponents without the + * {@link org.apache.coyote.ProtocolHandler} being aware of the properties available on those subcomponents. */ - protected HashMap attributes = new HashMap<>(); + protected HashMap attributes = new HashMap<>(); /** - * Generic property setter called when a property for which a specific - * setter already exists within the - * {@link org.apache.coyote.ProtocolHandler} needs to be made available to - * subcomponents. The specific setter will call this method to populate the - * attributes. + * Generic property setter called when a property for which a specific setter already exists within the + * {@link org.apache.coyote.ProtocolHandler} needs to be made available to subcomponents. The specific setter will + * call this method to populate the attributes. * * @param name Name of property to set * @param value The value to set the property to @@ -984,11 +1112,11 @@ } attributes.put(name, value); } + /** * Used by subcomponents to retrieve configuration information. * - * @param key The name of the property for which the value should be - * retrieved + * @param key The name of the property for which the value should be retrieved * * @return The value of the specified property */ @@ -1001,7 +1129,6 @@ } - public boolean setProperty(String name, String value) { setAttribute(name, value); final String socketName = "socket."; @@ -1009,13 +1136,14 @@ if (name.startsWith(socketName)) { return IntrospectionUtils.setProperty(socketProperties, name.substring(socketName.length()), value); } else { - return IntrospectionUtils.setProperty(this,name,value,false); + return IntrospectionUtils.setProperty(this, name, value, false); } - }catch ( Exception x ) { - getLog().error(sm.getString("endpoint.setAttributeError", name, value), x); + } catch (Exception e) { + getLog().error(sm.getString("endpoint.setAttributeError", name, value), e); return false; } } + public String getProperty(String name) { String value = (String) getAttribute(name); final String socketName = "socket."; @@ -1100,7 +1228,7 @@ if (executor != null && internalExecutor) { this.executor = null; if (executor instanceof ThreadPoolExecutor) { - //this is our internal one, so we need to shut it down + // this is our internal one, so we need to shut it down ThreadPoolExecutor tpe = (ThreadPoolExecutor) executor; tpe.shutdownNow(); long timeout = getExecutorTerminationTimeoutMillis(); @@ -1134,7 +1262,9 @@ try { localAddress = getLocalAddress(); } catch (IOException ioe) { - getLog().debug(sm.getString("endpoint.debug.unlock.localFail", getName()), ioe); + if (getLog().isDebugEnabled()) { + getLog().debug(sm.getString("endpoint.debug.unlock.localFail", getName()), ioe); + } } if (localAddress == null) { getLog().warn(sm.getString("endpoint.debug.unlock.localNone", getName())); @@ -1171,11 +1301,10 @@ Thread.sleep(1); } } - } catch(Throwable t) { + } catch (Throwable t) { ExceptionUtils.handleThrowable(t); if (getLog().isDebugEnabled()) { - getLog().debug(sm.getString( - "endpoint.debug.unlock.fail", String.valueOf(getPortWithOffset())), t); + getLog().debug(sm.getString("endpoint.debug.unlock.fail", String.valueOf(getPortWithOffset())), t); } } } @@ -1233,19 +1362,16 @@ // ---------------------------------------------- Request processing methods /** - * Process the given SocketWrapper with the given status. Used to trigger - * processing as if the Poller (for those endpoints that have one) - * selected the socket. + * Process the given SocketWrapper with the given status. Used to trigger processing as if the Poller (for those + * endpoints that have one) selected the socket. * * @param socketWrapper The socket wrapper to process * @param event The socket event to be processed - * @param dispatch Should the processing be performed on a new - * container thread + * @param dispatch Should the processing be performed on a new container thread * * @return if processing was triggered successfully */ - public boolean processSocket(SocketWrapperBase socketWrapper, - SocketEvent event, boolean dispatch) { + public boolean processSocket(SocketWrapperBase socketWrapper, SocketEvent event, boolean dispatch) { try { if (socketWrapper == null) { return false; @@ -1266,7 +1392,7 @@ sc.run(); } } catch (RejectedExecutionException ree) { - getLog().warn(sm.getString("endpoint.executor.fail", socketWrapper) , ree); + getLog().warn(sm.getString("endpoint.executor.fail", socketWrapper), ree); return false; } catch (Throwable t) { ExceptionUtils.handleThrowable(t); @@ -1279,23 +1405,24 @@ } - protected abstract SocketProcessorBase createSocketProcessor( - SocketWrapperBase socketWrapper, SocketEvent event); + protected abstract SocketProcessorBase createSocketProcessor(SocketWrapperBase socketWrapper, + SocketEvent event); // ------------------------------------------------------- Lifecycle methods /* - * NOTE: There is no maintenance of state or checking for valid transitions - * within this class other than ensuring that bind/unbind are called in the - * right place. It is expected that the calling code will maintain state and + * NOTE: There is no maintenance of state or checking for valid transitions within this class other than ensuring + * that bind/unbind are called in the right place. It is expected that the calling code will maintain state and * prevent invalid state transitions. */ public abstract void bind() throws Exception; + public abstract void unbind() throws Exception; public abstract void startInternal() throws Exception; + public abstract void stopInternal() throws Exception; @@ -1322,8 +1449,8 @@ oname = new ObjectName(domain + ":type=ThreadPool,name=\"" + getName() + "\""); Registry.getRegistry(null).registerComponent(this, oname, null); - ObjectName socketPropertiesOname = new ObjectName(domain + - ":type=SocketProperties,name=\"" + getName() + "\""); + ObjectName socketPropertiesOname = + new ObjectName(domain + ":type=SocketProperties,name=\"" + getName() + "\""); socketProperties.setObjectName(socketPropertiesOname); Registry.getRegistry(null).registerComponent(socketProperties, socketPropertiesOname, null); @@ -1341,8 +1468,8 @@ } ObjectName sslOname; try { - sslOname = new ObjectName(domain + ":type=SSLHostConfig,ThreadPool=\"" + - getName() + "\",name=" + ObjectName.quote(sslHostConfig.getHostName())); + sslOname = new ObjectName(domain + ":type=SSLHostConfig,ThreadPool=\"" + getName() + "\",name=" + + ObjectName.quote(sslHostConfig.getHostName())); sslHostConfig.setObjectName(sslOname); try { Registry.getRegistry(null).registerComponent(sslHostConfig, sslOname, null); @@ -1350,27 +1477,24 @@ getLog().warn(sm.getString("endpoint.jmxRegistrationFailed", sslOname), e); } } catch (MalformedObjectNameException e) { - getLog().warn(sm.getString("endpoint.invalidJmxNameSslHost", - sslHostConfig.getHostName()), e); + getLog().warn(sm.getString("endpoint.invalidJmxNameSslHost", sslHostConfig.getHostName()), e); } for (SSLHostConfigCertificate sslHostConfigCert : sslHostConfig.getCertificates()) { ObjectName sslCertOname; try { - sslCertOname = new ObjectName(domain + - ":type=SSLHostConfigCertificate,ThreadPool=\"" + getName() + - "\",Host=" + ObjectName.quote(sslHostConfig.getHostName()) + - ",name=" + sslHostConfigCert.getType()); + sslCertOname = new ObjectName( + domain + ":type=SSLHostConfigCertificate,ThreadPool=\"" + getName() + "\",Host=" + + ObjectName.quote(sslHostConfig.getHostName()) + ",name=" + sslHostConfigCert.getType()); sslHostConfigCert.setObjectName(sslCertOname); try { - Registry.getRegistry(null).registerComponent( - sslHostConfigCert, sslCertOname, null); + Registry.getRegistry(null).registerComponent(sslHostConfigCert, sslCertOname, null); } catch (Exception e) { getLog().warn(sm.getString("endpoint.jmxRegistrationFailed", sslCertOname), e); } } catch (MalformedObjectNameException e) { - getLog().warn(sm.getString("endpoint.invalidJmxNameSslHostCert", - sslHostConfig.getHostName(), sslHostConfigCert.getType()), e); + getLog().warn(sm.getString("endpoint.invalidJmxNameSslHostCert", sslHostConfig.getHostName(), + sslHostConfigCert.getType()), e); } } } @@ -1406,8 +1530,7 @@ /** - * Pause the endpoint, which will stop it accepting new connections and - * unlock the acceptor. + * Pause the endpoint, which will stop it accepting new connections and unlock the acceptor. */ public void pause() { if (running && !paused) { @@ -1419,8 +1542,7 @@ } /** - * Resume the endpoint, which will make it start accepting new connections - * again. + * Resume the endpoint, which will make it start accepting new connections again. */ public void resume() { if (running) { @@ -1457,10 +1579,10 @@ } protected LimitLatch initializeConnectionLatch() { - if (maxConnections==-1) { + if (maxConnections == -1) { return null; } - if (connectionLimitLatch==null) { + if (connectionLimitLatch == null) { connectionLimitLatch = new LimitLatch(getMaxConnections()); } return connectionLimitLatch; @@ -1468,30 +1590,30 @@ private void releaseConnectionLatch() { LimitLatch latch = connectionLimitLatch; - if (latch!=null) { + if (latch != null) { latch.releaseAll(); } connectionLimitLatch = null; } protected void countUpOrAwaitConnection() throws InterruptedException { - if (maxConnections==-1) { + if (maxConnections == -1) { return; } LimitLatch latch = connectionLimitLatch; - if (latch!=null) { + if (latch != null) { latch.countUpOrAwait(); } } protected long countDownConnection() { - if (maxConnections==-1) { + if (maxConnections == -1) { return -1; } LimitLatch latch = connectionLimitLatch; - if (latch!=null) { + if (latch != null) { long result = latch.countDown(); - if (result<0) { + if (result < 0) { getLog().warn(sm.getString("endpoint.warn.incorrectConnectionCount")); } return result; @@ -1502,9 +1624,8 @@ /** - * Close the server socket (to prevent further connections) if the server - * socket was originally bound on {@link #start()} (rather than on - * {@link #init()}). + * Close the server socket (to prevent further connections) if the server socket was originally bound on + * {@link #start()} (rather than on {@link #init()}). * * @see #getBindOnInit() */ @@ -1531,12 +1652,10 @@ /** - * Wait for the client connections to the server to close gracefully. The - * method will return when all of the client connections have closed or the - * method has been waiting for {@code waitTimeMillis}. + * Wait for the client connections to the server to close gracefully. The method will return when all of the client + * connections have closed or the method has been waiting for {@code waitTimeMillis}. * - * @param waitMillis The maximum time to wait in milliseconds for the - * client connections to close. + * @param waitMillis The maximum time to wait in milliseconds for the client connections to close. * * @return The wait time, if any remaining when the method returned */ @@ -1566,10 +1685,10 @@ protected abstract boolean setSocketOptions(U socket); /** - * Close the socket when the connection has to be immediately closed when - * an error occurs while configuring the accepted socket or trying to - * dispatch it for processing. The wrapper associated with the socket will - * be used for the close. + * Close the socket when the connection has to be immediately closed when an error occurs while configuring the + * accepted socket or trying to dispatch it for processing. The wrapper associated with the socket will be used for + * the close. + * * @param socket The newly accepted socket */ protected void closeSocket(U socket) { @@ -1580,9 +1699,9 @@ } /** - * Close the socket. This is used when the connector is not in a state - * which allows processing the socket, or if there was an error which - * prevented the allocation of the socket wrapper. + * Close the socket. This is used when the connector is not in a state which allows processing the socket, or if + * there was an error which prevented the allocation of the socket wrapper. + * * @param socket The newly accepted socket */ protected abstract void destroySocket(U socket); diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/net/AbstractJsseEndpoint.java tomcat10-10.1.52/java/org/apache/tomcat/util/net/AbstractJsseEndpoint.java --- tomcat10-10.1.40/java/org/apache/tomcat/util/net/AbstractJsseEndpoint.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/net/AbstractJsseEndpoint.java 2026-01-23 19:33:36.000000000 +0000 @@ -28,9 +28,17 @@ import javax.net.ssl.SSLEngine; import javax.net.ssl.SSLParameters; +import org.apache.tomcat.util.compat.JreCompat; import org.apache.tomcat.util.net.openssl.ciphers.Cipher; +import org.apache.tomcat.util.net.openssl.ciphers.Group; +import org.apache.tomcat.util.net.openssl.ciphers.SignatureScheme; -public abstract class AbstractJsseEndpoint extends AbstractEndpoint { +public abstract class AbstractJsseEndpoint extends AbstractEndpoint { + + // Thread local use to pass additional arguments to createSSLEngine without changing the protected method signature + static final ThreadLocal> clientRequestedProtocolsThreadLocal = new ThreadLocal<>(); + static final ThreadLocal> clientSupportedGroupsThreadLocal = new ThreadLocal<>(); + static final ThreadLocal> clientSignatureSchemesThreadLocal = new ThreadLocal<>(); private String sslImplementationName = null; private int sniParseLimit = 64 * 1024; @@ -72,8 +80,8 @@ // Validate default SSLHostConfigName if (sslHostConfigs.get(getDefaultSSLHostConfigName()) == null) { - throw new IllegalArgumentException(sm.getString("endpoint.noSslHostConfig", - getDefaultSSLHostConfigName(), getName())); + throw new IllegalArgumentException( + sm.getString("endpoint.noSslHostConfig", getDefaultSSLHostConfigName(), getName())); } } @@ -83,13 +91,6 @@ @Override protected void createSSLContext(SSLHostConfig sslHostConfig) throws IllegalArgumentException { - // HTTP/2 does not permit optional certificate authentication with any - // version of TLS. - if (sslHostConfig.getCertificateVerification().isOptional() && - negotiableProtocols.contains("h2")) { - getLog().warn(sm.getString("sslHostConfig.certificateVerificationWithHttp2", sslHostConfig.getHostName())); - } - boolean firstCertificate = true; for (SSLHostConfigCertificate certificate : sslHostConfig.getCertificates(true)) { SSLUtil sslUtil = sslImplementation.getSSLUtil(certificate); @@ -103,15 +104,15 @@ SSLContext sslContextGenerated = certificate.getSslContextGenerated(); // Generate the SSLContext from configuration unless (e.g. embedded) an SSLContext has been provided. // Need to handle both initial configuration and reload. - // Initial, SSLContext provided - sslContext will be non-null and sslContextGenerated will be null + // Initial, SSLContext provided - sslContext will be non-null and sslContextGenerated will be null // Initial, SSLContext not provided - sslContext null and sslContextGenerated will be null - // Reload, SSLContext provided - sslContext will be non-null and sslContextGenerated will be null - // Reload, SSLContext not provided - sslContext non-null and equal to sslContextGenerated + // Reload, SSLContext provided - sslContext will be non-null and sslContextGenerated will be null + // Reload, SSLContext not provided - sslContext non-null and equal to sslContextGenerated if (sslContext == null || sslContext == sslContextGenerated) { try { sslContext = sslUtil.createSSLContext(negotiableProtocols); } catch (Exception e) { - throw new IllegalArgumentException(e.getMessage(), e); + throw new IllegalArgumentException(sm.getString("endpoint.errorCreatingSSLContext"), e); } certificate.setSslContextGenerated(sslContext); @@ -119,19 +120,33 @@ logCertificate(certificate); } + } protected SSLEngine createSSLEngine(String sniHostName, List clientRequestedCiphers, List clientRequestedApplicationProtocols) { + List clientRequestedProtocols = clientRequestedProtocolsThreadLocal.get(); + if (clientRequestedProtocols == null) { + clientRequestedProtocols = new ArrayList(); + } + List clientSupportedGroups = clientSupportedGroupsThreadLocal.get(); + if (clientSupportedGroups == null) { + clientSupportedGroups = new ArrayList(); + } + List clientSignatureSchemes = clientSignatureSchemesThreadLocal.get(); + if (clientSignatureSchemes == null) { + clientSignatureSchemes = new ArrayList(); + } + SSLHostConfig sslHostConfig = getSSLHostConfig(sniHostName); - SSLHostConfigCertificate certificate = selectCertificate(sslHostConfig, clientRequestedCiphers); + SSLHostConfigCertificate certificate = selectCertificate(sslHostConfig, clientRequestedCiphers, + clientRequestedProtocols, clientSignatureSchemes); SSLContext sslContext = certificate.getSslContext(); if (sslContext == null) { - throw new IllegalStateException( - sm.getString("endpoint.jsse.noSslContext", sniHostName)); + throw new IllegalStateException(sm.getString("endpoint.jsse.noSslContext", sniHostName)); } SSLEngine engine = sslContext.createSSLEngine(); @@ -141,32 +156,54 @@ SSLParameters sslParameters = engine.getSSLParameters(); sslParameters.setUseCipherSuitesOrder(sslHostConfig.getHonorCipherOrder()); - if (clientRequestedApplicationProtocols != null - && clientRequestedApplicationProtocols.size() > 0 - && negotiableProtocols.size() > 0) { + if (clientRequestedApplicationProtocols != null && !clientRequestedApplicationProtocols.isEmpty() && + !negotiableProtocols.isEmpty()) { // Only try to negotiate if both client and server have at least // one protocol in common // Note: Tomcat does not explicitly negotiate http/1.1 - // TODO: Is this correct? Should it change? List commonProtocols = new ArrayList<>(negotiableProtocols); commonProtocols.retainAll(clientRequestedApplicationProtocols); - if (commonProtocols.size() > 0) { + if (!commonProtocols.isEmpty()) { String[] commonProtocolsArray = commonProtocols.toArray(new String[0]); sslParameters.setApplicationProtocols(commonProtocolsArray); } } + // Merge server groups with the client groups + if (JreCompat.isJre20Available()) { + List supportedGroups = new ArrayList<>(); + LinkedHashSet serverSupportedGroups = sslHostConfig.getGroupList(); + if (serverSupportedGroups != null) { + if (!clientSupportedGroups.isEmpty()) { + for (Group group : clientSupportedGroups) { + if (serverSupportedGroups.contains(group)) { + supportedGroups.add(group.toString()); + } + } + } else { + for (Group group : serverSupportedGroups) { + supportedGroups.add(group.toString()); + } + } + JreCompat.getInstance().setNamedGroupsMethod(sslParameters, supportedGroups.toArray(new String[0])); + } else if (!clientSupportedGroups.isEmpty()) { + for (Group group : clientSupportedGroups) { + supportedGroups.add(group.toString()); + } + JreCompat.getInstance().setNamedGroupsMethod(sslParameters, supportedGroups.toArray(new String[0])); + } + } switch (sslHostConfig.getCertificateVerification()) { - case NONE: - sslParameters.setNeedClientAuth(false); - sslParameters.setWantClientAuth(false); - break; - case OPTIONAL: - case OPTIONAL_NO_CA: - sslParameters.setWantClientAuth(true); - break; - case REQUIRED: - sslParameters.setNeedClientAuth(true); - break; + case NONE: + sslParameters.setNeedClientAuth(false); + sslParameters.setWantClientAuth(false); + break; + case OPTIONAL: + case OPTIONAL_NO_CA: + sslParameters.setWantClientAuth(true); + break; + case REQUIRED: + sslParameters.setNeedClientAuth(true); + break; } // The getter (at least in OpenJDK and derivatives) returns a defensive copy engine.setSSLParameters(sslParameters); @@ -175,14 +212,26 @@ } - private SSLHostConfigCertificate selectCertificate( - SSLHostConfig sslHostConfig, List clientCiphers) { + private SSLHostConfigCertificate selectCertificate(SSLHostConfig sslHostConfig, List clientCiphers, + List clientRequestedProtocols, List clientSignatureSchemes) { Set certificates = sslHostConfig.getCertificates(true); if (certificates.size() == 1) { return certificates.iterator().next(); } + // Use signature algorithm for cipher matching with TLS 1.3 + if ((clientRequestedProtocols.contains(Constants.SSL_PROTO_TLSv1_3)) && + sslHostConfig.getProtocols().contains(Constants.SSL_PROTO_TLSv1_3)) { + for (SignatureScheme signatureScheme : clientSignatureSchemes) { + for (SSLHostConfigCertificate certificate : certificates) { + if (certificate.getType().isCompatibleWith(signatureScheme)) { + return certificate; + } + } + } + } + LinkedHashSet serverCiphers = sslHostConfig.getCipherList(); List candidateCiphers = new ArrayList<>(); diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/net/Acceptor.java tomcat10-10.1.52/java/org/apache/tomcat/util/net/Acceptor.java --- tomcat10-10.1.40/java/org/apache/tomcat/util/net/Acceptor.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/net/Acceptor.java 2026-01-23 19:33:36.000000000 +0000 @@ -35,9 +35,8 @@ private final AbstractEndpoint endpoint; private String threadName; /* - * Tracked separately rather than using endpoint.isRunning() as calls to - * endpoint.stop() and endpoint.start() in quick succession can cause the - * acceptor to continue running when it should terminate. + * Tracked separately rather than using endpoint.isRunning() as calls to endpoint.stop() and endpoint.start() in + * quick succession can cause the acceptor to continue running when it should terminate. */ private volatile boolean stopCalled = false; private final CountDownLatch stopLatch = new CountDownLatch(1); @@ -83,9 +82,9 @@ // excessive CPU usage. // Therefore, we start with a tight loop but if there isn't a // rapid transition to stop then sleeps are introduced. - // < 1ms - tight loop + // < 1ms - tight loop // 1ms to 10ms - 1ms sleep - // > 10ms - 10ms sleep + // > 10ms - 10ms sleep while (endpoint.isPaused() && !stopCalled) { if (state != AcceptorState.PAUSED) { pauseStart = System.nanoTime(); @@ -112,7 +111,7 @@ state = AcceptorState.RUNNING; try { - //if we have reached max connections, wait + // if we have reached max connections, wait endpoint.countUpOrAwaitConnection(); // Endpoint might have been paused while waiting for latch @@ -126,14 +125,14 @@ // Accept the next incoming connection from the server // socket socket = endpoint.serverSocketAccept(); - } catch (Exception ioe) { + } catch (Exception e) { // We didn't get a socket endpoint.countDownConnection(); if (endpoint.isRunning()) { // Introduce delay if necessary errorDelay = handleExceptionWithDelay(errorDelay); // re-throw - throw ioe; + throw e; } else { break; } @@ -153,8 +152,7 @@ } } catch (Throwable t) { ExceptionUtils.handleThrowable(t); - String msg = sm.getString("endpoint.accept.fail"); - log.error(msg, t); + log.error(sm.getString("endpoint.accept.fail"), t); } } } finally { @@ -165,12 +163,10 @@ /** - * Signals the Acceptor to stop, optionally waiting for that stop process - * to complete before returning. If a wait is requested and the stop does - * not complete in that time a warning will be logged. + * Signals the Acceptor to stop, optionally waiting for that stop process to complete before returning. If a wait is + * requested and the stop does not complete in that time a warning will be logged. * - * @param waitSeconds The time to wait in seconds. Use a value less than - * zero for no wait. + * @param waitSeconds The time to wait in seconds. Use a value less than zero for no wait. * * @deprecated Unused. Will be remove in Tomcat 11 onwards. */ @@ -185,7 +181,7 @@ if (waitMilliseconds > 0) { try { if (!stopLatch.await(waitMilliseconds, TimeUnit.MILLISECONDS)) { - log.warn(sm.getString("acceptor.stop.fail", getThreadName())); + log.warn(sm.getString("acceptor.stop.fail", getThreadName())); } } catch (InterruptedException e) { log.warn(sm.getString("acceptor.stop.interrupted", getThreadName()), e); @@ -195,13 +191,13 @@ /** - * Handles exceptions where a delay is required to prevent a Thread from - * entering a tight loop which will consume CPU and may also trigger large - * amounts of logging. For example, this can happen if the ulimit for open - * files is reached. + * Handles exceptions where a delay is required to prevent a Thread from entering a tight loop which will consume + * CPU and may also trigger large amounts of logging. For example, this can happen if the ulimit for open files is + * reached. * * @param currentErrorDelay The current delay being applied on failure - * @return The delay to apply on the next failure + * + * @return The delay to apply on the next failure */ protected int handleExceptionWithDelay(int currentErrorDelay) { // Don't delay on first exception @@ -226,6 +222,9 @@ public enum AcceptorState { - NEW, RUNNING, PAUSED, ENDED + NEW, + RUNNING, + PAUSED, + ENDED } } diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/net/ApplicationBufferHandler.java tomcat10-10.1.52/java/org/apache/tomcat/util/net/ApplicationBufferHandler.java --- tomcat10-10.1.40/java/org/apache/tomcat/util/net/ApplicationBufferHandler.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/net/ApplicationBufferHandler.java 2026-01-23 19:33:36.000000000 +0000 @@ -19,8 +19,7 @@ import java.nio.ByteBuffer; /** - * Callback interface to be able to expand buffers when buffer overflow - * exceptions happen or to replace buffers + * Callback interface to be able to expand buffers when buffer overflow exceptions happen or to replace buffers */ public interface ApplicationBufferHandler { @@ -30,9 +29,11 @@ @Override public void expand(int newSize) { } + @Override public void setByteBuffer(ByteBuffer buffer) { } + @Override public ByteBuffer getByteBuffer() { return EMPTY_BUFFER; @@ -41,6 +42,7 @@ /** * Set the byte buffer. + * * @param buffer the byte buffer */ void setByteBuffer(ByteBuffer buffer); @@ -52,6 +54,7 @@ /** * Expand the byte buffer to at least the given size. Some implementations may not implement this. + * * @param size the desired size */ void expand(int size); diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/net/Constants.java tomcat10-10.1.52/java/org/apache/tomcat/util/net/Constants.java --- tomcat10-10.1.40/java/org/apache/tomcat/util/net/Constants.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/net/Constants.java 2026-01-23 19:33:36.000000000 +0000 @@ -19,24 +19,23 @@ public class Constants { /** - * Name of the system property containing - * the tomcat instance installation path + * Name of the system property containing the tomcat instance installation path */ public static final String CATALINA_BASE_PROP = "catalina.base"; /** * JSSE and OpenSSL protocol names */ - public static final String SSL_PROTO_ALL = "all"; - public static final String SSL_PROTO_TLS = "TLS"; - public static final String SSL_PROTO_TLSv1_3 = "TLSv1.3"; - public static final String SSL_PROTO_TLSv1_2 = "TLSv1.2"; - public static final String SSL_PROTO_TLSv1_1 = "TLSv1.1"; + public static final String SSL_PROTO_ALL = "all"; + public static final String SSL_PROTO_TLS = "TLS"; + public static final String SSL_PROTO_TLSv1_3 = "TLSv1.3"; + public static final String SSL_PROTO_TLSv1_2 = "TLSv1.2"; + public static final String SSL_PROTO_TLSv1_1 = "TLSv1.1"; // Two different forms for TLS 1.0 - public static final String SSL_PROTO_TLSv1_0 = "TLSv1.0"; - public static final String SSL_PROTO_TLSv1 = "TLSv1"; - public static final String SSL_PROTO_SSLv3 = "SSLv3"; - public static final String SSL_PROTO_SSLv2 = "SSLv2"; + public static final String SSL_PROTO_TLSv1_0 = "TLSv1.0"; + public static final String SSL_PROTO_TLSv1 = "TLSv1"; + public static final String SSL_PROTO_SSLv3 = "SSLv3"; + public static final String SSL_PROTO_SSLv2 = "SSLv2"; public static final String SSL_PROTO_SSLv2Hello = "SSLv2Hello"; public static final boolean IS_SECURITY_ENABLED = (System.getSecurityManager() != null); diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/net/DispatchType.java tomcat10-10.1.52/java/org/apache/tomcat/util/net/DispatchType.java --- tomcat10-10.1.40/java/org/apache/tomcat/util/net/DispatchType.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/net/DispatchType.java 2026-01-23 19:33:36.000000000 +0000 @@ -17,9 +17,8 @@ package org.apache.tomcat.util.net; /** - * This enumeration lists the different types of dispatches that request - * processing can trigger. In this instance, dispatch means re-process this - * request using the given socket status. + * This enumeration lists the different types of dispatches that request processing can trigger. In this instance, + * dispatch means re-process this request using the given socket status. */ public enum DispatchType { diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/net/IPv6Utils.java tomcat10-10.1.52/java/org/apache/tomcat/util/net/IPv6Utils.java --- tomcat10-10.1.40/java/org/apache/tomcat/util/net/IPv6Utils.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/net/IPv6Utils.java 2026-01-23 19:33:36.000000000 +0000 @@ -17,9 +17,10 @@ package org.apache.tomcat.util.net; /** - *

      IPv6 utilities. - *

      For the moment, it only contains function to canonicalize IPv6 address - * into RFC 5952 form. + *

      + * IPv6 utilities. + *

      + * For the moment, it only contains function to canonicalize IPv6 address into RFC 5952 form. */ public class IPv6Utils { @@ -27,21 +28,25 @@ private static final int MAX_GROUP_LENGTH = 4; /** - *

      Convert IPv6 address into RFC 5952 form. - * E.g. 2001:db8:0:1:0:0:0:1 -> 2001:db8:0:1::1

      - * - *

      Method is null safe, and if IPv4 address or host name is passed to the - * method it is returned without any processing.

      - * - *

      Method also supports IPv4 in IPv6 (e.g. 0:0:0:0:0:ffff:192.0.2.1 -> - * ::ffff:192.0.2.1), and zone ID (e.g. fe80:0:0:0:f0f0:c0c0:1919:1234%4 - * -> fe80::f0f0:c0c0:1919:1234%4).

      - * - *

      The behaviour of this method is undefined if an invalid IPv6 address - * is passed in as input.

      + *

      + * Convert IPv6 address into RFC 5952 form. E.g. 2001:db8:0:1:0:0:0:1 -> 2001:db8:0:1::1 + *

      + *

      + * Method is null safe, and if IPv4 address or host name is passed to the method it is returned without any + * processing. + *

      + *

      + * Method also supports IPv4 in IPv6 (e.g. 0:0:0:0:0:ffff:192.0.2.1 -> ::ffff:192.0.2.1), and zone ID (e.g. + * fe80:0:0:0:f0f0:c0c0:1919:1234%4 -> fe80::f0f0:c0c0:1919:1234%4). + *

      + *

      + * The behaviour of this method is undefined if an invalid IPv6 address is passed in as input. + *

      * * @param ipv6Address String representing valid IPv6 address. + * * @return String representing IPv6 in canonical form. + * * @throws IllegalArgumentException if IPv6 format is unacceptable. */ public static String canonize(String ipv6Address) throws IllegalArgumentException { @@ -64,16 +69,12 @@ int lastColonsPos = ipv6Address.lastIndexOf("::"); if (lastColonsPos >= 0 && lastColonPos == lastColonsPos + 1) { /* - * IPv6 part ends with two consecutive colons, - * last colon is part of IPv6 format. - * e.g. ::127.0.0.1 + * IPv6 part ends with two consecutive colons, last colon is part of IPv6 format. e.g. ::127.0.0.1 */ ipv6AddressLength = lastColonPos + 1; } else { /* - * IPv6 part ends with only one colon, - * last colon is not part of IPv6 format. - * e.g. ::FFFF:127.0.0.1 + * IPv6 part ends with only one colon, last colon is not part of IPv6 format. e.g. ::FFFF:127.0.0.1 */ ipv6AddressLength = lastColonPos; } @@ -84,7 +85,7 @@ } StringBuilder result = new StringBuilder(); - char [][] groups = new char[MAX_NUMBER_OF_GROUPS][MAX_GROUP_LENGTH]; + char[][] groups = new char[MAX_NUMBER_OF_GROUPS][MAX_GROUP_LENGTH]; int groupCounter = 0; int charInGroupCounter = 0; @@ -100,8 +101,7 @@ boolean groupStart = true; /* - * Two consecutive colons, initial expansion. - * e.g. 2001:db8:0:0:1::1 -> 2001:db8:0:0:1:0:0:1 + * Two consecutive colons, initial expansion. e.g. 2001:db8:0:0:1::1 -> 2001:db8:0:0:1:0:0:1 */ StringBuilder expanded = new StringBuilder(ipv6Address); @@ -183,16 +183,15 @@ // Output results for (groupCounter = 0; groupCounter < numberOfGroups; groupCounter++) { - if (maxZeroGroupLength <= 1 || groupCounter < maxZeroGroupIndex - || groupCounter >= maxZeroGroupIndex + maxZeroGroupLength) { + if (maxZeroGroupLength <= 1 || groupCounter < maxZeroGroupIndex || + groupCounter >= maxZeroGroupIndex + maxZeroGroupLength) { for (int j = 0; j < MAX_GROUP_LENGTH; j++) { if (groups[groupCounter][j] != 0) { result.append(groups[groupCounter][j]); } } - if (groupCounter < (numberOfGroups - 1) - && (groupCounter != maxZeroGroupIndex - 1 - || maxZeroGroupLength <= 1)) { + if (groupCounter < (numberOfGroups - 1) && + (groupCounter != maxZeroGroupIndex - 1 || maxZeroGroupLength <= 1)) { result.append(':'); } } else if (groupCounter == maxZeroGroupIndex) { @@ -203,8 +202,8 @@ // Solve problem with three colons in IPv4 in IPv6 format // e.g. 0:0:0:0:0:0:127.0.0.1 -> :::127.0.0.1 -> ::127.0.0.1 int resultLength = result.length(); - if (result.charAt(resultLength - 1) == ':' && ipv6AddressLength < ipv6Address.length() - && ipv6Address.charAt(ipv6AddressLength) == ':') { + if (result.charAt(resultLength - 1) == ':' && ipv6AddressLength < ipv6Address.length() && + ipv6Address.charAt(ipv6AddressLength) == ':') { result.delete(resultLength - 1, resultLength); } @@ -222,6 +221,7 @@ * Heuristic check if string might be an IPv6 address. * * @param input Any string or null + * * @return true, if input string contains only hex digits and at least two colons, before '.' or '%' character */ static boolean mayBeIPv6Address(String input) { @@ -237,8 +237,7 @@ // IPv4 in IPv6 or Zone ID detected, end of checking. break; } - if (!((c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') - || (c >= 'A' && c <= 'F') || c == ':')) { + if (!((c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F') || c == ':')) { return false; } else if (c == ':') { colonsCounter++; diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/net/LocalStrings.properties tomcat10-10.1.52/java/org/apache/tomcat/util/net/LocalStrings.properties --- tomcat10-10.1.40/java/org/apache/tomcat/util/net/LocalStrings.properties 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/net/LocalStrings.properties 2026-01-23 19:33:36.000000000 +0000 @@ -73,6 +73,7 @@ endpoint.err.duplicateAccept=Duplicate socket accept detected. This is a known Linux kernel bug. The original connection has been processed normally and the duplicate has been ignored. The client should be unaffected. Updating the OS to a version that uses kernel 5.10 or later should fix the duplicate accept bug. endpoint.err.handshake=Handshake failed for client connection from IP address [{0}] and port [{1}] endpoint.err.unexpected=Unexpected error processing socket +endpoint.errorCreatingSSLContext=Error creating SSLContext endpoint.executor.fail=Executor rejected socket [{0}] for processing endpoint.getAttribute=[{0}] is [{1}] endpoint.init.bind=Socket bind failed: [{0}] [{1}] @@ -124,6 +125,7 @@ endpoint.tls.cert.noCerts=Certificate details not available as the certificate chain returned from the SSLContext was empty endpoint.tls.info=Connector [{0}], TLS virtual host [{1}], certificate type [{2}] configured from {3} with trust store [{4}] endpoint.tls.info.cert.keystore=keystore [{0}] using alias [{1}] +endpoint.tls.info.cert.keystore.direct=Set directly - location unknown endpoint.tls.info.cert.pem=key [{0}], certificate [{1}] and certificate chain [{2}] endpoint.unknownSslHostName=The SSL host name [{0}] is not recognised for this endpoint endpoint.warn.executorShutdown=The executor associated with thread pool [{0}] has not fully shutdown. Some application threads may still be running. @@ -151,10 +153,12 @@ sslHostConfig.certificate.notype=Multiple certificates were specified and at least one is missing the required attribute type sslHostConfig.certificateVerificationInvalid=The certificate verification value [{0}] is not recognised -sslHostConfig.certificateVerificationWithHttp2=The TLS virtual host [{0}] is configured for optional certificate verification and the enclosing connector is configured to support upgrade to h2. HTTP/2 over TLS does not permit optional certificate verification. sslHostConfig.fileNotFound=Configured file [{0}] does not exist +sslHostConfig.ignoreNonTls13Ciphersuite=The non-TLS 1.3 cipher suite [{0}] included in the TLS 1.3 cipher suite list will be ignored +sslHostConfig.ignoreTls13Ciphersuite=The TLS 1.3 cipher suite [{0}] included in the TLS 1.2 and below ciphers list will be ignored sslHostConfig.invalid_truststore_password=The provided trust store password could not be used to unlock and/or validate the trust store. Retrying to access the trust store with a null password which will skip validation. sslHostConfig.mismatch=The property [{0}] was set on the SSLHostConfig named [{1}] and is for the [{2}] configuration syntax but the SSLHostConfig is being used with the [{3}] configuration syntax +sslHostConfig.mismatch.trust=The trust configuration property [{0}] was set on the SSLHostConfig named [{1}] and is for the [{2}] configuration syntax but the SSLHostConfig is being used with the [{3}] trust configuration syntax sslHostConfig.opensslconf.alreadyset=Attempt to set another OpenSSLConf ignored sslHostConfig.opensslconf.null=Attempt to set null OpenSSLConf ignored sslHostConfig.prefix_missing=The protocol [{0}] was added to the list of protocols on the SSLHostConfig named [{1}]. Check if a +/- prefix is missing. diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/net/LocalStrings_fr.properties tomcat10-10.1.52/java/org/apache/tomcat/util/net/LocalStrings_fr.properties --- tomcat10-10.1.40/java/org/apache/tomcat/util/net/LocalStrings_fr.properties 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/net/LocalStrings_fr.properties 2026-01-23 19:33:36.000000000 +0000 @@ -73,6 +73,7 @@ endpoint.err.duplicateAccept=Le socket a été accpeté deux fois. Ceci est un bug connu du kernel Linux. La connection originelle a été traitée normalement et le doublon a été ignoré. Le client ne devrait pas être affecté. Mettre à jour l'OS vers une version qui utilise un kernel 5.10 ou plus récent devrait corriger le problème. endpoint.err.handshake=Echec de négociation endpoint.err.unexpected=Erreur inattendue lors du traitement du socket +endpoint.errorCreatingSSLContext=Erreur lors de la création du SSLContext endpoint.executor.fail=L''exécuteur a rejeté le traitement du socket [{0}] endpoint.getAttribute=[{0}] est [{1}] endpoint.init.bind=L''association du socket a échoué : [{0}] [{1}] @@ -151,7 +152,6 @@ sslHostConfig.certificate.notype=Plusieurs certificats ont été spécifiés et au moins un n'a pas d'attribut type sslHostConfig.certificateVerificationInvalid=La valeur de vérification de certificat [{0}] n''est pas reconnue -sslHostConfig.certificateVerificationWithHttp2=L''hôte virtuel TLS [{0}] est configuré avec la validation optionelle du certificat, et le connecteur qui l''utilise est configuré pour supporter l''upgrade vers h2. HTTP/2 sur TLS ne permet pas la validation optionelle du certificat. sslHostConfig.fileNotFound=Le fichier [{0}] configuré n''existe pas. sslHostConfig.invalid_truststore_password=Le mot de passe de la base de confiance n'a pas pu être utilisé pour déverrouiller et ou valider celle ci, nouvel essai en utilisant un mot de passe null pour passer la validation sslHostConfig.mismatch=La propriété [{0}] a été fixée sur le SSLHostConfig nommé [{1}] et est pour la syntaxe de configuration [{2}] mais le SSLHostConfig est utilisé avec la syntaxe de configuration [{3}] diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/net/LocalStrings_ja.properties tomcat10-10.1.52/java/org/apache/tomcat/util/net/LocalStrings_ja.properties --- tomcat10-10.1.40/java/org/apache/tomcat/util/net/LocalStrings_ja.properties 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/net/LocalStrings_ja.properties 2026-01-23 19:33:36.000000000 +0000 @@ -73,10 +73,11 @@ endpoint.err.duplicateAccept=重複したソケット受け付けが検出されました。 これはLinuxカーネルの既知のバグです。 最初のコネクションは正常に処理され、重複受け付けは無視されました。 クライアントは影響を受けないはずです。Linuxカーネルをバージョン5.10以降に更新すると、重複受け付けのバグが修正されます。 endpoint.err.handshake=ハンドシェイク失敗 endpoint.err.unexpected=ソケット処理中の予期せぬエラー +endpoint.errorCreatingSSLContext=SSLContextの作成中にエラーが発生しました endpoint.executor.fail=エグゼキュータは処理するソケット [{0}] を拒否しました endpoint.getAttribute=[{0}] は [{1}] です endpoint.init.bind=ソケットバインドに失敗しました:[{0}] [{1}] -endpoint.init.bind.inherited=コネクタが1つを使用するように構成されている間、継承されたチャネルはありません。 +endpoint.init.bind.inherited=コネクタは継承されたチャネルを使用するように設定されていますが、継承すべきチャネルが存在しません endpoint.init.listen=ソケットの待ち受けを開始できません: [{0}] [{1}] endpoint.init.unixnotavail=Unixドメインソケットのサポートは利用できません endpoint.invalidJmxNameSslHost=ホスト [{0}] に関連付けられた SSLHostConfig に有効な JMX オブジェクト名を生成できません。 @@ -124,6 +125,7 @@ endpoint.tls.cert.noCerts=SSLContext から返された証明書チェーンが空だったため、証明書の詳細を利用できません endpoint.tls.info=トラストストア [{4}] を使用して {3} から構成されたコネクタ [{0}]、TLS 仮想ホスト [{1}]、および証明書タイプ [{2}] endpoint.tls.info.cert.keystore=エイリアス [{1}] を使用したキーストア [{0}] +endpoint.tls.info.cert.keystore.direct=直接設定 - 場所が不明 endpoint.tls.info.cert.pem=キー [{0}]、証明書 [{1}]、および証明書チェーン [{2}] endpoint.unknownSslHostName=SSL ホスト名 [{0}] はこのエンドポイントから認識されていません。 endpoint.warn.executorShutdown=スレッドプール [{0}] と関連付けられたエグゼキュータは完全に停止できませんでした。いくつかのアプリケーションスレッドはまだ動作し続けている可能性があります。 @@ -151,7 +153,6 @@ sslHostConfig.certificate.notype=指定された複数の証明書の中に、少なくとも1つは必須要素の存在しない証明書が含まれています。 sslHostConfig.certificateVerificationInvalid=証明書検証値[{0}]が認識されません -sslHostConfig.certificateVerificationWithHttp2=TLS仮想ホスト[{0}]はオプションの証明書検証用に構成されており、コネクタはh2へのアップグレードをサポートするように構成されています。 HTTP/2 over TLSでは、オプションの証明書検証は許可されていません。 sslHostConfig.fileNotFound=構成ファイル[{0}]は存在しません sslHostConfig.invalid_truststore_password=提供されたトラストストアパスワードは、トラストストアのロック解除および検証に使用できませんでした。 検証をスキップするnullパスワードでトラストストアにアクセスしようとしました。 sslHostConfig.mismatch=[{0}] プロパティは [{1}] という名前のSSLHostConfigで設定され、[{2}] 構成構文用ですが、[{3}] 構成構文でSSLHostConfigが使用されています diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/net/LocalStrings_ko.properties tomcat10-10.1.52/java/org/apache/tomcat/util/net/LocalStrings_ko.properties --- tomcat10-10.1.40/java/org/apache/tomcat/util/net/LocalStrings_ko.properties 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/net/LocalStrings_ko.properties 2026-01-23 19:33:36.000000000 +0000 @@ -141,7 +141,6 @@ sslHostConfig.certificate.notype=여러 개의 인증서들이 지정되었는데, 적어도 하나의 인증서에 필수 속성 타입이 없습니다. sslHostConfig.certificateVerificationInvalid=인증서 검증 값 [{0}]은(는) 인식되지 않는 값입니다. -sslHostConfig.certificateVerificationWithHttp2=TLS 가상 호스트 [{0}](은)는 선택적 인증서 확인을 하도록 설정되었고, 내부에 정의된 커넥터는 HTTP/2로 업그레이드를 지원하도록 설정되었습니다. TLS 기반의 HTTP/2는 선택적 인증서 확인을 허용하지 않습니다. sslHostConfig.fileNotFound=설정된 파일 [{0}]이(가) 존재하지 않습니다. sslHostConfig.invalid_truststore_password=Trust 저장소를 잠금을 풀거나 유효한지 확인하는 용도로, 제공된 Trust 저장소 비밀번호를 사용할 수 없었습니다. 널 비밀번호를 사용하여, 해당 Trust 저장소에 대한 접근을 다시 시도합니다. 이는 유효한지 확인하는 작업을 건너뛸 것입니다. sslHostConfig.mismatch=[{1}](이)라는 이름의 SSLHostConfig에 프로퍼티 [{0}]이(가) 설정되었는데, 이 프로퍼티는 [{2}] 설정 문법을 위한 것이나, 해당 SSLHostConfig은 [{3}] 설정 문법으로 사용되고 있습니다. diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/net/LocalStrings_zh_CN.properties tomcat10-10.1.52/java/org/apache/tomcat/util/net/LocalStrings_zh_CN.properties --- tomcat10-10.1.40/java/org/apache/tomcat/util/net/LocalStrings_zh_CN.properties 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/net/LocalStrings_zh_CN.properties 2026-01-23 19:33:36.000000000 +0000 @@ -143,7 +143,6 @@ sslHostConfig.certificate.notype=指定了多个证书,并且至少有一个证书缺少必需的属性类型 sslHostConfig.certificateVerificationInvalid=证书认证值[{0}]未识别 -sslHostConfig.certificateVerificationWithHttp2=TLS虚拟主机[{0}]被配置为可选的证书验证,包围的连接器被配置为支持升级到h2。HTTP/2 over TLS不允许可选的证书验证。 sslHostConfig.fileNotFound=配置文件 [{0}] 不存在 sslHostConfig.invalid_truststore_password=提供的信任存储密码无法用于解锁和/或验证信任存储。正在重试使用空密码访问信任存储,该密码将跳过验证。 sslHostConfig.mismatch=属性[{0}]是在名为[{1}]的SSLHostConfig 上设置的,用于[{2}]配置语法,但SSLHostConfig 正与[{3}]配置语法一起使用 diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/net/Nio2Channel.java tomcat10-10.1.52/java/org/apache/tomcat/util/net/Nio2Channel.java --- tomcat10-10.1.40/java/org/apache/tomcat/util/net/Nio2Channel.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/net/Nio2Channel.java 2026-01-23 19:33:36.000000000 +0000 @@ -28,9 +28,8 @@ import java.util.concurrent.TimeoutException; /** - * Base class for a SocketChannel wrapper used by the endpoint. - * This way, logic for an SSL socket channel remains the same as for - * a non SSL, making sure we don't need to code for any exception cases. + * Base class for a SocketChannel wrapper used by the endpoint. This way, logic for an SSL socket channel remains the + * same as for a non SSL, making sure we don't need to code for any exception cases. */ public class Nio2Channel implements AsynchronousByteChannel { @@ -47,7 +46,7 @@ /** * Reset the channel. * - * @param channel The new async channel to associate with this NIO2 channel + * @param channel The new async channel to associate with this NIO2 channel * @param socketWrapper The new socket to associate with this NIO2 channel * * @throws IOException If a problem was encountered resetting the channel @@ -123,8 +122,7 @@ } /** - * Performs SSL handshake hence is a no-op for the non-secure - * implementation. + * Performs SSL handshake hence is a no-op for the non-secure implementation. * * @return Always returns zero * @@ -145,20 +143,17 @@ } @Override - public void read(ByteBuffer dst, A attachment, - CompletionHandler handler) { + public void read(ByteBuffer dst, A attachment, CompletionHandler handler) { read(dst, 0L, TimeUnit.MILLISECONDS, attachment, handler); } - public void read(ByteBuffer dst, - long timeout, TimeUnit unit, A attachment, - CompletionHandler handler) { + public void read(ByteBuffer dst, long timeout, TimeUnit unit, A attachment, + CompletionHandler handler) { sc.read(dst, timeout, unit, attachment, handler); } - public void read(ByteBuffer[] dsts, - int offset, int length, long timeout, TimeUnit unit, - A attachment, CompletionHandler handler) { + public void read(ByteBuffer[] dsts, int offset, int length, long timeout, TimeUnit unit, A attachment, + CompletionHandler handler) { sc.read(dsts, offset, length, timeout, unit, attachment, handler); } @@ -168,18 +163,16 @@ } @Override - public void write(ByteBuffer src, A attachment, - CompletionHandler handler) { + public void write(ByteBuffer src, A attachment, CompletionHandler handler) { write(src, 0L, TimeUnit.MILLISECONDS, attachment, handler); } public void write(ByteBuffer src, long timeout, TimeUnit unit, A attachment, - CompletionHandler handler) { + CompletionHandler handler) { sc.write(src, timeout, unit, attachment, handler); } - public void write(ByteBuffer[] srcs, int offset, int length, - long timeout, TimeUnit unit, A attachment, + public void write(ByteBuffer[] srcs, int offset, int length, long timeout, TimeUnit unit, A attachment, CompletionHandler handler) { sc.write(srcs, offset, length, timeout, unit, attachment, handler); } @@ -189,23 +182,25 @@ public boolean cancel(boolean mayInterruptIfRunning) { return false; } + @Override public boolean isCancelled() { return false; } + @Override public boolean isDone() { return true; } + @Override - public Boolean get() throws InterruptedException, - ExecutionException { + public Boolean get() throws InterruptedException, ExecutionException { return Boolean.TRUE; } + @Override public Boolean get(long timeout, TimeUnit unit) - throws InterruptedException, ExecutionException, - TimeoutException { + throws InterruptedException, ExecutionException, TimeoutException { return Boolean.TRUE; } }; @@ -215,9 +210,11 @@ } private ApplicationBufferHandler appReadBufHandler; + public void setAppReadBufHandler(ApplicationBufferHandler handler) { this.appReadBufHandler = handler; } + protected ApplicationBufferHandler getAppReadBufHandler() { return appReadBufHandler; } @@ -227,23 +224,25 @@ public boolean cancel(boolean mayInterruptIfRunning) { return false; } + @Override public boolean isCancelled() { return false; } + @Override public boolean isDone() { return true; } + @Override - public Integer get() throws InterruptedException, - ExecutionException { + public Integer get() throws InterruptedException, ExecutionException { return Integer.valueOf(-1); } + @Override public Integer get(long timeout, TimeUnit unit) - throws InterruptedException, ExecutionException, - TimeoutException { + throws InterruptedException, ExecutionException, TimeoutException { return Integer.valueOf(-1); } }; @@ -252,54 +251,63 @@ @Override public void close() throws IOException { } + @Override public boolean isOpen() { return false; } + @Override public void reset(AsynchronousSocketChannel channel, SocketWrapperBase socket) throws IOException { } + @Override public void free() { } + @Override protected ApplicationBufferHandler getAppReadBufHandler() { return ApplicationBufferHandler.EMPTY; } + @Override public void setAppReadBufHandler(ApplicationBufferHandler handler) { } + @Override public Future read(ByteBuffer dst) { return DONE_INT; } + @Override - public void read(ByteBuffer dst, - long timeout, TimeUnit unit, A attachment, - CompletionHandler handler) { + public void read(ByteBuffer dst, long timeout, TimeUnit unit, A attachment, + CompletionHandler handler) { handler.failed(new ClosedChannelException(), attachment); } + @Override - public void read(ByteBuffer[] dsts, - int offset, int length, long timeout, TimeUnit unit, - A attachment, CompletionHandler handler) { + public void read(ByteBuffer[] dsts, int offset, int length, long timeout, TimeUnit unit, A attachment, + CompletionHandler handler) { handler.failed(new ClosedChannelException(), attachment); } + @Override public Future write(ByteBuffer src) { return DONE_INT; } + @Override public void write(ByteBuffer src, long timeout, TimeUnit unit, A attachment, - CompletionHandler handler) { + CompletionHandler handler) { handler.failed(new ClosedChannelException(), attachment); } + @Override - public void write(ByteBuffer[] srcs, int offset, int length, - long timeout, TimeUnit unit, A attachment, + public void write(ByteBuffer[] srcs, int offset, int length, long timeout, TimeUnit unit, A attachment, CompletionHandler handler) { handler.failed(new ClosedChannelException(), attachment); } + @Override public String toString() { return "Closed Nio2Channel"; diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/net/Nio2Endpoint.java tomcat10-10.1.52/java/org/apache/tomcat/util/net/Nio2Endpoint.java --- tomcat10-10.1.40/java/org/apache/tomcat/util/net/Nio2Endpoint.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/net/Nio2Endpoint.java 2026-01-23 19:33:36.000000000 +0000 @@ -150,14 +150,12 @@ paused = false; if (socketProperties.getProcessorCache() != 0) { - processorCache = new SynchronizedStack<>(SynchronizedStack.DEFAULT_SIZE, - socketProperties.getProcessorCache()); + processorCache = + new SynchronizedStack<>(SynchronizedStack.DEFAULT_SIZE, socketProperties.getProcessorCache()); } - int actualBufferPool = - socketProperties.getActualBufferPool(isSSLEnabled() ? getSniParseLimit() * 2 : 0); + int actualBufferPool = socketProperties.getActualBufferPool(isSSLEnabled() ? getSniParseLimit() * 2 : 0); if (actualBufferPool != 0) { - nioChannels = new SynchronizedStack<>(SynchronizedStack.DEFAULT_SIZE, - actualBufferPool); + nioChannels = new SynchronizedStack<>(SynchronizedStack.DEFAULT_SIZE, actualBufferPool); } // Create worker collection if (getExecutor() == null) { @@ -291,10 +289,11 @@ /** * Process the specified connection. + * * @param socket The socket channel - * @return true if the socket was correctly configured - * and processing may continue, false if the socket needs to be - * close immediately + * + * @return true if the socket was correctly configured and processing may continue, false + * if the socket needs to be close immediately */ @Override protected boolean setSocketOptions(AsynchronousSocketChannel socket) { @@ -306,10 +305,8 @@ channel = nioChannels.pop(); } if (channel == null) { - SocketBufferHandler bufhandler = new SocketBufferHandler( - socketProperties.getAppReadBufSize(), - socketProperties.getAppWriteBufSize(), - socketProperties.getDirectBuffer()); + SocketBufferHandler bufhandler = new SocketBufferHandler(socketProperties.getAppReadBufSize(), + socketProperties.getAppWriteBufSize(), socketProperties.getDirectBuffer()); if (isSSLEnabled()) { channel = new SecureNio2Channel(bufhandler, this); } else { @@ -398,18 +395,18 @@ @Override - protected SocketProcessorBase createSocketProcessor( - SocketWrapperBase socketWrapper, SocketEvent event) { + protected SocketProcessorBase createSocketProcessor(SocketWrapperBase socketWrapper, + SocketEvent event) { return new SocketProcessor(socketWrapper, event); } protected class Nio2Acceptor extends Acceptor - implements CompletionHandler { + implements CompletionHandler { protected int errorDelay = 0; - public Nio2Acceptor(AbstractEndpoint endpoint) { + public Nio2Acceptor(AbstractEndpoint endpoint) { super(endpoint); } @@ -417,7 +414,7 @@ public void run() { // The initial accept will be called in a separate utility thread if (!isPaused()) { - //if we have reached max connections, wait + // if we have reached max connections, wait try { countUpOrAwaitConnection(); } catch (InterruptedException e) { @@ -439,7 +436,6 @@ * Signals the Acceptor to stop. * * @param waitMilliseconds Ignored for NIO2. - * */ @Override public void stopMillis(int waitMilliseconds) { @@ -447,8 +443,7 @@ } @Override - public void completed(AsynchronousSocketChannel socket, - Void attachment) { + public void completed(AsynchronousSocketChannel socket, Void attachment) { // Successful accept, reset the error delay errorDelay = 0; // Continue processing the socket on the current thread @@ -512,17 +507,16 @@ private SendfileData sendfileData = null; - private final CompletionHandler readCompletionHandler; + private final CompletionHandler readCompletionHandler; private boolean readInterest = false; // Guarded by readCompletionHandler private boolean readNotify = false; - private final CompletionHandler writeCompletionHandler; - private final CompletionHandler gatheringWriteCompletionHandler; + private final CompletionHandler writeCompletionHandler; + private final CompletionHandler gatheringWriteCompletionHandler; private boolean writeInterest = false; // Guarded by writeCompletionHandler private boolean writeNotify = false; - private final CompletionHandler sendfileHandler - = new CompletionHandler<>() { + private final CompletionHandler sendfileHandler = new CompletionHandler<>() { @Override public void completed(Integer nWrite, SendfileData attachment) { @@ -545,21 +539,21 @@ attachment.doneInline = true; } else { switch (attachment.keepAliveState) { - case NONE: { - getEndpoint().processSocket(Nio2SocketWrapper.this, - SocketEvent.DISCONNECT, false); - break; - } - case PIPELINED: { - if (!getEndpoint().processSocket(Nio2SocketWrapper.this, SocketEvent.OPEN_READ, true)) { - close(); + case NONE: { + getEndpoint().processSocket(Nio2SocketWrapper.this, SocketEvent.DISCONNECT, false); + break; + } + case PIPELINED: { + if (!getEndpoint().processSocket(Nio2SocketWrapper.this, SocketEvent.OPEN_READ, + true)) { + close(); + } + break; + } + case OPEN: { + registerReadInterest(); + break; } - break; - } - case OPEN: { - registerReadInterest(); - break; - } } } return; @@ -635,6 +629,7 @@ getEndpoint().processSocket(Nio2SocketWrapper.this, SocketEvent.OPEN_READ, false); } } + @Override public void failed(Throwable exc, ByteBuffer attachment) { IOException ioe; @@ -667,13 +662,12 @@ } else if (!nonBlockingWriteBuffer.isEmpty()) { // Continue writing data using a gathering write ByteBuffer[] array = nonBlockingWriteBuffer.toArray(attachment); - getSocket().write(array, 0, array.length, - toTimeout(getWriteTimeout()), TimeUnit.MILLISECONDS, - array, gatheringWriteCompletionHandler); + getSocket().write(array, 0, array.length, toTimeout(getWriteTimeout()), + TimeUnit.MILLISECONDS, array, gatheringWriteCompletionHandler); } else if (attachment.hasRemaining()) { // Regular write - getSocket().write(attachment, toTimeout(getWriteTimeout()), - TimeUnit.MILLISECONDS, attachment, writeCompletionHandler); + getSocket().write(attachment, toTimeout(getWriteTimeout()), TimeUnit.MILLISECONDS, + attachment, writeCompletionHandler); } else { // All data has been written if (writeInterest && !isInline()) { @@ -694,6 +688,7 @@ } } } + @Override public void failed(Throwable exc, ByteBuffer attachment) { IOException ioe; @@ -718,12 +713,12 @@ writeNotify = false; if (nBytes.longValue() < 0) { failed(new EOFException(sm.getString("iob.failedwrite")), attachment); - } else if (!nonBlockingWriteBuffer.isEmpty() || buffersArrayHasRemaining(attachment, 0, attachment.length)) { + } else if (!nonBlockingWriteBuffer.isEmpty() || + buffersArrayHasRemaining(attachment, 0, attachment.length)) { // Continue writing data using a gathering write ByteBuffer[] array = nonBlockingWriteBuffer.toArray(attachment); - getSocket().write(array, 0, array.length, - toTimeout(getWriteTimeout()), TimeUnit.MILLISECONDS, - array, gatheringWriteCompletionHandler); + getSocket().write(array, 0, array.length, toTimeout(getWriteTimeout()), + TimeUnit.MILLISECONDS, array, gatheringWriteCompletionHandler); } else { // All data has been written if (writeInterest && !isInline()) { @@ -744,6 +739,7 @@ } } } + @Override public void failed(Throwable exc, ByteBuffer[] attachment) { IOException ioe; @@ -757,14 +753,19 @@ if (!endpoint.processSocket(Nio2SocketWrapper.this, SocketEvent.ERROR, true)) { close(); } - } + } }; } - public void setSendfileData(SendfileData sf) { this.sendfileData = sf; } - public SendfileData getSendfileData() { return this.sendfileData; } + public void setSendfileData(SendfileData sf) { + this.sendfileData = sf; + } + + public SendfileData getSendfileData() { + return this.sendfileData; + } @Override public boolean isReadyForRead() throws IOException { @@ -971,6 +972,7 @@ getSocket().close(true); } if (getEndpoint().running) { + getSocket().reset(null, null); if (nioChannels == null || !nioChannels.push(getSocket())) { getSocket().free(); } @@ -1014,22 +1016,21 @@ } @Override - protected OperationState newOperationState(boolean read, - ByteBuffer[] buffers, int offset, int length, - BlockingMode block, long timeout, TimeUnit unit, A attachment, - CompletionCheck check, CompletionHandler handler, - Semaphore semaphore, VectoredIOCompletionHandler completion) { - return new Nio2OperationState<>(read, buffers, offset, length, block, - timeout, unit, attachment, check, handler, semaphore, completion); + protected OperationState newOperationState(boolean read, ByteBuffer[] buffers, int offset, int length, + BlockingMode block, long timeout, TimeUnit unit, A attachment, CompletionCheck check, + CompletionHandler handler, Semaphore semaphore, + VectoredIOCompletionHandler completion) { + return new Nio2OperationState<>(read, buffers, offset, length, block, timeout, unit, attachment, check, + handler, semaphore, completion); } private class Nio2OperationState extends OperationState { - private Nio2OperationState(boolean read, ByteBuffer[] buffers, int offset, int length, - BlockingMode block, long timeout, TimeUnit unit, A attachment, - CompletionCheck check, CompletionHandler handler, - Semaphore semaphore, VectoredIOCompletionHandler completion) { - super(read, buffers, offset, length, block, - timeout, unit, attachment, check, handler, semaphore, completion); + private Nio2OperationState(boolean read, ByteBuffer[] buffers, int offset, int length, BlockingMode block, + long timeout, TimeUnit unit, A attachment, CompletionCheck check, + CompletionHandler handler, Semaphore semaphore, + VectoredIOCompletionHandler completion) { + super(read, buffers, offset, length, block, timeout, unit, attachment, check, handler, semaphore, + completion); } @Override @@ -1084,26 +1085,27 @@ socketBufferHandler.configureWriteBufferForRead(); ByteBuffer[] array = nonBlockingWriteBuffer.toArray(socketBufferHandler.getWriteBuffer()); if (buffersArrayHasRemaining(array, 0, array.length)) { - getSocket().write(array, 0, array.length, timeout, unit, - array, new CompletionHandler<>() { - @Override - public void completed(Long nBytes, ByteBuffer[] buffers) { - if (nBytes.longValue() < 0) { - failed(new EOFException(), null); - } else if (buffersArrayHasRemaining(buffers, 0, buffers.length)) { - getSocket().write(buffers, 0, buffers.length, toTimeout(getWriteTimeout()), - TimeUnit.MILLISECONDS, buffers, this); - } else { - // Continue until everything is written - process(); + getSocket().write(array, 0, array.length, timeout, unit, array, + new CompletionHandler<>() { + @Override + public void completed(Long nBytes, ByteBuffer[] buffers) { + if (nBytes.longValue() < 0) { + failed(new EOFException(), null); + } else if (buffersArrayHasRemaining(buffers, 0, buffers.length)) { + getSocket().write(buffers, 0, buffers.length, + toTimeout(getWriteTimeout()), TimeUnit.MILLISECONDS, + buffers, this); + } else { + // Continue until everything is written + process(); + } } - } - @Override - public void failed(Throwable exc, ByteBuffer[] buffers) { - completion.failed(exc, Nio2OperationState.this); - } - }); + @Override + public void failed(Throwable exc, ByteBuffer[] buffers) { + completion.failed(exc, Nio2OperationState.this); + } + }); return; } } @@ -1113,12 +1115,12 @@ } } - /* Callers of this method must: - * - have acquired the readPending semaphore - * - have acquired a lock on readCompletionHandler + /* + * Callers of this method must: - have acquired the readPending semaphore - have acquired a lock on + * readCompletionHandler * - * This method will release (or arrange for the release of) the - * readPending semaphore once the read has completed. + * This method will release (or arrange for the release of) the readPending semaphore once the read has + * completed. */ private int fillReadBuffer(boolean block) throws IOException { socketBufferHandler.configureReadBufferForWrite(); @@ -1155,8 +1157,7 @@ } } else { startInline(); - getSocket().read(to, toTimeout(getReadTimeout()), TimeUnit.MILLISECONDS, to, - readCompletionHandler); + getSocket().read(to, toTimeout(getReadTimeout()), TimeUnit.MILLISECONDS, to, readCompletionHandler); endInline(); if (readPending.availablePermits() == 1) { nRead = to.position(); @@ -1169,9 +1170,8 @@ /** * {@inheritDoc} *

      - * Overridden for NIO2 to enable a gathering write to be used to write - * all of the remaining data in a single additional write should a - * non-blocking write leave data in the buffer. + * Overridden for NIO2 to enable a gathering write to be used to write all of the remaining data in a single + * additional write should a non-blocking write leave data in the buffer. */ @Override protected void writeNonBlocking(byte[] buf, int off, int len) throws IOException { @@ -1207,9 +1207,8 @@ /** * {@inheritDoc} *

      - * Overridden for NIO2 to enable a gathering write to be used to write - * all of the remaining data in a single additional write should a - * non-blocking write leave data in the buffer. + * Overridden for NIO2 to enable a gathering write to be used to write all of the remaining data in a single + * additional write should a non-blocking write leave data in the buffer. */ @Override protected void writeNonBlocking(ByteBuffer from) throws IOException { @@ -1220,9 +1219,8 @@ /** * {@inheritDoc} *

      - * Overridden for NIO2 to enable a gathering write to be used to write - * all of the remaining data in a single additional write should a - * non-blocking write leave data in the buffer. + * Overridden for NIO2 to enable a gathering write to be used to write all of the remaining data in a single + * additional write should a non-blocking write leave data in the buffer. */ @Override protected void writeNonBlockingInternal(ByteBuffer from) throws IOException { @@ -1254,8 +1252,7 @@ /** - * @param block Ignored since this method is only called in the - * blocking case + * @param block Ignored since this method is only called in the blocking case */ @Override protected void doWrite(boolean block, ByteBuffer from) throws IOException { @@ -1322,15 +1319,14 @@ if (!nonBlockingWriteBuffer.isEmpty()) { ByteBuffer[] array = nonBlockingWriteBuffer.toArray(socketBufferHandler.getWriteBuffer()); startInline(); - getSocket().write(array, 0, array.length, toTimeout(getWriteTimeout()), - TimeUnit.MILLISECONDS, array, gatheringWriteCompletionHandler); + getSocket().write(array, 0, array.length, toTimeout(getWriteTimeout()), TimeUnit.MILLISECONDS, + array, gatheringWriteCompletionHandler); endInline(); } else if (socketBufferHandler.getWriteBuffer().hasRemaining()) { // Regular write startInline(); getSocket().write(socketBufferHandler.getWriteBuffer(), toTimeout(getWriteTimeout()), - TimeUnit.MILLISECONDS, socketBufferHandler.getWriteBuffer(), - writeCompletionHandler); + TimeUnit.MILLISECONDS, socketBufferHandler.getWriteBuffer(), writeCompletionHandler); endInline(); } else { // Nothing was written @@ -1348,8 +1344,7 @@ @Override public boolean hasDataToRead() { synchronized (readCompletionHandler) { - return !socketBufferHandler.isReadBufferEmpty() - || readNotify || getError() != null; + return !socketBufferHandler.isReadBufferEmpty() || readNotify || getError() != null; } } @@ -1357,8 +1352,8 @@ @Override public boolean hasDataToWrite() { synchronized (writeCompletionHandler) { - return !socketBufferHandler.isWriteBufferEmpty() || !nonBlockingWriteBuffer.isEmpty() - || writeNotify || writePending.availablePermits() == 0 || getError() != null; + return !socketBufferHandler.isWriteBufferEmpty() || !nonBlockingWriteBuffer.isEmpty() || writeNotify || + writePending.availablePermits() == 0 || getError() != null; } } @@ -1462,8 +1457,7 @@ data.length -= nRead; getSocket().getBufHandler().configureWriteBufferForRead(); startInline(); - getSocket().write(buffer, toTimeout(getWriteTimeout()), TimeUnit.MILLISECONDS, - data, sendfileHandler); + getSocket().write(buffer, toTimeout(getWriteTimeout()), TimeUnit.MILLISECONDS, data, sendfileHandler); endInline(); if (data.doneInline) { if (data.error) { @@ -1634,8 +1628,7 @@ // ---------------------------------------------- SocketProcessor Inner Class /** - * This class is the equivalent of the Worker, but will simply use in an - * external Executor thread pool. + * This class is the equivalent of the Worker, but will simply use in an external Executor thread pool. */ protected class SocketProcessor extends SocketProcessorBase { @@ -1673,21 +1666,22 @@ } catch (IOException x) { handshake = -1; if (logHandshake.isDebugEnabled()) { - logHandshake.debug(sm.getString("endpoint.err.handshake", - socketWrapper.getRemoteAddr(), Integer.toString(socketWrapper.getRemotePort())), x); + logHandshake.debug(sm.getString("endpoint.err.handshake", socketWrapper.getRemoteAddr(), + Integer.toString(socketWrapper.getRemotePort())), x); } } if (handshake == 0) { SocketState state; // Process the request from this socket - state = getHandler().process(socketWrapper, Objects.requireNonNullElse(event, SocketEvent.OPEN_READ)); + state = getHandler().process(socketWrapper, + Objects.requireNonNullElse(event, SocketEvent.OPEN_READ)); if (state == SocketState.CLOSED) { // Close socket and pool socketWrapper.close(); } else if (state == SocketState.UPGRADING) { launch = true; } - } else if (handshake == -1 ) { + } else if (handshake == -1) { getHandler().process(socketWrapper, SocketEvent.CONNECT_FAIL); socketWrapper.close(); } @@ -1704,14 +1698,13 @@ getExecutor().execute(new SocketProcessor(socketWrapper, SocketEvent.OPEN_READ)); } catch (NullPointerException npe) { if (running) { - log.error(sm.getString("endpoint.launch.fail"), - npe); + log.error(sm.getString("endpoint.launch.fail"), npe); } } } socketWrapper = null; event = null; - //return to cache + // return to cache if (running && processorCache != null) { processorCache.push(this); } diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/net/NioChannel.java tomcat10-10.1.52/java/org/apache/tomcat/util/net/NioChannel.java --- tomcat10-10.1.40/java/org/apache/tomcat/util/net/NioChannel.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/net/NioChannel.java 2026-01-23 19:33:36.000000000 +0000 @@ -28,9 +28,8 @@ import org.apache.tomcat.util.res.StringManager; /** - * Base class for a SocketChannel wrapper used by the endpoint. - * This way, logic for an SSL socket channel remains the same as for - * a non SSL, making sure we don't need to code for any exception cases. + * Base class for a SocketChannel wrapper used by the endpoint. This way, logic for an SSL socket channel remains the + * same as for a non SSL, making sure we don't need to code for any exception cases. */ public class NioChannel implements ByteChannel, ScatteringByteChannel, GatheringByteChannel { @@ -49,12 +48,17 @@ /** * Reset the channel * - * @param channel the socket channel + * @param channel the socket channel * @param socketWrapper the socket wrapper + * * @throws IOException If a problem was encountered resetting the channel */ public void reset(SocketChannel channel, NioSocketWrapper socketWrapper) throws IOException { - this.sc = channel; + // Don't reset socket on null as it can lead to NPEs + if (channel != null) { + this.sc = channel; + } + // Resetting socketWrapper is possible this.socketWrapper = socketWrapper; bufHandler.reset(); } @@ -87,6 +91,7 @@ * Close the connection. * * @param force Should the underlying socket be forcibly closed? + * * @throws IOException If closing the secure channel fails. */ public void close(boolean force) throws IOException { @@ -109,7 +114,9 @@ * Writes a sequence of bytes to this channel from the given buffer. * * @param src The buffer from which bytes are to be retrieved + * * @return The number of bytes written, possibly zero + * * @throws IOException If some other I/O error occurs */ @Override @@ -128,8 +135,7 @@ } @Override - public long write(ByteBuffer[] srcs, int offset, int length) - throws IOException { + public long write(ByteBuffer[] srcs, int offset, int length) throws IOException { checkInterruptStatus(); return sc.write(srcs, offset, length); } @@ -138,8 +144,9 @@ * Reads a sequence of bytes from this channel into the given buffer. * * @param dst The buffer into which bytes are to be transferred - * @return The number of bytes read, possibly zero, or -1 if - * the channel has reached end-of-stream + * + * @return The number of bytes read, possibly zero, or -1 if the channel has reached end-of-stream + * * @throws IOException If some other I/O error occurs */ @Override @@ -153,8 +160,7 @@ } @Override - public long read(ByteBuffer[] dsts, int offset, int length) - throws IOException { + public long read(ByteBuffer[] dsts, int offset, int length) throws IOException { return sc.read(dsts, offset, length); } @@ -175,12 +181,13 @@ } /** - * Performs SSL handshake hence is a no-op for the non-secure - * implementation. + * Performs SSL handshake hence is a no-op for the non-secure implementation. * * @param read Unused in non-secure implementation * @param write Unused in non-secure implementation + * * @return Always returns zero + * * @throws IOException Never for non-secure channel */ public int handshake(boolean read, boolean write) throws IOException { @@ -200,6 +207,7 @@ * Return true if the buffer wrote data. NO-OP for non-secure channel. * * @return Always returns {@code false} for non-secure channel + * * @throws IOException Never for non-secure channel */ public boolean flushOutbound() throws IOException { @@ -207,13 +215,10 @@ } /** - * This method should be used to check the interrupt status before - * attempting a write. - * If a thread has been interrupted and the interrupt has not been cleared - * then an attempt to write to the socket will fail. When this happens the - * socket is removed from the poller without the socket being selected. This - * results in a connection limit leak for NIO as the endpoint expects the - * socket to be selected even in error conditions. + * This method should be used to check the interrupt status before attempting a write. If a thread has been + * interrupted and the interrupt has not been cleared then an attempt to write to the socket will fail. When this + * happens the socket is removed from the poller without the socket being selected. This results in a connection + * limit leak for NIO as the endpoint expects the socket to be selected even in error conditions. * * @throws IOException If the current thread was interrupted */ @@ -224,9 +229,11 @@ } private ApplicationBufferHandler appReadBufHandler; + public void setAppReadBufHandler(ApplicationBufferHandler handler) { this.appReadBufHandler = handler; } + protected ApplicationBufferHandler getAppReadBufHandler() { return appReadBufHandler; } @@ -235,42 +242,50 @@ @Override public void close() throws IOException { } + @Override public boolean isOpen() { return false; } + @Override public void reset(SocketChannel channel, NioSocketWrapper socketWrapper) throws IOException { } + @Override public void free() { } + @Override protected ApplicationBufferHandler getAppReadBufHandler() { return ApplicationBufferHandler.EMPTY; } + @Override public void setAppReadBufHandler(ApplicationBufferHandler handler) { } + @Override public int read(ByteBuffer dst) throws IOException { return -1; } + @Override - public long read(ByteBuffer[] dsts, int offset, int length) - throws IOException { + public long read(ByteBuffer[] dsts, int offset, int length) throws IOException { return -1L; } + @Override public int write(ByteBuffer src) throws IOException { checkInterruptStatus(); throw new ClosedChannelException(); } + @Override - public long write(ByteBuffer[] srcs, int offset, int length) - throws IOException { + public long write(ByteBuffer[] srcs, int offset, int length) throws IOException { throw new ClosedChannelException(); } + @Override public String toString() { return "Closed NioChannel"; diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/net/NioEndpoint.java tomcat10-10.1.52/java/org/apache/tomcat/util/net/NioEndpoint.java --- tomcat10-10.1.40/java/org/apache/tomcat/util/net/NioEndpoint.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/net/NioEndpoint.java 2026-01-23 19:33:36.000000000 +0000 @@ -66,8 +66,6 @@ /** * NIO endpoint. - * - * @author Mladen Turk */ public class NioEndpoint extends AbstractJsseEndpoint { @@ -80,7 +78,7 @@ private static final Log logHandshake = LogFactory.getLog(NioEndpoint.class.getName() + ".handshake"); - public static final int OP_REGISTER = 0x100; //register interest op + public static final int OP_REGISTER = 0x100; // register interest op // ----------------------------------------------------------------- Fields @@ -114,15 +112,25 @@ * Use System.inheritableChannel to obtain channel from stdin/stdout. */ private boolean useInheritedChannel = false; - public void setUseInheritedChannel(boolean useInheritedChannel) { this.useInheritedChannel = useInheritedChannel; } - public boolean getUseInheritedChannel() { return useInheritedChannel; } + + public void setUseInheritedChannel(boolean useInheritedChannel) { + this.useInheritedChannel = useInheritedChannel; + } + + public boolean getUseInheritedChannel() { + return useInheritedChannel; + } /** * Path for the Unix domain socket, used to create the socket address. */ private String unixDomainSocketPath = null; - public String getUnixDomainSocketPath() { return this.unixDomainSocketPath; } + + public String getUnixDomainSocketPath() { + return this.unixDomainSocketPath; + } + public void setUnixDomainSocketPath(String unixDomainSocketPath) { this.unixDomainSocketPath = unixDomainSocketPath; } @@ -132,7 +140,11 @@ * Permissions which will be set on the Unix domain socket if it is created. */ private String unixDomainSocketPathPermissions = null; - public String getUnixDomainSocketPathPermissions() { return this.unixDomainSocketPathPermissions; } + + public String getUnixDomainSocketPathPermissions() { + return this.unixDomainSocketPathPermissions; + } + public void setUnixDomainSocketPathPermissions(String unixDomainSocketPathPermissions) { this.unixDomainSocketPathPermissions = unixDomainSocketPathPermissions; } @@ -142,13 +154,25 @@ * Priority of the poller thread. */ private int pollerThreadPriority = Thread.NORM_PRIORITY; - public void setPollerThreadPriority(int pollerThreadPriority) { this.pollerThreadPriority = pollerThreadPriority; } - public int getPollerThreadPriority() { return pollerThreadPriority; } + + public void setPollerThreadPriority(int pollerThreadPriority) { + this.pollerThreadPriority = pollerThreadPriority; + } + + public int getPollerThreadPriority() { + return pollerThreadPriority; + } private long selectorTimeout = 1000; - public void setSelectorTimeout(long timeout) { this.selectorTimeout = timeout;} - public long getSelectorTimeout() { return this.selectorTimeout; } + + public void setSelectorTimeout(long timeout) { + this.selectorTimeout = timeout; + } + + public long getSelectorTimeout() { + return this.selectorTimeout; + } /** * The socket poller. @@ -161,8 +185,8 @@ /** * Number of keep-alive sockets. * - * @return The number of sockets currently in the keep-alive state waiting - * for the next request to be received on the socket + * @return The number of sockets currently in the keep-alive state waiting for the next request to be received on + * the socket */ public int getKeepAliveCount() { if (poller == null) { @@ -239,7 +263,7 @@ InetSocketAddress addr = new InetSocketAddress(getAddress(), getPortWithOffset()); serverSock.bind(addr, getAcceptCount()); } - serverSock.configureBlocking(true); //mimic APR behavior + serverSock.configureBlocking(true); // mimic APR behavior } @@ -254,18 +278,15 @@ paused = false; if (socketProperties.getProcessorCache() != 0) { - processorCache = new SynchronizedStack<>(SynchronizedStack.DEFAULT_SIZE, - socketProperties.getProcessorCache()); + processorCache = + new SynchronizedStack<>(SynchronizedStack.DEFAULT_SIZE, socketProperties.getProcessorCache()); } if (socketProperties.getEventCache() != 0) { - eventCache = new SynchronizedStack<>(SynchronizedStack.DEFAULT_SIZE, - socketProperties.getEventCache()); + eventCache = new SynchronizedStack<>(SynchronizedStack.DEFAULT_SIZE, socketProperties.getEventCache()); } - int actualBufferPool = - socketProperties.getActualBufferPool(isSSLEnabled() ? getSniParseLimit() * 2 : 0); + int actualBufferPool = socketProperties.getActualBufferPool(isSSLEnabled() ? getSniParseLimit() * 2 : 0); if (actualBufferPool != 0) { - nioChannels = new SynchronizedStack<>(SynchronizedStack.DEFAULT_SIZE, - actualBufferPool); + nioChannels = new SynchronizedStack<>(SynchronizedStack.DEFAULT_SIZE, actualBufferPool); } // Create worker collection @@ -340,8 +361,7 @@ @Override public void unbind() throws Exception { if (log.isTraceEnabled()) { - log.trace("Destroy initiated for " + - new InetSocketAddress(getAddress(),getPortWithOffset())); + log.trace("Destroy initiated for " + new InetSocketAddress(getAddress(), getPortWithOffset())); } if (running) { stop(); @@ -353,12 +373,11 @@ } destroySsl(); super.unbind(); - if (getHandler() != null ) { + if (getHandler() != null) { getHandler().recycle(); } if (log.isTraceEnabled()) { - log.trace("Destroy completed for " + - new InetSocketAddress(getAddress(), getPortWithOffset())); + log.trace("Destroy completed for " + new InetSocketAddress(getAddress(), getPortWithOffset())); } } @@ -399,16 +418,14 @@ } // Wait for up to 1000ms acceptor threads to unlock long waitLeft = 1000; - while (waitLeft > 0 && - acceptor.getState() == AcceptorState.RUNNING) { + while (waitLeft > 0 && acceptor.getState() == AcceptorState.RUNNING) { Thread.sleep(5); waitLeft -= 5; } - } catch(Throwable t) { + } catch (Throwable t) { ExceptionUtils.handleThrowable(t); if (getLog().isDebugEnabled()) { - getLog().debug(sm.getString( - "endpoint.debug.unlock.fail", String.valueOf(getPortWithOffset())), t); + getLog().debug(sm.getString("endpoint.debug.unlock.fail", String.valueOf(getPortWithOffset())), t); } } } @@ -437,10 +454,11 @@ /** * Process the specified connection. + * * @param socket The socket channel - * @return true if the socket was correctly configured - * and processing may continue, false if the socket needs to be - * close immediately + * + * @return true if the socket was correctly configured and processing may continue, false + * if the socket needs to be close immediately */ @Override protected boolean setSocketOptions(SocketChannel socket) { @@ -452,10 +470,8 @@ channel = nioChannels.pop(); } if (channel == null) { - SocketBufferHandler bufhandler = new SocketBufferHandler( - socketProperties.getAppReadBufSize(), - socketProperties.getAppWriteBufSize(), - socketProperties.getDirectBuffer()); + SocketBufferHandler bufhandler = new SocketBufferHandler(socketProperties.getAppReadBufSize(), + socketProperties.getAppWriteBufSize(), socketProperties.getDirectBuffer()); if (isSSLEnabled()) { channel = new SecureNioChannel(bufhandler, this); } else { @@ -547,8 +563,8 @@ @Override - protected SocketProcessorBase createSocketProcessor( - SocketWrapperBase socketWrapper, SocketEvent event) { + protected SocketProcessorBase createSocketProcessor(SocketWrapperBase socketWrapper, + SocketEvent event) { return new SocketProcessor(socketWrapper, event); } @@ -596,8 +612,7 @@ public class Poller implements Runnable { private final Selector selector; - private final SynchronizedQueue events = - new SynchronizedQueue<>(); + private final SynchronizedQueue events = new SynchronizedQueue<>(); private volatile boolean close = false; // Optimize expiration handling @@ -611,9 +626,13 @@ this.selector = Selector.open(); } - public int getKeyCount() { return keyCount; } + public int getKeyCount() { + return selector.keys().size(); + } - public Selector getSelector() { return selector; } + public Selector getSelector() { + return selector; + } /** * Destroy the poller. @@ -647,14 +666,12 @@ } /** - * Add specified socket and associated pool to the poller. The socket will - * be added to a temporary array, and polled first after a maximum amount - * of time equal to pollTime (in most cases, latency will be much lower, + * Add specified socket and associated pool to the poller. The socket will be added to a temporary array, and + * polled first after a maximum amount of time equal to pollTime (in most cases, latency will be much lower, * however). * * @param socketWrapper to add to the poller - * @param interestOps Operations for which to register this socket with - * the Poller + * @param interestOps Operations for which to register this socket with the Poller */ public void add(NioSocketWrapper socketWrapper, int interestOps) { PollerEvent pollerEvent = createPollerEvent(socketWrapper, interestOps); @@ -667,14 +684,13 @@ /** * Processes events in the event queue of the Poller. * - * @return true if some events were processed, - * false if queue was empty + * @return true if some events were processed, false if queue was empty */ public boolean events() { boolean result = false; PollerEvent pe; - for (int i = 0, size = events.size(); i < size && (pe = events.poll()) != null; i++ ) { + for (int i = 0, size = events.size(); i < size && (pe = events.poll()) != null; i++) { result = true; NioSocketWrapper socketWrapper = pe.getSocketWrapper(); SocketChannel sc = socketWrapper.getSocket().getIOChannel(); @@ -687,8 +703,8 @@ } else if (interestOps == OP_REGISTER) { try { sc.register(getSelector(), SelectionKey.OP_READ, socketWrapper); - } catch (Exception x) { - log.error(sm.getString("endpoint.nio.registerFail"), x); + } catch (Exception e) { + log.error(sm.getString("endpoint.nio.registerFail"), e); } } else { final SelectionKey key = sc.keyFor(getSelector()); @@ -730,15 +746,14 @@ * @param socketWrapper The socket wrapper */ public void register(final NioSocketWrapper socketWrapper) { - socketWrapper.interestOps(SelectionKey.OP_READ);//this is what OP_REGISTER turns into. + socketWrapper.interestOps(SelectionKey.OP_READ);// this is what OP_REGISTER turns into. PollerEvent pollerEvent = createPollerEvent(socketWrapper, OP_REGISTER); addEvent(pollerEvent); } /** - * The background thread that adds sockets to the Poller, checks the - * poller for triggered events and hands the associated socket off to an - * appropriate processor as events occur. + * The background thread that adds sockets to the Poller, checks the poller for triggered events and hands the + * associated socket off to an appropriate processor as events occur. */ @Override public void run() { @@ -779,8 +794,7 @@ continue; } - Iterator iterator = - keyCount > 0 ? selector.selectedKeys().iterator() : null; + Iterator iterator = keyCount > 0 ? selector.selectedKeys().iterator() : null; // Walk through the collection of ready keys and dispatch // any active event. while (iterator != null && iterator.hasNext()) { @@ -795,7 +809,7 @@ } // Process timeouts - timeout(keyCount,hasEvents); + timeout(keyCount, hasEvents); } getStopLatch().countDown(); @@ -901,7 +915,7 @@ } } } - if (sd.length <= 0 && sc.getOutboundRemaining()<=0) { + if (sd.length <= 0 && sc.getOutboundRemaining() <= 0) { if (log.isTraceEnabled()) { log.trace("Send file complete for: " + sd.fileName); } @@ -909,35 +923,36 @@ try { sd.fchannel.close(); } catch (Exception ignore) { + // Ignore } // For calls from outside the Poller, the caller is // responsible for registering the socket for the // appropriate event(s) if sendfile completes. if (!calledByProcessor) { switch (sd.keepAliveState) { - case NONE: { - if (log.isTraceEnabled()) { - log.trace("Send file connection is being closed"); - } - socketWrapper.close(); - break; - } - case PIPELINED: { - if (log.isTraceEnabled()) { - log.trace("Connection is keep alive, processing pipe-lined data"); - } - if (!processSocket(socketWrapper, SocketEvent.OPEN_READ, true)) { + case NONE: { + if (log.isTraceEnabled()) { + log.trace("Send file connection is being closed"); + } socketWrapper.close(); + break; } - break; - } - case OPEN: { - if (log.isTraceEnabled()) { - log.trace("Connection is keep alive, registering back for OP_READ"); + case PIPELINED: { + if (log.isTraceEnabled()) { + log.trace("Connection is keep alive, processing pipe-lined data"); + } + if (!processSocket(socketWrapper, SocketEvent.OPEN_READ, true)) { + socketWrapper.close(); + } + break; + } + case OPEN: { + if (log.isTraceEnabled()) { + log.trace("Connection is keep alive, registering back for OP_READ"); + } + reg(sk, socketWrapper, SelectionKey.OP_READ); + break; } - reg(sk, socketWrapper, SelectionKey.OP_READ); - break; - } } } return SendfileState.DONE; @@ -952,9 +967,9 @@ } return SendfileState.PENDING; } - } catch (IOException e) { + } catch (IOException ioe) { if (log.isDebugEnabled()) { - log.debug(sm.getString("endpoint.sendfile.error"), e); + log.debug(sm.getString("endpoint.sendfile.error"), ioe); } if (!calledByProcessor && sc != null) { socketWrapper.close(); @@ -1008,7 +1023,7 @@ socketWrapper.interestOps(0); socketWrapper.close(); } else if (socketWrapper.interestOpsHas(SelectionKey.OP_READ) || - socketWrapper.interestOpsHas(SelectionKey.OP_WRITE)) { + socketWrapper.interestOpsHas(SelectionKey.OP_WRITE)) { boolean readTimeout = false; boolean writeTimeout = false; // Check for read timeout @@ -1057,13 +1072,11 @@ } // For logging purposes only long prevExp = nextExpiration; - nextExpiration = System.currentTimeMillis() + - socketProperties.getTimeoutInterval(); + nextExpiration = System.currentTimeMillis() + socketProperties.getTimeoutInterval(); if (log.isTraceEnabled()) { - log.trace("timeout completed: keys processed=" + keycount + - "; now=" + now + "; nextExpiration=" + prevExp + - "; keyCount=" + keyCount + "; hasEvents=" + hasEvents + - "; eval=" + ((now < prevExp) && (keyCount>0 || hasEvents) && (!close) )); + log.trace("timeout completed: keys processed=" + keycount + "; now=" + now + "; nextExpiration=" + + prevExp + "; keyCount=" + keyCount + "; hasEvents=" + hasEvents + "; eval=" + + ((now < prevExp) && (keyCount > 0 || hasEvents) && (!close))); } } @@ -1104,20 +1117,46 @@ writeLock = (writePending == null) ? new Object() : writePending; } - public Poller getPoller() { return poller; } - public int interestOps() { return interestOps; } - public int interestOps(int ops) { this.interestOps = ops; return ops; } + public Poller getPoller() { + return poller; + } + + public int interestOps() { + return interestOps; + } + + public int interestOps(int ops) { + this.interestOps = ops; + return ops; + } + public boolean interestOpsHas(int targetOp) { return (this.interestOps() & targetOp) == targetOp; } - public void setSendfileData(SendfileData sf) { this.sendfileData = sf;} - public SendfileData getSendfileData() { return this.sendfileData; } + public void setSendfileData(SendfileData sf) { + this.sendfileData = sf; + } + + public SendfileData getSendfileData() { + return this.sendfileData; + } + + public void updateLastWrite() { + lastWrite = System.currentTimeMillis(); + } + + public long getLastWrite() { + return lastWrite; + } - public void updateLastWrite() { lastWrite = System.currentTimeMillis(); } - public long getLastWrite() { return lastWrite; } - public void updateLastRead() { lastRead = System.currentTimeMillis(); } - public long getLastRead() { return lastRead; } + public void updateLastRead() { + lastRead = System.currentTimeMillis(); + } + + public long getLastRead() { + return lastRead; + } @Override public boolean isReadyForRead() throws IOException { @@ -1139,11 +1178,9 @@ if (nRead > 0) { return nRead; /* - * Since more bytes may have arrived since the buffer was last - * filled, it is an option at this point to perform a - * non-blocking read. However, correctly handling the case if - * that read returns end of stream adds complexity. Therefore, - * at the moment, the preference is for simplicity. + * Since more bytes may have arrived since the buffer was last filled, it is an option at this point to + * perform a non-blocking read. However, correctly handling the case if that read returns end of stream + * adds complexity. Therefore, at the moment, the preference is for simplicity. */ } @@ -1168,11 +1205,9 @@ if (nRead > 0) { return nRead; /* - * Since more bytes may have arrived since the buffer was last - * filled, it is an option at this point to perform a - * non-blocking read. However, correctly handling the case if - * that read returns end of stream adds complexity. Therefore, - * at the moment, the preference is for simplicity. + * Since more bytes may have arrived since the buffer was last filled, it is an option at this point to + * perform a non-blocking read. However, correctly handling the case if that read returns end of stream + * adds complexity. Therefore, at the moment, the preference is for simplicity. */ } @@ -1214,14 +1249,15 @@ getSocket().close(true); } if (getEndpoint().running) { + getSocket().reset(null, null); if (nioChannels == null || !nioChannels.push(getSocket())) { getSocket().free(); } } - } catch (Throwable e) { - ExceptionUtils.handleThrowable(e); + } catch (Throwable t) { + ExceptionUtils.handleThrowable(t); if (log.isDebugEnabled()) { - log.error(sm.getString("endpoint.debug.channelCloseFail"), e); + log.error(sm.getString("endpoint.debug.channelCloseFail"), t); } } finally { socketBufferHandler = SocketBufferHandler.EMPTY; @@ -1233,10 +1269,10 @@ if (data != null && data.fchannel != null && data.fchannel.isOpen()) { data.fchannel.close(); } - } catch (Throwable e) { - ExceptionUtils.handleThrowable(e); + } catch (Throwable t) { + ExceptionUtils.handleThrowable(t); if (log.isDebugEnabled()) { - log.error(sm.getString("endpoint.sendfile.closeError"), e); + log.error(sm.getString("endpoint.sendfile.closeError"), t); } } } @@ -1283,8 +1319,11 @@ } else { readLock.wait(); } - } catch (InterruptedException e) { - // Continue + } catch (InterruptedException ignore) { + /* + * Most likely the Poller signalling there is data to read but could be spurious. Exit + * the wait, check status and proceed accordingly. + */ } } } @@ -1325,13 +1364,11 @@ /* * https://bz.apache.org/bugzilla/show_bug.cgi?id=66076 * - * When using TLS an additional buffer is used for the encrypted data - * before it is written to the network. It is possible for this network - * output buffer to contain data while the socket write buffer is empty. + * When using TLS an additional buffer is used for the encrypted data before it is written to the network. It is + * possible for this network output buffer to contain data while the socket write buffer is empty. * - * For NIO with non-blocking I/O, this case is handling by ensuring that - * flush only returns false (i.e. no data left to flush) if all buffers - * are empty. + * For NIO with non-blocking I/O, this case is handling by ensuring that flush only returns false (i.e. no data + * left to flush) if all buffers are empty. */ private boolean socketOrNetworkBufferHasDataLeft() { return !socketBufferHandler.isWriteBufferEmpty() || getSocket().getOutboundRemaining() > 0; @@ -1349,16 +1386,13 @@ /* * Socket has previously timed out. * - * Blocking writes assume that buffer is always fully - * written so there is no code checking for incomplete - * writes, retaining the unwritten data and attempting to - * write it as part of a subsequent write call. + * Blocking writes assume that buffer is always fully written so there is no code checking for + * incomplete writes, retaining the unwritten data and attempting to write it as part of a + * subsequent write call. * - * Because of the above, when a timeout is triggered we need - * to skip subsequent attempts to write as otherwise it will - * appear to the client as if some data was dropped just - * before the connection is lost. It is better if the client - * just sees the dropped connection. + * Because of the above, when a timeout is triggered we need to skip subsequent attempts to write as + * otherwise it will appear to the client as if some data was dropped just before the connection is + * lost. It is better if the client just sees the dropped connection. */ throw new IOException(previousIOException); } @@ -1395,8 +1429,11 @@ } else { writeLock.wait(); } - } catch (InterruptedException e) { - // Continue + } catch (InterruptedException ignore) { + /* + * Most likely the Poller signalling that data can be written but could be spurious. + * Exit the wait, check status and proceed accordingly. + */ } } else if (startNanos > 0) { // If something was written, reset timeout @@ -1553,23 +1590,23 @@ } @Override - protected OperationState newOperationState(boolean read, - ByteBuffer[] buffers, int offset, int length, - BlockingMode block, long timeout, TimeUnit unit, A attachment, - CompletionCheck check, CompletionHandler handler, - Semaphore semaphore, VectoredIOCompletionHandler completion) { - return new NioOperationState<>(read, buffers, offset, length, block, - timeout, unit, attachment, check, handler, semaphore, completion); + protected OperationState newOperationState(boolean read, ByteBuffer[] buffers, int offset, int length, + BlockingMode block, long timeout, TimeUnit unit, A attachment, CompletionCheck check, + CompletionHandler handler, Semaphore semaphore, + VectoredIOCompletionHandler completion) { + return new NioOperationState<>(read, buffers, offset, length, block, timeout, unit, attachment, check, + handler, semaphore, completion); } private class NioOperationState extends OperationState { private volatile boolean inline = true; - private NioOperationState(boolean read, ByteBuffer[] buffers, int offset, int length, - BlockingMode block, long timeout, TimeUnit unit, A attachment, CompletionCheck check, - CompletionHandler handler, Semaphore semaphore, + + private NioOperationState(boolean read, ByteBuffer[] buffers, int offset, int length, BlockingMode block, + long timeout, TimeUnit unit, A attachment, CompletionCheck check, + CompletionHandler handler, Semaphore semaphore, VectoredIOCompletionHandler completion) { - super(read, buffers, offset, length, block, - timeout, unit, attachment, check, handler, semaphore, completion); + super(read, buffers, offset, length, block, timeout, unit, attachment, check, handler, semaphore, + completion); } @Override @@ -1646,8 +1683,8 @@ completionDone = false; } } - } catch (IOException e) { - setError(e); + } catch (IOException ioe) { + setError(ioe); } } if (nBytes > 0 || (nBytes == 0 && !buffersArrayHasRemaining(buffers, offset, length) && @@ -1677,8 +1714,7 @@ // ---------------------------------------------- SocketProcessor Inner Class /** - * This class is the equivalent of the Worker, but will simply use in an - * external Executor thread pool. + * This class is the equivalent of the Worker, but will simply use in an external Executor thread pool. */ protected class SocketProcessor extends SocketProcessorBase { @@ -1689,12 +1725,10 @@ @Override protected void doRun() { /* - * Do not cache and re-use the value of socketWrapper.getSocket() in - * this method. If the socket closes the value will be updated to - * CLOSED_NIO_CHANNEL and the previous value potentially re-used for - * a new connection. That can result in a stale cached value which - * in turn can result in unintentionally closing currently active - * connections. + * Do not cache and re-use the value of socketWrapper.getSocket() in this method. If the socket closes the + * value will be updated to CLOSED_NIO_CHANNEL and the previous value potentially re-used for a new + * connection. That can result in a stale cached value which in turn can result in unintentionally closing + * currently active connections. */ Poller poller = NioEndpoint.this.poller; if (poller == null) { @@ -1715,7 +1749,8 @@ // if the handshake failed. handshake = -1; } else { - handshake = socketWrapper.getSocket().handshake(event == SocketEvent.OPEN_READ, event == SocketEvent.OPEN_WRITE); + handshake = socketWrapper.getSocket().handshake(event == SocketEvent.OPEN_READ, + event == SocketEvent.OPEN_WRITE); // The handshake process reads/writes from/to the // socket. status may therefore be OPEN_WRITE once // the handshake completes. However, the handshake @@ -1725,11 +1760,11 @@ // the handshake completes. event = SocketEvent.OPEN_READ; } - } catch (IOException x) { + } catch (IOException ioe) { handshake = -1; if (logHandshake.isDebugEnabled()) { - logHandshake.debug(sm.getString("endpoint.err.handshake", - socketWrapper.getRemoteAddr(), Integer.toString(socketWrapper.getRemotePort())), x); + logHandshake.debug(sm.getString("endpoint.err.handshake", socketWrapper.getRemoteAddr(), + Integer.toString(socketWrapper.getRemotePort())), ioe); } } catch (CancelledKeyException ckx) { handshake = -1; @@ -1737,16 +1772,17 @@ if (handshake == 0) { SocketState state; // Process the request from this socket - state = getHandler().process(socketWrapper, Objects.requireNonNullElse(event, SocketEvent.OPEN_READ)); + state = getHandler().process(socketWrapper, + Objects.requireNonNullElse(event, SocketEvent.OPEN_READ)); if (state == SocketState.CLOSED) { socketWrapper.close(); } - } else if (handshake == -1 ) { + } else if (handshake == -1) { getHandler().process(socketWrapper, SocketEvent.CONNECT_FAIL); socketWrapper.close(); - } else if (handshake == SelectionKey.OP_READ){ + } else if (handshake == SelectionKey.OP_READ) { socketWrapper.registerReadInterest(); - } else if (handshake == SelectionKey.OP_WRITE){ + } else if (handshake == SelectionKey.OP_WRITE) { socketWrapper.registerWriteInterest(); } } catch (CancelledKeyException cx) { @@ -1759,7 +1795,7 @@ } finally { socketWrapper = null; event = null; - //return to cache + // return to cache if (running && processorCache != null) { processorCache.push(this); } diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/net/SSLContext.java tomcat10-10.1.52/java/org/apache/tomcat/util/net/SSLContext.java --- tomcat10-10.1.40/java/org/apache/tomcat/util/net/SSLContext.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/net/SSLContext.java 2026-01-23 19:33:36.000000000 +0000 @@ -28,14 +28,12 @@ import javax.net.ssl.TrustManager; /** - * This interface is needed to override the default SSLContext class - * to allow SSL implementation pluggability without having to use JCE. With - * regular JSSE it will do nothing but delegate to the SSLContext. + * This interface is needed to override the default SSLContext class to allow SSL implementation pluggability without + * having to use JCE. With regular JSSE it will do nothing but delegate to the SSLContext. */ public interface SSLContext { - void init(KeyManager[] kms, TrustManager[] tms, - SecureRandom sr) throws KeyManagementException; + void init(KeyManager[] kms, TrustManager[] tms, SecureRandom sr) throws KeyManagementException; void destroy(); diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/net/SSLHostConfig.java tomcat10-10.1.52/java/org/apache/tomcat/util/net/SSLHostConfig.java --- tomcat10-10.1.40/java/org/apache/tomcat/util/net/SSLHostConfig.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/net/SSLHostConfig.java 2026-01-23 19:33:36.000000000 +0000 @@ -38,6 +38,7 @@ import org.apache.juli.logging.LogFactory; import org.apache.tomcat.util.net.openssl.OpenSSLConf; import org.apache.tomcat.util.net.openssl.ciphers.Cipher; +import org.apache.tomcat.util.net.openssl.ciphers.Group; import org.apache.tomcat.util.net.openssl.ciphers.OpenSSLCipherConfigurationParser; import org.apache.tomcat.util.res.StringManager; @@ -56,11 +57,18 @@ // keys in Maps. protected static final String DEFAULT_SSL_HOST_NAME = "_default_"; protected static final Set SSL_PROTO_ALL_SET = new HashSet<>(); - public static final String DEFAULT_TLS_CIPHERS = "HIGH:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!kRSA"; + public static final String DEFAULT_TLS_CIPHERS_12 = "HIGH:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!kRSA"; + public static final String DEFAULT_TLS_CIPHERS_13 = "TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256:TLS_AES_128_GCM_SHA256"; + /** + * Default cipher list for TLS 1.2 and below. + * @deprecated Replaced by {@link #DEFAULT_TLS_CIPHERS_12} + */ + @Deprecated + public static final String DEFAULT_TLS_CIPHERS = DEFAULT_TLS_CIPHERS_12; static { - /* Default used if protocols are not configured, also used if - * protocols="All" + /* + * Default used if protocols are not configured, also used if protocols="All" */ SSL_PROTO_ALL_SET.add(Constants.SSL_PROTO_SSLv2Hello); SSL_PROTO_ALL_SET.add(Constants.SSL_PROTO_TLSv1); @@ -70,6 +78,7 @@ } private Type configType = null; + private Type trustConfigType = null; private String hostName = DEFAULT_SSL_HOST_NAME; @@ -100,10 +109,16 @@ private int certificateVerificationDepth = 10; // Used to track if certificateVerificationDepth has been explicitly set private boolean certificateVerificationDepthConfigured = false; - private String ciphers = DEFAULT_TLS_CIPHERS; + private String ciphers = DEFAULT_TLS_CIPHERS_12; + private String cipherSuites = DEFAULT_TLS_CIPHERS_13; private LinkedHashSet cipherList = null; + private LinkedHashSet cipherSuiteList = null; private List jsseCipherNames = null; private boolean honorCipherOrder = false; + private boolean ocspEnabled = false; + private boolean ocspSoftFail = true; + private int ocspTimeout = 15000; + private int ocspVerifyFlags = 0; private final Set protocols = new HashSet<>(); // Values <0 mean use the implementation default private int sessionCacheSize = -1; @@ -119,6 +134,8 @@ private String truststoreProvider = System.getProperty("javax.net.ssl.trustStoreProvider"); private String truststoreType = System.getProperty("javax.net.ssl.trustStoreType"); private transient KeyStore truststore = null; + private String groups = null; + private LinkedHashSet groupList = null; // OpenSSL private String certificateRevocationListPath; private String caCertificateFile; @@ -172,18 +189,40 @@ /** * Set property which belongs to the specified configuration type. - * @param name the property name + * + * @param name the property name * @param configType the configuration type - * @return true if the property belongs to the current configuration, - * and false otherwise + * + * @return true if the property belongs to the current configuration type, and false otherwise */ boolean setProperty(String name, Type configType) { if (this.configType == null) { this.configType = configType; } else { if (configType != this.configType) { - log.warn(sm.getString("sslHostConfig.mismatch", - name, getHostName(), configType, this.configType)); + log.warn(sm.getString("sslHostConfig.mismatch", name, getHostName(), configType, this.configType)); + return false; + } + } + return true; + } + + + /** + * Set property which belongs to the specified trust configuration type. + * + * @param name the property name + * @param trustConfigType the trust configuration type + * + * @return true if the property belongs to the current trust configuration type, and false otherwise + */ + boolean setTrustProperty(String name, Type trustConfigType) { + if (this.trustConfigType == null) { + this.trustConfigType = trustConfigType; + } else { + if (trustConfigType != this.trustConfigType) { + log.warn(sm.getString("sslHostConfig.mismatch.trust", name, getHostName(), trustConfigType, + this.trustConfigType)); return false; } } @@ -237,8 +276,8 @@ private void registerDefaultCertificate() { if (defaultCertificate == null) { - SSLHostConfigCertificate defaultCertificate = new SSLHostConfigCertificate( - this, SSLHostConfigCertificate.Type.UNDEFINED); + SSLHostConfigCertificate defaultCertificate = + new SSLHostConfigCertificate(this, SSLHostConfigCertificate.Type.UNDEFINED); addCertificate(defaultCertificate); this.defaultCertificate = defaultCertificate; } @@ -255,7 +294,7 @@ if (certificates.size() == 1 && certificates.iterator().next().getType() == SSLHostConfigCertificate.Type.UNDEFINED || - certificate.getType() == SSLHostConfigCertificate.Type.UNDEFINED) { + certificate.getType() == SSLHostConfigCertificate.Type.UNDEFINED) { // Invalid config throw new IllegalArgumentException(sm.getString("sslHostConfig.certificate.notype")); } @@ -275,7 +314,6 @@ } else if (openSslConf != null) { throw new IllegalArgumentException(sm.getString("sslHostConfig.opensslconf.alreadySet")); } - setProperty("", Type.OPENSSL); openSslConf = conf; } @@ -307,8 +345,7 @@ public void setCertificateVerification(String certificateVerification) { try { - this.certificateVerification = - CertificateVerification.fromString(certificateVerification); + this.certificateVerification = CertificateVerification.fromString(certificateVerification); } catch (IllegalArgumentException iae) { // If the specified value is not recognised, default to the // strictest possible option. @@ -350,36 +387,59 @@ /** - * Set the new cipher configuration. Note: Regardless of the format used to - * set the configuration, it is always stored in OpenSSL format. + * Set the new cipher (TLSv1.2 and below) configuration. Note: Regardless of the format used to set the + * configuration, it is always stored in OpenSSL format. * * @param ciphersList The new cipher configuration in OpenSSL or JSSE format */ public void setCiphers(String ciphersList) { // Ciphers is stored in OpenSSL format. Convert the provided value if // necessary. - if (ciphersList != null && !ciphersList.contains(":")) { - StringBuilder sb = new StringBuilder(); - // Not obviously in OpenSSL format. Might be a single OpenSSL or JSSE - // cipher name. Might be a comma separated list of cipher names - String[] ciphers = ciphersList.split(","); - for (String cipher : ciphers) { - String trimmed = cipher.trim(); - if (!trimmed.isEmpty()) { - String openSSLName = OpenSSLCipherConfigurationParser.jsseToOpenSSL(trimmed); - if (openSSLName == null) { - // Not a JSSE name. Maybe an OpenSSL name or alias - openSSLName = trimmed; + if (ciphersList != null) { + if (ciphersList.contains(":")) { + // OpenSSL format + StringBuilder sb = new StringBuilder(); + String[] components = ciphersList.split(":"); + // Remove any TLS 1.3 cipher suites + for (String component : components) { + String trimmed = component.trim(); + if (OpenSSLCipherConfigurationParser.isTls13Cipher(trimmed)) { + log.warn(sm.getString("sslHostConfig.ignoreTls13Ciphersuite", trimmed)); + } else { + if (sb.length() > 0) { + sb.append(':'); + } + sb.append(trimmed); } - if (sb.length() > 0) { - sb.append(':'); + } + this.ciphers = sb.toString(); + } else { + // Not obviously in OpenSSL format. Might be a single OpenSSL or JSSE + // cipher name. Might be a comma separated list of cipher names + StringBuilder sb = new StringBuilder(); + String[] ciphers = ciphersList.split(","); + for (String cipher : ciphers) { + String trimmed = cipher.trim(); + if (!trimmed.isEmpty()) { + if (OpenSSLCipherConfigurationParser.isTls13Cipher(trimmed)) { + log.warn(sm.getString("sslHostConfig.ignoreTls13Ciphersuite", trimmed)); + continue; + } + String openSSLName = OpenSSLCipherConfigurationParser.jsseToOpenSSL(trimmed); + if (openSSLName == null) { + // Not a JSSE name. Maybe an OpenSSL name or alias + openSSLName = trimmed; + } + if (sb.length() > 0) { + sb.append(':'); + } + sb.append(openSSLName); } - sb.append(openSSLName); } + this.ciphers = sb.toString(); } - this.ciphers = sb.toString(); } else { - this.ciphers = ciphersList; + this.ciphers = null; } this.cipherList = null; this.jsseCipherNames = null; @@ -403,20 +463,83 @@ /** - * Obtain the list of JSSE cipher names for the current configuration. - * Ciphers included in the configuration but not supported by JSSE will be - * excluded from this list. + * Obtain the list of JSSE cipher names for the current configuration. Ciphers included in the configuration but not + * supported by JSSE will be excluded from this list. * * @return A list of the JSSE cipher names */ public List getJsseCipherNames() { if (jsseCipherNames == null) { - jsseCipherNames = OpenSSLCipherConfigurationParser.convertForJSSE(getCipherList()); + Set jsseCiphers = new HashSet<>(); + jsseCiphers.addAll(getCipherSuiteList()); + jsseCiphers.addAll(getCipherList()); + jsseCipherNames = OpenSSLCipherConfigurationParser.convertForJSSE(jsseCiphers); } return jsseCipherNames; } + /** + * Set the cipher suite (TLSv1.3) configuration. + * + * @param cipherSuites The cipher suites to use in a colon-separated, preference order list + */ + public void setCipherSuites(String cipherSuites) { + StringBuilder sb = new StringBuilder(); + String[] values; + if (cipherSuites.contains(":")) { + // OpenSSL format + values = cipherSuites.split(":"); + } else { + // JSSE format or possible a single cipher suite name + values = cipherSuites.split(","); + } + for (String value : values) { + String trimmed = value.trim(); + if (!trimmed.isEmpty()) { + if (!OpenSSLCipherConfigurationParser.isTls13Cipher(trimmed)) { + log.warn(sm.getString("sslHostConfig.ignoreNonTls13Ciphersuite", trimmed)); + continue; + } + /* + * OpenSSL and JSSE names for TLSv1.3 cipher suites are currently (January 2026) the same but handle the + * possible future case where they are not. + */ + String openSSLName = OpenSSLCipherConfigurationParser.jsseToOpenSSL(trimmed); + if (openSSLName == null) { + // Not a JSSE name. Maybe an OpenSSL name or alias + openSSLName = trimmed; + } + if (sb.length() > 0) { + sb.append(':'); + } + sb.append(trimmed); + } + } + this.cipherSuites = sb.toString(); + this.cipherSuiteList = null; + this.jsseCipherNames = null; + } + + + /** + * Obtain the current cipher suite (TLSv1.3) configuration. + * + * @return An OpenSSL cipher suite string for the current configuration. + */ + public String getCipherSuites() { + return cipherSuites; + } + + + private LinkedHashSet getCipherSuiteList() { + if (cipherSuiteList == null) { + cipherSuiteList = OpenSSLCipherConfigurationParser.parse(getCipherSuites()); + } + return cipherSuiteList; + } + + public void setHonorCipherOrder(boolean honorCipherOrder) { this.honorCipherOrder = honorCipherOrder; } @@ -433,14 +556,53 @@ /** - * @return The host name associated with this SSL configuration - always in - * lower case. + * @return The host name associated with this SSL configuration - always in lower case. */ public String getHostName() { return hostName; } + public boolean getOcspEnabled() { + return ocspEnabled; + } + + + public void setOcspEnabled(boolean ocspEnabled) { + this.ocspEnabled = ocspEnabled; + } + + + public boolean getOcspSoftFail() { + return ocspSoftFail; + } + + + public void setOcspSoftFail(boolean ocspSoftFail) { + this.ocspSoftFail = ocspSoftFail; + } + + + public int getOcspTimeout() { + return ocspTimeout; + } + + + public void setOcspTimeout(int ocspTimeout) { + this.ocspTimeout = ocspTimeout; + } + + + public int getOcspVerifyFlags() { + return ocspVerifyFlags; + } + + + public void setOcspVerifyFlags(int ocspVerifyFlags) { + this.ocspVerifyFlags = ocspVerifyFlags; + } + + public void setProtocols(String input) { protocols.clear(); explicitlyRequestedProtocols.clear(); @@ -456,7 +618,7 @@ // Split using a positive lookahead to keep the separator in // the capture so we can check which case it is. - for (String value: input.split("(?=[-+,])")) { + for (String value : input.split("(?=[-+,])")) { String trimmed = value.trim(); // Ignore token which only consists of prefix character if (trimmed.length() > 1) { @@ -481,8 +643,7 @@ trimmed = trimmed.substring(1).trim(); } if (!protocols.isEmpty()) { - log.warn(sm.getString("sslHostConfig.prefix_missing", - trimmed, getHostName())); + log.warn(sm.getString("sslHostConfig.prefix_missing", trimmed, getHostName())); } if (trimmed.equalsIgnoreCase(Constants.SSL_PROTO_ALL)) { protocols.addAll(SSL_PROTO_ALL_SET); @@ -526,8 +687,43 @@ } + /** + * @return the configured named groups + */ + public String getGroups() { + return groups; + } + + + /** + * Set the enabled named groups. + * @param groupsString the case sensitive comma separated list of groups + */ + public void setGroups(String groupsString) { + if (groupsString != null) { + LinkedHashSet groupList = new LinkedHashSet<>(); + String[] groupNames = groupsString.split(","); + for (String groupName : groupNames) { + Group group = Group.valueOf(groupName.trim()); + groupList.add(group); + } + this.groups = groupsString; + this.groupList = groupList; + } + } + + + /** + * @return the groupList + */ + public LinkedHashSet getGroupList() { + return this.groupList; + } + + // ---------------------------------- JSSE specific configuration properties + public void setKeyManagerAlgorithm(String keyManagerAlgorithm) { setProperty("keyManagerAlgorithm", Type.JSSE); this.keyManagerAlgorithm = keyManagerAlgorithm; @@ -562,7 +758,7 @@ public void setTrustManagerClassName(String trustManagerClassName) { - setProperty("trustManagerClassName", Type.JSSE); + setTrustProperty("trustManagerClassName", Type.JSSE); this.trustManagerClassName = trustManagerClassName; } @@ -573,7 +769,7 @@ public void setTruststoreAlgorithm(String truststoreAlgorithm) { - setProperty("truststoreAlgorithm", Type.JSSE); + setTrustProperty("truststoreAlgorithm", Type.JSSE); this.truststoreAlgorithm = truststoreAlgorithm; } @@ -584,7 +780,7 @@ public void setTruststoreFile(String truststoreFile) { - setProperty("truststoreFile", Type.JSSE); + setTrustProperty("truststoreFile", Type.JSSE); this.truststoreFile = truststoreFile; } @@ -595,7 +791,7 @@ public void setTruststorePassword(String truststorePassword) { - setProperty("truststorePassword", Type.JSSE); + setTrustProperty("truststorePassword", Type.JSSE); this.truststorePassword = truststorePassword; } @@ -606,7 +802,7 @@ public void setTruststoreProvider(String truststoreProvider) { - setProperty("truststoreProvider", Type.JSSE); + setTrustProperty("truststoreProvider", Type.JSSE); this.truststoreProvider = truststoreProvider; } @@ -625,7 +821,7 @@ public void setTruststoreType(String truststoreType) { - setProperty("truststoreType", Type.JSSE); + setTrustProperty("truststoreType", Type.JSSE); this.truststoreType = truststoreType; } @@ -649,6 +845,7 @@ public void setTrustStore(KeyStore truststore) { + setTrustProperty("trustStore", Type.JSSE); this.truststore = truststore; } @@ -656,19 +853,18 @@ public KeyStore getTruststore() throws IOException { KeyStore result = truststore; if (result == null) { - if (truststoreFile != null){ + if (truststoreFile != null) { try { - result = SSLUtilBase.getStore(getTruststoreType(), getTruststoreProvider(), - getTruststoreFile(), getTruststorePassword(), null); + result = SSLUtilBase.getStore(getTruststoreType(), getTruststoreProvider(), getTruststoreFile(), + getTruststorePassword(), null); } catch (IOException ioe) { Throwable cause = ioe.getCause(); if (cause instanceof UnrecoverableKeyException) { // Log a warning we had a password issue - log.warn(sm.getString("sslHostConfig.invalid_truststore_password"), - cause); + log.warn(sm.getString("sslHostConfig.invalid_truststore_password"), cause); // Re-try - result = SSLUtilBase.getStore(getTruststoreType(), getTruststoreProvider(), - getTruststoreFile(), null, null); + result = SSLUtilBase.getStore(getTruststoreType(), getTruststoreProvider(), getTruststoreFile(), + null, null); } else { // Something else went wrong - re-throw throw ioe; @@ -694,7 +890,7 @@ public void setCaCertificateFile(String caCertificateFile) { - if (setProperty("caCertificateFile", Type.OPENSSL)) { + if (setTrustProperty("caCertificateFile", Type.OPENSSL)) { // Reset default JSSE trust store if not a JSSE configuration if (truststoreFile != null) { truststoreFile = null; @@ -710,7 +906,7 @@ public void setCaCertificatePath(String caCertificatePath) { - if (setProperty("caCertificatePath", Type.OPENSSL)) { + if (setTrustProperty("caCertificatePath", Type.OPENSSL)) { // Reset default JSSE trust store if not a JSSE configuration if (truststoreFile != null) { truststoreFile = null; @@ -792,7 +988,7 @@ } String newPath = path; File f = new File(newPath); - if ( !f.isAbsolute()) { + if (!f.isAbsolute()) { newPath = System.getProperty(Constants.CATALINA_BASE_PROP) + File.separator + newPath; f = new File(newPath); } @@ -824,31 +1020,25 @@ } public boolean isOptional() { - return optional; + return optional; } public static CertificateVerification fromString(String value) { - if ("true".equalsIgnoreCase(value) || - "yes".equalsIgnoreCase(value) || - "require".equalsIgnoreCase(value) || + if ("true".equalsIgnoreCase(value) || "yes".equalsIgnoreCase(value) || "require".equalsIgnoreCase(value) || "required".equalsIgnoreCase(value)) { return REQUIRED; - } else if ("optional".equalsIgnoreCase(value) || - "want".equalsIgnoreCase(value)) { + } else if ("optional".equalsIgnoreCase(value) || "want".equalsIgnoreCase(value)) { return OPTIONAL; - } else if ("optionalNoCA".equalsIgnoreCase(value) || - "optional_no_ca".equalsIgnoreCase(value)) { + } else if ("optionalNoCA".equalsIgnoreCase(value) || "optional_no_ca".equalsIgnoreCase(value)) { return OPTIONAL_NO_CA; - } else if ("false".equalsIgnoreCase(value) || - "no".equalsIgnoreCase(value) || + } else if ("false".equalsIgnoreCase(value) || "no".equalsIgnoreCase(value) || "none".equalsIgnoreCase(value)) { return NONE; } else { // Could be a typo. Don't default to NONE since that is not // secure. Force user to fix config. Could default to REQUIRED // instead. - throw new IllegalArgumentException( - sm.getString("sslHostConfig.certificateVerificationInvalid", value)); + throw new IllegalArgumentException(sm.getString("sslHostConfig.certificateVerificationInvalid", value)); } } } diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/net/SSLHostConfigCertificate.java tomcat10-10.1.52/java/org/apache/tomcat/util/net/SSLHostConfigCertificate.java --- tomcat10-10.1.40/java/org/apache/tomcat/util/net/SSLHostConfigCertificate.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/net/SSLHostConfigCertificate.java 2026-01-23 19:33:36.000000000 +0000 @@ -30,6 +30,7 @@ import org.apache.juli.logging.Log; import org.apache.juli.logging.LogFactory; import org.apache.tomcat.util.net.openssl.ciphers.Authentication; +import org.apache.tomcat.util.net.openssl.ciphers.SignatureScheme; import org.apache.tomcat.util.res.StringManager; public class SSLHostConfigCertificate implements Serializable { @@ -43,17 +44,16 @@ static final String DEFAULT_KEYSTORE_PROVIDER = System.getProperty("javax.net.ssl.keyStoreProvider"); static final String DEFAULT_KEYSTORE_TYPE = System.getProperty("javax.net.ssl.keyStoreType", "JKS"); - private static final String DEFAULT_KEYSTORE_FILE = - System.getProperty("user.home") + File.separator + ".keystore"; + private static final String DEFAULT_KEYSTORE_FILE = System.getProperty("user.home") + File.separator + ".keystore"; private static final String DEFAULT_KEYSTORE_PASSWORD = "changeit"; // Internal private ObjectName oname; /* - * OpenSSL can handle multiple certs in a single config so the reference to the context is at the virtual host - * level. JSSE can't so the reference is held here on the certificate. Typically, the SSLContext is generated from - * the configuration but, particularly in embedded scenarios, it can be provided directly. + * OpenSSL can handle multiple certs in a single config so the reference to the context is at the virtual host + * level. JSSE can't so the reference is held here on the certificate. Typically, the SSLContext is generated from + * the configuration but, particularly in embedded scenarios, it can be provided directly. */ private transient volatile SSLContext sslContextProvided; private transient volatile SSLContext sslContextGenerated; @@ -84,7 +84,7 @@ private StoreType storeType = null; public SSLHostConfigCertificate() { - this(null, Type.UNDEFINED); + this(null, DEFAULT_TYPE); } public SSLHostConfigCertificate(SSLHostConfig sslHostConfig, Type type) { @@ -163,8 +163,7 @@ // JSSE public void setCertificateKeyAlias(String certificateKeyAlias) { - sslHostConfig.setProperty( - "Certificate.certificateKeyAlias", SSLHostConfig.Type.JSSE); + sslHostConfig.setProperty("Certificate.certificateKeyAlias", SSLHostConfig.Type.JSSE); this.certificateKeyAlias = certificateKeyAlias; } @@ -175,8 +174,7 @@ public void setCertificateKeystoreFile(String certificateKeystoreFile) { - sslHostConfig.setProperty( - "Certificate.certificateKeystoreFile", SSLHostConfig.Type.JSSE); + sslHostConfig.setProperty("Certificate.certificateKeystoreFile", SSLHostConfig.Type.JSSE); setStoreType("Certificate.certificateKeystoreFile", StoreType.KEYSTORE); this.certificateKeystoreFile = certificateKeystoreFile; } @@ -188,8 +186,7 @@ public void setCertificateKeystorePassword(String certificateKeystorePassword) { - sslHostConfig.setProperty( - "Certificate.certificateKeystorePassword", SSLHostConfig.Type.JSSE); + sslHostConfig.setProperty("Certificate.certificateKeystorePassword", SSLHostConfig.Type.JSSE); setStoreType("Certificate.certificateKeystorePassword", StoreType.KEYSTORE); this.certificateKeystorePassword = certificateKeystorePassword; } @@ -201,8 +198,7 @@ public void setCertificateKeystorePasswordFile(String certificateKeystorePasswordFile) { - sslHostConfig.setProperty( - "Certificate.certificateKeystorePasswordFile", SSLHostConfig.Type.JSSE); + sslHostConfig.setProperty("Certificate.certificateKeystorePasswordFile", SSLHostConfig.Type.JSSE); setStoreType("Certificate.certificateKeystorePasswordFile", StoreType.KEYSTORE); this.certificateKeystorePasswordFile = certificateKeystorePasswordFile; } @@ -214,8 +210,7 @@ public void setCertificateKeystoreProvider(String certificateKeystoreProvider) { - sslHostConfig.setProperty( - "Certificate.certificateKeystoreProvider", SSLHostConfig.Type.JSSE); + sslHostConfig.setProperty("Certificate.certificateKeystoreProvider", SSLHostConfig.Type.JSSE); setStoreType("Certificate.certificateKeystoreProvider", StoreType.KEYSTORE); this.certificateKeystoreProvider = certificateKeystoreProvider; } @@ -227,8 +222,7 @@ public void setCertificateKeystoreType(String certificateKeystoreType) { - sslHostConfig.setProperty( - "Certificate.certificateKeystoreType", SSLHostConfig.Type.JSSE); + sslHostConfig.setProperty("Certificate.certificateKeystoreType", SSLHostConfig.Type.JSSE); setStoreType("Certificate.certificateKeystoreType", StoreType.KEYSTORE); this.certificateKeystoreType = certificateKeystoreType; } @@ -251,15 +245,20 @@ KeyStore result = certificateKeystore; if (result == null && storeType == StoreType.KEYSTORE) { - result = SSLUtilBase.getStore(getCertificateKeystoreType(), - getCertificateKeystoreProvider(), getCertificateKeystoreFile(), - getCertificateKeystorePassword(), getCertificateKeystorePasswordFile()); + result = SSLUtilBase.getStore(getCertificateKeystoreType(), getCertificateKeystoreProvider(), + getCertificateKeystoreFile(), getCertificateKeystorePassword(), + getCertificateKeystorePasswordFile()); } return result; } + KeyStore getCertificateKeystoreInternal() { + return certificateKeystore; + } + + public void setCertificateKeyManager(X509KeyManager certificateKeyManager) { this.certificateKeyManager = certificateKeyManager; } @@ -309,8 +308,8 @@ if (storeType == null) { storeType = type; } else if (storeType != type) { - log.warn(sm.getString("sslHostConfigCertificate.mismatch", - name, sslHostConfig.getHostName(), type, this.storeType)); + log.warn(sm.getString("sslHostConfigCertificate.mismatch", name, sslHostConfig.getHostName(), type, + this.storeType)); } } @@ -323,12 +322,19 @@ UNDEFINED, RSA(Authentication.RSA), - DSA(Authentication.DSS), - EC(Authentication.ECDH, Authentication.ECDSA); + DSA(Authentication.DSS, Authentication.EdDSA), + EC(Authentication.ECDH, Authentication.ECDSA), + MLDSA("ML-DSA", Authentication.MLDSA); + private final String keyType; private final Set compatibleAuthentications; Type(Authentication... authentications) { + this(null, authentications); + } + + Type(String keyType, Authentication... authentications) { + this.keyType = keyType; compatibleAuthentications = new HashSet<>(); if (authentications != null) { compatibleAuthentications.addAll(Arrays.asList(authentications)); @@ -338,6 +344,18 @@ public boolean isCompatibleWith(Authentication au) { return compatibleAuthentications.contains(au); } + + public boolean isCompatibleWith(SignatureScheme scheme) { + return compatibleAuthentications.contains(scheme.getAuth()); + } + + public String getKeyType() { + if (keyType != null) { + return keyType; + } + return super.toString(); + } + } enum StoreType { diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/net/SSLImplementation.java tomcat10-10.1.52/java/org/apache/tomcat/util/net/SSLImplementation.java --- tomcat10-10.1.40/java/org/apache/tomcat/util/net/SSLImplementation.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/net/SSLImplementation.java 2026-01-23 19:33:36.000000000 +0000 @@ -27,9 +27,8 @@ import org.apache.tomcat.util.res.StringManager; /** - * Provides a factory and base implementation for the Tomcat specific mechanism - * that allows alternative SSL/TLS implementations to be used without requiring - * the implementation of a full JSSE provider. + * Provides a factory and base implementation for the Tomcat specific mechanism that allows alternative SSL/TLS + * implementations to be used without requiring the implementation of a full JSSE provider. */ public abstract class SSLImplementation { @@ -37,19 +36,16 @@ private static final StringManager sm = StringManager.getManager(SSLImplementation.class); /** - * Obtain an instance (not a singleton) of the implementation with the given - * class name. + * Obtain an instance (not a singleton) of the implementation with the given class name. * - * @param className The class name of the required implementation or null to - * use the default (currently {@link JSSEImplementation}). + * @param className The class name of the required implementation or null to use the default (currently + * {@link JSSEImplementation}). * * @return An instance of the required implementation * - * @throws ClassNotFoundException If an instance of the requested class - * cannot be created + * @throws ClassNotFoundException If an instance of the requested class cannot be created */ - public static SSLImplementation getInstance(String className) - throws ClassNotFoundException { + public static SSLImplementation getInstance(String className) throws ClassNotFoundException { if (className == null) { return new JSSEImplementation(); } @@ -69,12 +65,10 @@ /** * Obtain an instance of SSLSupport. * - * @param session The SSL session - * @param additionalAttributes Additional SSL attributes that are not - * available from the session. + * @param session The SSL session + * @param additionalAttributes Additional SSL attributes that are not available from the session. * - * @return An instance of SSLSupport based on the given session and the - * provided additional attributes + * @return An instance of SSLSupport based on the given session and the provided additional attributes */ public abstract SSLSupport getSSLSupport(SSLSession session, Map> additionalAttributes); diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/net/SSLSessionManager.java tomcat10-10.1.52/java/org/apache/tomcat/util/net/SSLSessionManager.java --- tomcat10-10.1.40/java/org/apache/tomcat/util/net/SSLSessionManager.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/net/SSLSessionManager.java 2026-01-23 19:33:36.000000000 +0000 @@ -17,8 +17,7 @@ package org.apache.tomcat.util.net; /** - * Defines an interface used to manage SSL sessions. The manager operates on a - * single session. + * Defines an interface used to manage SSL sessions. The manager operates on a single session. */ public interface SSLSessionManager { /** diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/net/SSLSupport.java tomcat10-10.1.52/java/org/apache/tomcat/util/net/SSLSupport.java --- tomcat10-10.1.40/java/org/apache/tomcat/util/net/SSLSupport.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/net/SSLSupport.java 2026-01-23 19:33:36.000000000 +0000 @@ -26,8 +26,7 @@ /** * The Request attribute key for the cipher suite. */ - String CIPHER_SUITE_KEY = - "jakarta.servlet.request.cipher_suite"; + String CIPHER_SUITE_KEY = "jakarta.servlet.request.cipher_suite"; /** * The Request attribute key for the key size. @@ -37,49 +36,38 @@ /** * The Request attribute key for the client certificate chain. */ - String CERTIFICATE_KEY = - "jakarta.servlet.request.X509Certificate"; + String CERTIFICATE_KEY = "jakarta.servlet.request.X509Certificate"; /** - * The Request attribute key for the session id. - * This one is a Tomcat extension to the Servlet spec. + * The Request attribute key for the session id. This one is a Tomcat extension to the Servlet spec. */ - String SESSION_ID_KEY = - "jakarta.servlet.request.ssl_session_id"; + String SESSION_ID_KEY = "jakarta.servlet.request.ssl_session_id"; /** - * The request attribute key for the session manager. - * This one is a Tomcat extension to the Servlet spec. + * The request attribute key for the session manager. This one is a Tomcat extension to the Servlet spec. */ - String SESSION_MGR = - "jakarta.servlet.request.ssl_session_mgr"; + String SESSION_MGR = "jakarta.servlet.request.ssl_session_mgr"; /** - * The request attribute key under which the String indicating the protocol - * that created the SSL socket is recorded - e.g. TLSv1 or TLSv1.2 etc. + * The request attribute key under which the String indicating the protocol that created the SSL socket is recorded + * - e.g. TLSv1 or TLSv1.2 etc. */ - String PROTOCOL_VERSION_KEY = - "org.apache.tomcat.util.net.secure_protocol_version"; + String PROTOCOL_VERSION_KEY = "org.apache.tomcat.util.net.secure_protocol_version"; /** - * The request attribute key under which the String indicating the ciphers - * requested by the client are recorded. + * The request attribute key under which the String indicating the ciphers requested by the client are recorded. */ - String REQUESTED_CIPHERS_KEY = - "org.apache.tomcat.util.net.secure_requested_ciphers"; + String REQUESTED_CIPHERS_KEY = "org.apache.tomcat.util.net.secure_requested_ciphers"; /** - * The request attribute key under which the String indicating the protocols - * requested by the client are recorded. + * The request attribute key under which the String indicating the protocols requested by the client are recorded. */ - String REQUESTED_PROTOCOL_VERSIONS_KEY = - "org.apache.tomcat.util.net.secure_requested_protocol_versions"; + String REQUESTED_PROTOCOL_VERSIONS_KEY = "org.apache.tomcat.util.net.secure_requested_protocol_versions"; /** * The cipher suite being used on this connection. * - * @return The name of the cipher suite as returned by the SSL/TLS - * implementation + * @return The name of the cipher suite as returned by the SSL/TLS implementation * * @throws IOException If an error occurs trying to obtain the cipher suite */ @@ -88,36 +76,28 @@ /** * The client certificate chain (if any). * - * @return The certificate chain presented by the client with the peer's - * certificate first, followed by those of any certificate - * authorities + * @return The certificate chain presented by the client with the peer's certificate first, followed by those of any + * certificate authorities * - * @throws IOException If an error occurs trying to obtain the certificate - * chain + * @throws IOException If an error occurs trying to obtain the certificate chain */ X509Certificate[] getPeerCertificateChain() throws IOException; /** * The server certificate chain (if any) that were sent to the peer. * - * @return The certificate chain sent with the server - * certificate first, followed by those of any certificate - * authorities + * @return The certificate chain sent with the server certificate first, followed by those of any certificate + * authorities */ default X509Certificate[] getLocalCertificateChain() { return null; } /** - * Get the key size. - * What we're supposed to put here is ill-defined by the - * Servlet spec (S 4.7 again). There are at least 4 potential - * values that might go here: - * (a) The size of the encryption key - * (b) The size of the MAC key - * (c) The size of the key-exchange key - * (d) The size of the signature key used by the server - * Unfortunately, all of these values are nonsensical. + * Get the key size. What we're supposed to put here is ill-defined by the Servlet spec (S 4.7 again). There are at + * least 4 potential values that might go here: (a) The size of the encryption key (b) The size of the MAC key (c) + * The size of the key-exchange key (d) The size of the signature key used by the server Unfortunately, all of these + * values are nonsensical. * * @return The effective key size for the current cipher suite * @@ -135,27 +115,23 @@ String getSessionId() throws IOException; /** - * @return the protocol String indicating how the SSL socket was created - * e.g. TLSv1 or TLSv1.2 etc. + * @return the protocol String indicating how the SSL socket was created e.g. TLSv1 or TLSv1.2 etc. * - * @throws IOException If an error occurs trying to obtain the protocol - * information from the socket + * @throws IOException If an error occurs trying to obtain the protocol information from the socket */ String getProtocol() throws IOException; /** * @return the list of SSL/TLS protocol versions requested by the client * - * @throws IOException If an error occurs trying to obtain the client - * requested protocol information from the socket + * @throws IOException If an error occurs trying to obtain the client requested protocol information from the socket */ String getRequestedProtocols() throws IOException; /** - * @return the list of SSL/TLS ciphers requested by the client - * - * @throws IOException If an error occurs trying to obtain the client - * request cipher information from the socket - */ - String getRequestedCiphers() throws IOException; + * @return the list of SSL/TLS ciphers requested by the client + * + * @throws IOException If an error occurs trying to obtain the client request cipher information from the socket + */ + String getRequestedCiphers() throws IOException; } diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/net/SSLUtil.java tomcat10-10.1.52/java/org/apache/tomcat/util/net/SSLUtil.java --- tomcat10-10.1.40/java/org/apache/tomcat/util/net/SSLUtil.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/net/SSLUtil.java 2026-01-23 19:33:36.000000000 +0000 @@ -25,9 +25,8 @@ import javax.net.ssl.X509TrustManager; /** - * Provides a common interface for {@link SSLImplementation}s to create the - * necessary JSSE implementation objects for TLS connections created via the - * JSSE API. + * Provides a common interface for {@link SSLImplementation}s to create the necessary JSSE implementation objects for + * TLS connections created via the JSSE API. */ public interface SSLUtil { @@ -56,45 +55,40 @@ void configureSessionContext(SSLSessionContext sslSessionContext); /** - * The set of enabled protocols is the intersection of the implemented - * protocols and the configured protocols. If no protocols are explicitly - * configured, then all of the implemented protocols will be included in the - * returned array. + * The set of enabled protocols is the intersection of the implemented protocols and the configured protocols. If no + * protocols are explicitly configured, then all of the implemented protocols will be included in the returned + * array. * - * @return The protocols currently enabled and available for clients to - * select from for the associated connection + * @return The protocols currently enabled and available for clients to select from for the associated connection * - * @throws IllegalArgumentException If there is no intersection between the - * implemented and configured protocols + * @throws IllegalArgumentException If there is no intersection between the implemented and configured protocols */ String[] getEnabledProtocols() throws IllegalArgumentException; /** - * The set of enabled ciphers is the intersection of the implemented ciphers - * and the configured ciphers. If no ciphers are explicitly configured, then - * the default ciphers will be included in the returned array. + * The set of enabled ciphers is the intersection of the implemented ciphers and the configured ciphers. If no + * ciphers are explicitly configured, then the default ciphers will be included in the returned array. *

      - * The ciphers used during the TLS handshake may be further restricted by - * the {@link #getEnabledProtocols()} and the certificates. + * The ciphers used during the TLS handshake may be further restricted by the {@link #getEnabledProtocols()} and the + * certificates. * - * @return The ciphers currently enabled and available for clients to select - * from for the associated connection + * @return The ciphers currently enabled and available for clients to select from for the associated connection * - * @throws IllegalArgumentException If there is no intersection between the - * implemented and configured ciphers + * @throws IllegalArgumentException If there is no intersection between the implemented and configured ciphers */ String[] getEnabledCiphers() throws IllegalArgumentException; /** - * Optional interface that can be implemented by - * {@link javax.net.ssl.SSLEngine}s to indicate that they support ALPN and - * can provide the protocol agreed with the client. + * Optional interface that can be implemented by {@link javax.net.ssl.SSLEngine}s to indicate that they support ALPN + * and can provide the protocol agreed with the client. */ interface ProtocolInfo { /** * ALPN information. + * * @return the protocol selected using ALPN */ String getNegotiatedProtocol(); } + } diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/net/SSLUtilBase.java tomcat10-10.1.52/java/org/apache/tomcat/util/net/SSLUtilBase.java --- tomcat10-10.1.40/java/org/apache/tomcat/util/net/SSLUtilBase.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/net/SSLUtilBase.java 2026-01-23 19:33:36.000000000 +0000 @@ -28,6 +28,7 @@ import java.security.cert.CRL; import java.security.cert.CRLException; import java.security.cert.CertPathParameters; +import java.security.cert.CertPathValidator; import java.security.cert.CertStore; import java.security.cert.CertStoreParameters; import java.security.cert.Certificate; @@ -37,12 +38,14 @@ import java.security.cert.CertificateNotYetValidException; import java.security.cert.CollectionCertStoreParameters; import java.security.cert.PKIXBuilderParameters; +import java.security.cert.PKIXRevocationChecker; import java.security.cert.X509CertSelector; import java.security.cert.X509Certificate; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.Date; +import java.util.EnumSet; import java.util.Enumeration; import java.util.List; import java.util.Locale; @@ -117,8 +120,7 @@ this.enabledProtocols = enabledProtocols.toArray(new String[0]); if (enabledProtocols.contains(Constants.SSL_PROTO_TLSv1_3) && - sslHostConfig.getCertificateVerification().isOptional() && - !isTls13RenegAuthAvailable() && warnTls13) { + sslHostConfig.getCertificateVerification().isOptional() && !isTls13RenegAuthAvailable() && warnTls13) { log.warn(sm.getString("sslUtilBase.tls13.auth")); } @@ -130,7 +132,7 @@ // OpenSSL profiles cannot be resolved without Java 22 this.enabledCiphers = new String[0]; } else { - boolean warnOnSkip = !sslHostConfig.getCiphers().equals(SSLHostConfig.DEFAULT_TLS_CIPHERS); + boolean warnOnSkip = !sslHostConfig.getCiphers().equals(SSLHostConfig.DEFAULT_TLS_CIPHERS_12); List configuredCiphers = sslHostConfig.getJsseCipherNames(); Set implementedCiphers = getImplementedCiphers(); List enabledCiphers = @@ -160,8 +162,7 @@ // Don't use the defaults in this case. They may be less secure // than the configuration the user intended. // Force the failure of the connector - throw new IllegalArgumentException( - sm.getString("sslUtilBase.noneSupported", name, configured)); + throw new IllegalArgumentException(sm.getString("sslUtilBase.noneSupported", name, configured)); } if (log.isDebugEnabled()) { log.debug(sm.getString("sslUtilBase.active", name, enabled)); @@ -187,8 +188,8 @@ /* * Gets the key- or truststore with the specified type, path, password and password file. */ - static KeyStore getStore(String type, String provider, String path, - String pass, String passFile) throws IOException { + static KeyStore getStore(String type, String provider, String path, String pass, String passFile) + throws IOException { KeyStore ks; InputStream istream = null; @@ -204,9 +205,7 @@ } else { // Some key store types (e.g. hardware) expect the InputStream // to be null - if(!("PKCS11".equalsIgnoreCase(type) || - path.isEmpty() || - "NONE".equalsIgnoreCase(path))) { + if (!("PKCS11".equalsIgnoreCase(type) || path.isEmpty() || "NONE".equalsIgnoreCase(path))) { istream = ConfigFileLoader.getSource().getResource(path).getInputStream(); } @@ -219,22 +218,21 @@ // Therefore: // - generally use null if pass is null or "" // - for JKS or PKCS12 only use null if pass is null - // (because JKS will auto-switch to PKCS12) + // (because JKS will auto-switch to PKCS12) char[] storePass = null; String passToUse; if (passFile != null) { - try (BufferedReader reader = - new BufferedReader(new InputStreamReader( - ConfigFileLoader.getSource().getResource(passFile).getInputStream(), - StandardCharsets.UTF_8))) { + try (BufferedReader reader = new BufferedReader( + new InputStreamReader(ConfigFileLoader.getSource().getResource(passFile).getInputStream(), + StandardCharsets.UTF_8))) { passToUse = reader.readLine(); } } else { passToUse = pass; } - if (passToUse != null && (!passToUse.isEmpty() || - "JKS".equalsIgnoreCase(type) || "PKCS12".equalsIgnoreCase(type))) { + if (passToUse != null && + (!passToUse.isEmpty() || "JKS".equalsIgnoreCase(type) || "PKCS12".equalsIgnoreCase(type))) { storePass = passToUse.toCharArray(); } KeyStoreUtil.load(ks, istream, storePass); @@ -243,10 +241,9 @@ // May be expected when working with a trust store // Re-throw. Caller will catch and log as required throw ioe; - } catch(Exception ex) { - String msg = sm.getString("sslUtilBase.keystore_load_failed", type, path, - ex.getMessage()); - log.error(msg, ex); + } catch (Exception e) { + String msg = sm.getString("sslUtilBase.keystore_load_failed", type, path, e.getMessage()); + log.error(msg, e); throw new IOException(msg); } finally { if (istream != null) { @@ -309,23 +306,17 @@ KeyStore ksUsed = ks; /* - * Use an in memory key store where possible. - * For PEM format keys and certificates, it allows them to be imported - * into the expected format. - * For Java key stores with PKCS8 encoded keys (e.g. JKS files), it - * enables Tomcat to handle the case where multiple keys exist in the - * key store, each with a different password. The KeyManagerFactory - * can't handle that so using an in memory key store with just the - * required key works around that. - * Other keys stores (hardware, MS, etc.) will be used as is. + * Use an in memory key store where possible. For PEM format keys and certificates, it allows them to be + * imported into the expected format. For Java key stores with PKCS8 encoded keys (e.g. JKS files), it enables + * Tomcat to handle the case where multiple keys exist in the key store, each with a different password. The + * KeyManagerFactory can't handle that so using an in memory key store with just the required key works around + * that. Other keys stores (hardware, MS, etc.) will be used as is. */ char[] keyPassArray = null; String keyPassToUse = null; if (keyPassFile != null) { - try (BufferedReader reader = - new BufferedReader(new InputStreamReader( - ConfigFileLoader.getSource().getResource(keyPassFile).getInputStream(), - StandardCharsets.UTF_8))) { + try (BufferedReader reader = new BufferedReader(new InputStreamReader( + ConfigFileLoader.getSource().getResource(keyPassFile).getInputStream(), StandardCharsets.UTF_8))) { keyPassToUse = reader.readLine(); } } else { @@ -351,9 +342,9 @@ throw new IOException(sm.getString("sslUtilBase.noCertFile")); } - PEMFile privateKeyFile = new PEMFile( - certificate.getCertificateKeyFile() != null ? certificate.getCertificateKeyFile() : certificate.getCertificateFile(), - keyPass, keyPassFile, null); + PEMFile privateKeyFile = + new PEMFile(certificate.getCertificateKeyFile() != null ? certificate.getCertificateKeyFile() : + certificate.getCertificateFile(), keyPass, keyPassFile, null); PEMFile certificateFile = new PEMFile(certificate.getCertificateFile()); Collection chain = new ArrayList<>(certificateFile.getCertificates()); @@ -368,7 +359,7 @@ // Switch to in-memory key store ksUsed = KeyStore.getInstance("JKS"); - ksUsed.load(null, null); + ksUsed.load(null, null); ksUsed.setKeyEntry(keyAlias, privateKeyFile.getPrivateKey(), keyPassArray, chain.toArray(new Certificate[0])); } else { @@ -398,10 +389,9 @@ if (provider == null) { ksUsed = KeyStore.getInstance(certificate.getCertificateKeystoreType()); } else { - ksUsed = KeyStore.getInstance(certificate.getCertificateKeystoreType(), - provider); + ksUsed = KeyStore.getInstance(certificate.getCertificateKeystoreType(), provider); } - ksUsed.load(null, null); + ksUsed.load(null, null); ksUsed.setKeyEntry(keyAlias, k, keyPassArray, ks.getCertificateChain(keyAlias)); } // Non-PKCS#8 key stores will use the original key store @@ -421,8 +411,8 @@ if ("JKS".equals(certificate.getCertificateKeystoreType())) { alias = alias.toLowerCase(Locale.ENGLISH); } - for(int i = 0; i < kms.length; i++) { - kms[i] = new JSSEKeyManager((X509KeyManager)kms[i], alias); + for (int i = 0; i < kms.length; i++) { + kms[i] = new JSSEKeyManager((X509KeyManager) kms[i], alias); } } @@ -446,16 +436,15 @@ public TrustManager[] getTrustManagers() throws Exception { String className = sslHostConfig.getTrustManagerClassName(); - if(className != null && !className.isEmpty()) { - ClassLoader classLoader = getClass().getClassLoader(); - Class clazz = classLoader.loadClass(className); - if(!(TrustManager.class.isAssignableFrom(clazz))){ - throw new InstantiationException(sm.getString( - "sslUtilBase.invalidTrustManagerClassName", className)); - } - Object trustManagerObject = clazz.getConstructor().newInstance(); - TrustManager trustManager = (TrustManager) trustManagerObject; - return new TrustManager[]{ trustManager }; + if (className != null && !className.isEmpty()) { + ClassLoader classLoader = getClass().getClassLoader(); + Class clazz = classLoader.loadClass(className); + if (!(TrustManager.class.isAssignableFrom(clazz))) { + throw new InstantiationException(sm.getString("sslUtilBase.invalidTrustManagerClassName", className)); + } + Object trustManagerObject = clazz.getConstructor().newInstance(); + TrustManager trustManager = (TrustManager) trustManagerObject; + return new TrustManager[] { trustManager }; } TrustManager[] tms = null; @@ -522,47 +511,64 @@ /** - * Return the initialization parameters for the TrustManager. - * Currently, only the default PKIX is supported. + * Return the initialization parameters for the TrustManager. Currently, only the default PKIX is + * supported. + * + * @param crlf The path to the CRL file. + * @param trustStore The configured TrustStore. + * @param revocationEnabled Should the JSSE provider perform revocation checks? Ignored if {@code crlf} is non-null. + * Configuration of revocation checks are expected to be via proprietary JSSE provider + * methods. * - * @param crlf The path to the CRL file. - * @param trustStore The configured TrustStore. - * @param revocationEnabled Should the JSSE provider perform revocation - * checks? Ignored if {@code crlf} is non-null. - * Configuration of revocation checks are expected - * to be via proprietary JSSE provider methods. * @return The parameters including the CRLs and TrustStore. + * * @throws Exception An error occurred */ - protected CertPathParameters getParameters(String crlf, KeyStore trustStore, - boolean revocationEnabled) throws Exception { + protected CertPathParameters getParameters(final String crlf, final KeyStore trustStore, + final boolean revocationEnabled) throws Exception { - PKIXBuilderParameters xparams = - new PKIXBuilderParameters(trustStore, new X509CertSelector()); + boolean enableRevocation = revocationEnabled; + + PKIXBuilderParameters xparams = new PKIXBuilderParameters(trustStore, new X509CertSelector()); if (crlf != null && !crlf.isEmpty()) { Collection crls = getCRLs(crlf); CertStoreParameters csp = new CollectionCertStoreParameters(crls); CertStore store = CertStore.getInstance("Collection", csp); xparams.addCertStore(store); - xparams.setRevocationEnabled(true); - } else { - xparams.setRevocationEnabled(revocationEnabled); + enableRevocation = true; } + + if (sslHostConfig.getOcspEnabled()) { + PKIXRevocationChecker revocationChecker =(PKIXRevocationChecker) CertPathValidator.getInstance("PKIX").getRevocationChecker(); + if (sslHostConfig.getOcspSoftFail()) { + revocationChecker.setOptions(EnumSet.of(PKIXRevocationChecker.Option.SOFT_FAIL)); + } else { + revocationChecker.setOptions(Collections.emptySet()); + } + xparams.addCertPathChecker(revocationChecker); + enableRevocation = true; + } + + xparams.setRevocationEnabled(enableRevocation); + xparams.setMaxPathLength(sslHostConfig.getCertificateVerificationDepth()); + return xparams; } /** * Load the collection of CRLs. + * * @param crlf The path to the CRL file. + * * @return the CRLs collection - * @throws IOException Error reading CRL file - * @throws CRLException CRL error + * + * @throws IOException Error reading CRL file + * @throws CRLException CRL error * @throws CertificateException Error processing certificate */ - protected Collection getCRLs(String crlf) - throws IOException, CRLException, CertificateException { + protected Collection getCRLs(String crlf) throws IOException, CRLException, CertificateException { Collection crls; CertificateFactory cf = CertificateFactory.getInstance("X.509"); @@ -574,8 +580,12 @@ protected abstract Set getImplementedProtocols(); + protected abstract Set getImplementedCiphers(); + protected abstract Log getLog(); + protected abstract boolean isTls13RenegAuthAvailable(); + protected abstract SSLContext createSSLContextInternal(List negotiableProtocols) throws Exception; } diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/net/SecureNio2Channel.java tomcat10-10.1.52/java/org/apache/tomcat/util/net/SecureNio2Channel.java --- tomcat10-10.1.40/java/org/apache/tomcat/util/net/SecureNio2Channel.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/net/SecureNio2Channel.java 2026-01-23 19:33:36.000000000 +0000 @@ -44,12 +44,14 @@ import org.apache.tomcat.util.buf.ByteBufferUtils; import org.apache.tomcat.util.net.TLSClientHelloExtractor.ExtractorResult; import org.apache.tomcat.util.net.openssl.ciphers.Cipher; +import org.apache.tomcat.util.net.openssl.ciphers.Group; +import org.apache.tomcat.util.net.openssl.ciphers.SignatureScheme; import org.apache.tomcat.util.res.StringManager; /** * Implementation of a secure socket channel for NIO2. */ -public class SecureNio2Channel extends Nio2Channel { +public class SecureNio2Channel extends Nio2Channel { private static final Log log = LogFactory.getLog(SecureNio2Channel.class); private static final StringManager sm = StringManager.getManager(SecureNio2Channel.class); @@ -71,7 +73,7 @@ private volatile boolean handshakeComplete = false; private final AtomicInteger handshakeWrapQueueLength = new AtomicInteger(); - private volatile HandshakeStatus handshakeStatus; //gets set by handshake + private volatile HandshakeStatus handshakeStatus; // gets set by handshake protected boolean closed; protected boolean closing; @@ -79,8 +81,8 @@ private final Map> additionalTlsAttributes = new HashMap<>(); private volatile boolean unwrapBeforeRead; - private final CompletionHandler> handshakeReadCompletionHandler; - private final CompletionHandler> handshakeWriteCompletionHandler; + private final CompletionHandler> handshakeReadCompletionHandler; + private final CompletionHandler> handshakeWriteCompletionHandler; public SecureNio2Channel(SocketBufferHandler bufHandler, Nio2Endpoint endpoint) { super(bufHandler); @@ -96,9 +98,7 @@ handshakeWriteCompletionHandler = new HandshakeWriteCompletionHandler(); } - - private class HandshakeReadCompletionHandler - implements CompletionHandler> { + private class HandshakeReadCompletionHandler implements CompletionHandler> { @Override public void completed(Integer result, SocketWrapperBase attachment) { if (result.intValue() < 0) { @@ -107,6 +107,7 @@ endpoint.processSocket(attachment, SocketEvent.OPEN_READ, false); } } + @Override public void failed(Throwable exc, SocketWrapperBase attachment) { endpoint.processSocket(attachment, SocketEvent.ERROR, false); @@ -114,8 +115,7 @@ } - private class HandshakeWriteCompletionHandler - implements CompletionHandler> { + private class HandshakeWriteCompletionHandler implements CompletionHandler> { @Override public void completed(Integer result, SocketWrapperBase attachment) { if (result.intValue() < 0) { @@ -124,6 +124,7 @@ endpoint.processSocket(attachment, SocketEvent.OPEN_WRITE, false); } } + @Override public void failed(Throwable exc, SocketWrapperBase attachment) { endpoint.processSocket(attachment, SocketEvent.ERROR, false); @@ -132,8 +133,7 @@ @Override - public void reset(AsynchronousSocketChannel channel, SocketWrapperBase socket) - throws IOException { + public void reset(AsynchronousSocketChannel channel, SocketWrapperBase socket) throws IOException { super.reset(channel, socket); sslEngine = null; sniComplete = false; @@ -157,6 +157,7 @@ private class FutureFlush implements Future { private Future integer; private Exception e = null; + protected FutureFlush() { try { integer = sc.write(netOutBuffer); @@ -164,30 +165,33 @@ this.e = e; } } + @Override public boolean cancel(boolean mayInterruptIfRunning) { return e != null || integer.cancel(mayInterruptIfRunning); } + @Override public boolean isCancelled() { return e != null || integer.isCancelled(); } + @Override public boolean isDone() { return e != null || integer.isDone(); } + @Override - public Boolean get() throws InterruptedException, - ExecutionException { + public Boolean get() throws InterruptedException, ExecutionException { if (e != null) { throw new ExecutionException(e); } return Boolean.valueOf(integer.get().intValue() >= 0); } + @Override public Boolean get(long timeout, TimeUnit unit) - throws InterruptedException, ExecutionException, - TimeoutException { + throws InterruptedException, ExecutionException, TimeoutException { if (e != null) { throw new ExecutionException(e); } @@ -198,8 +202,8 @@ /** * Flush the channel. * - * @return true if the network buffer has been flushed out and - * is empty else false (as a future) + * @return true if the network buffer has been flushed out and is empty else false (as a + * future) */ @Override public Future flush() { @@ -207,17 +211,15 @@ } /** - * Performs SSL handshake, non-blocking, but performs NEED_TASK on the same - * thread. Hence, you should never call this method using your Acceptor - * thread, as you would slow down your system significantly. + * Performs SSL handshake, non-blocking, but performs NEED_TASK on the same thread. Hence, you should never call + * this method using your Acceptor thread, as you would slow down your system significantly. *

      - * The return for this operation is 0 if the handshake is complete and a - * positive value if it is not complete. In the event of a positive value - * coming back, the appropriate read/write will already have been called - * with an appropriate CompletionHandler. + * The return for this operation is 0 if the handshake is complete and a positive value if it is not complete. In + * the event of a positive value coming back, the appropriate read/write will already have been called with an + * appropriate CompletionHandler. * - * @return 0 if hand shake is complete, negative if the socket needs to - * close and positive if the handshake is incomplete + * @return 0 if hand shake is complete, negative if the socket needs to close and positive if the handshake is + * incomplete * * @throws IOException if an error occurs during the handshake */ @@ -228,7 +230,7 @@ protected int handshakeInternal(boolean async) throws IOException { if (handshakeComplete) { - return 0; //we have done our initial handshake + return 0; // we have done our initial handshake } if (!sniComplete) { @@ -246,27 +248,27 @@ while (!handshakeComplete) { switch (handshakeStatus) { case NOT_HANDSHAKING: { - //should never happen + // should never happen throw new IOException(sm.getString("channel.nio.ssl.notHandshaking")); } case FINISHED: { if (endpoint.hasNegotiableProtocols()) { if (sslEngine instanceof SSLUtil.ProtocolInfo) { - socketWrapper.setNegotiatedProtocol( - ((SSLUtil.ProtocolInfo) sslEngine).getNegotiatedProtocol()); + socketWrapper + .setNegotiatedProtocol(((SSLUtil.ProtocolInfo) sslEngine).getNegotiatedProtocol()); } else { socketWrapper.setNegotiatedProtocol(sslEngine.getApplicationProtocol()); } } - //we are complete if we have delivered the last package + // we are complete if we have delivered the last package handshakeComplete = !netOutBuffer.hasRemaining(); - //return 0 if we are complete, otherwise we still have data to write + // return 0 if we are complete, otherwise we still have data to write if (handshakeComplete) { return 0; } else { if (async) { - sc.write(netOutBuffer, AbstractEndpoint.toTimeout(timeout), - TimeUnit.MILLISECONDS, socketWrapper, handshakeWriteCompletionHandler); + sc.write(netOutBuffer, AbstractEndpoint.toTimeout(timeout), TimeUnit.MILLISECONDS, + socketWrapper, handshakeWriteCompletionHandler); } else { try { if (timeout > 0) { @@ -282,7 +284,7 @@ } } case NEED_WRAP: { - //perform the wrap function + // perform the wrap function try { handshake = handshakeWrap(); } catch (SSLException e) { @@ -296,14 +298,15 @@ } else if (handshake.getStatus() == Status.CLOSED) { return -1; } else { - //wrap should always work with our buffers - throw new IOException(sm.getString("channel.nio.ssl.unexpectedStatusDuringWrap", handshake.getStatus())); + // wrap should always work with our buffers + throw new IOException( + sm.getString("channel.nio.ssl.unexpectedStatusDuringWrap", handshake.getStatus())); } if (handshakeStatus != HandshakeStatus.NEED_UNWRAP || netOutBuffer.remaining() > 0) { - //should actually return OP_READ if we have NEED_UNWRAP + // should actually return OP_READ if we have NEED_UNWRAP if (async) { - sc.write(netOutBuffer, AbstractEndpoint.toTimeout(timeout), - TimeUnit.MILLISECONDS, socketWrapper, handshakeWriteCompletionHandler); + sc.write(netOutBuffer, AbstractEndpoint.toTimeout(timeout), TimeUnit.MILLISECONDS, + socketWrapper, handshakeWriteCompletionHandler); } else { try { if (timeout > 0) { @@ -317,22 +320,22 @@ } return 1; } - //fall down to NEED_UNWRAP on the same call, will result in a - //BUFFER_UNDERFLOW if it needs data + // fall down to NEED_UNWRAP on the same call, will result in a + // BUFFER_UNDERFLOW if it needs data } //$FALL-THROUGH$ case NEED_UNWRAP: { - //perform the unwrap function + // perform the unwrap function handshake = handshakeUnwrap(); if (handshake.getStatus() == Status.OK) { if (handshakeStatus == HandshakeStatus.NEED_TASK) { handshakeStatus = tasks(); } } else if (handshake.getStatus() == Status.BUFFER_UNDERFLOW) { - //read more data + // read more data if (async) { - sc.read(netInBuffer, AbstractEndpoint.toTimeout(timeout), - TimeUnit.MILLISECONDS, socketWrapper, handshakeReadCompletionHandler); + sc.read(netInBuffer, AbstractEndpoint.toTimeout(timeout), TimeUnit.MILLISECONDS, + socketWrapper, handshakeReadCompletionHandler); } else { try { int read; @@ -350,7 +353,8 @@ } return 1; } else { - throw new IOException(sm.getString("channel.nio.ssl.unexpectedStatusDuringUnwrap", handshake.getStatus())); + throw new IOException( + sm.getString("channel.nio.ssl.unexpectedStatusDuringUnwrap", handshake.getStatus())); } break; } @@ -358,26 +362,26 @@ handshakeStatus = tasks(); break; } - default: throw new IllegalStateException(sm.getString("channel.nio.ssl.invalidStatus", handshakeStatus)); + default: + throw new IllegalStateException(sm.getString("channel.nio.ssl.invalidStatus", handshakeStatus)); } } - //return 0 if we are complete, otherwise recurse to process the task + // return 0 if we are complete, otherwise recurse to process the task return handshakeComplete ? 0 : handshakeInternal(async); } /* - * Peeks at the initial network bytes to determine if the SNI extension is - * present and, if it is, what host name has been requested. Based on the - * provided host name, configure the SSLEngine for this connection. + * Peeks at the initial network bytes to determine if the SNI extension is present and, if it is, what host name has + * been requested. Based on the provided host name, configure the SSLEngine for this connection. */ private int processSNI() throws IOException { // If there is no data to process, trigger a read immediately. This is // an optimisation for the typical case so we don't create an // SNIExtractor only to discover there is no data to process if (netInBuffer.position() == 0) { - sc.read(netInBuffer, AbstractEndpoint.toTimeout(endpoint.getConnectionTimeout()), - TimeUnit.MILLISECONDS, socketWrapper, handshakeReadCompletionHandler); + sc.read(netInBuffer, AbstractEndpoint.toTimeout(endpoint.getConnectionTimeout()), TimeUnit.MILLISECONDS, + socketWrapper, handshakeReadCompletionHandler); return 1; } @@ -388,60 +392,70 @@ // extractor needed more data to process but netInBuffer was full so // expand the buffer and read some more data. int newLimit = Math.min(netInBuffer.capacity() * 2, endpoint.getSniParseLimit()); - log.info(sm.getString("channel.nio.ssl.expandNetInBuffer", - Integer.toString(newLimit))); + log.info(sm.getString("channel.nio.ssl.expandNetInBuffer", Integer.toString(newLimit))); netInBuffer = ByteBufferUtils.expand(netInBuffer, newLimit); - sc.read(netInBuffer, AbstractEndpoint.toTimeout(endpoint.getConnectionTimeout()), - TimeUnit.MILLISECONDS, socketWrapper, handshakeReadCompletionHandler); + sc.read(netInBuffer, AbstractEndpoint.toTimeout(endpoint.getConnectionTimeout()), TimeUnit.MILLISECONDS, + socketWrapper, handshakeReadCompletionHandler); return 1; } String hostName = null; List clientRequestedCiphers = null; List clientRequestedApplicationProtocols = null; + List clientSupportedGroups = null; + List clientSignatureSchemes = null; switch (extractor.getResult()) { - case COMPLETE: - hostName = extractor.getSNIValue(); - clientRequestedApplicationProtocols = - extractor.getClientRequestedApplicationProtocols(); - //$FALL-THROUGH$ to set the client requested ciphers - case NOT_PRESENT: - clientRequestedCiphers = extractor.getClientRequestedCiphers(); - break; - case NEED_READ: - sc.read(netInBuffer, AbstractEndpoint.toTimeout(endpoint.getConnectionTimeout()), - TimeUnit.MILLISECONDS, socketWrapper, handshakeReadCompletionHandler); - return 1; - case UNDERFLOW: - // Unable to buffer enough data to read SNI extension data - if (log.isDebugEnabled()) { - log.debug(sm.getString("channel.nio.ssl.sniDefault")); - } - hostName = endpoint.getDefaultSSLHostConfigName(); - clientRequestedCiphers = Collections.emptyList(); - break; - case NON_SECURE: - netOutBuffer.clear(); - netOutBuffer.put(TLSClientHelloExtractor.USE_TLS_RESPONSE); - netOutBuffer.flip(); - flush(); - throw new IOException(sm.getString("channel.nio.ssl.foundHttp")); + case COMPLETE: + hostName = extractor.getSNIValue(); + socketWrapper.setSniHostName(hostName); + clientRequestedApplicationProtocols = extractor.getClientRequestedApplicationProtocols(); + //$FALL-THROUGH$ to set the client requested ciphers + case NOT_PRESENT: + clientRequestedCiphers = extractor.getClientRequestedCiphers(); + clientSupportedGroups = extractor.getClientSupportedGroups(); + clientSignatureSchemes = extractor.getClientSignatureSchemes(); + break; + case NEED_READ: + sc.read(netInBuffer, AbstractEndpoint.toTimeout(endpoint.getConnectionTimeout()), TimeUnit.MILLISECONDS, + socketWrapper, handshakeReadCompletionHandler); + return 1; + case UNDERFLOW: + // Unable to buffer enough data to read SNI extension data + if (log.isDebugEnabled()) { + log.debug(sm.getString("channel.nio.ssl.sniDefault")); + } + hostName = endpoint.getDefaultSSLHostConfigName(); + clientRequestedCiphers = Collections.emptyList(); + break; + case NON_SECURE: + netOutBuffer.clear(); + netOutBuffer.put(TLSClientHelloExtractor.USE_TLS_RESPONSE); + netOutBuffer.flip(); + flush(); + throw new IOException(sm.getString("channel.nio.ssl.foundHttp")); } if (log.isTraceEnabled()) { log.trace(sm.getString("channel.nio.ssl.sniHostName", sc, hostName)); } - sslEngine = endpoint.createSSLEngine(hostName, clientRequestedCiphers, - clientRequestedApplicationProtocols); + try { + AbstractJsseEndpoint.clientRequestedProtocolsThreadLocal.set(extractor.getClientRequestedProtocols()); + AbstractJsseEndpoint.clientSupportedGroupsThreadLocal.set(clientSupportedGroups); + AbstractJsseEndpoint.clientSignatureSchemesThreadLocal.set(clientSignatureSchemes); + sslEngine = endpoint.createSSLEngine(hostName, clientRequestedCiphers, clientRequestedApplicationProtocols); + } finally { + AbstractJsseEndpoint.clientRequestedProtocolsThreadLocal.set(null); + AbstractJsseEndpoint.clientSupportedGroupsThreadLocal.set(null); + AbstractJsseEndpoint.clientSignatureSchemesThreadLocal.set(null); + } // Populate additional TLS attributes obtained from the handshake that // aren't available from the session additionalTlsAttributes.put(SSLSupport.REQUESTED_PROTOCOL_VERSIONS_KEY, extractor.getClientRequestedProtocols()); - additionalTlsAttributes.put(SSLSupport.REQUESTED_CIPHERS_KEY, - extractor.getClientRequestedCipherNames()); + additionalTlsAttributes.put(SSLSupport.REQUESTED_CIPHERS_KEY, extractor.getClientRequestedCipherNames()); // Ensure the application buffers (which have to be created earlier) are // big enough. @@ -467,14 +481,15 @@ /** - * Force a blocking handshake to take place for this key. - * This requires that both network and application buffers have been emptied out prior to this call taking place, or a - * IOException will be thrown. - * @throws IOException - if an IO exception occurs or if application or network buffers contain data + * Force a blocking handshake to take place for this key. This requires that both network and application buffers + * have been emptied out prior to this call taking place, or a IOException will be thrown. + * + * @throws IOException - if an IO exception occurs or if application or network buffers contain + * data * @throws java.net.SocketTimeoutException - if a socket operation timed out */ public void rehandshake() throws IOException { - //validate the network buffers are empty + // validate the network buffers are empty if (netInBuffer.position() > 0 && netInBuffer.position() < netInBuffer.limit()) { throw new IOException(sm.getString("channel.nio.ssl.netInputNotEmpty")); } @@ -495,7 +510,7 @@ getBufHandler().reset(); handshakeComplete = false; - //initiate handshake + // initiate handshake sslEngine.beginHandshake(); handshakeStatus = sslEngine.getHandshakeStatus(); @@ -504,9 +519,12 @@ while (handshaking) { int hsStatus = handshakeInternal(false); switch (hsStatus) { - case -1 : throw new EOFException(sm.getString("channel.nio.ssl.eofDuringHandshake")); - case 0 : handshaking = false; break; - default : // Some blocking IO occurred, so iterate + case -1: + throw new EOFException(sm.getString("channel.nio.ssl.eofDuringHandshake")); + case 0: + handshaking = false; + break; + default: // Some blocking IO occurred, so iterate } } } catch (IOException x) { @@ -521,10 +539,11 @@ /** * Executes all the tasks needed on the same thread. + * * @return the status */ protected SSLEngineResult.HandshakeStatus tasks() { - Runnable r ; + Runnable r; while ((r = sslEngine.getDelegatedTask()) != null) { r.run(); } @@ -533,55 +552,58 @@ /** * Performs the WRAP function + * * @return the result + * * @throws IOException An IO error occurred */ protected SSLEngineResult handshakeWrap() throws IOException { - //this should never be called with a network buffer that contains data - //so we can clear it here. + // this should never be called with a network buffer that contains data + // so we can clear it here. netOutBuffer.clear(); - //perform the wrap + // perform the wrap getBufHandler().configureWriteBufferForRead(); SSLEngineResult result = sslEngine.wrap(getBufHandler().getWriteBuffer(), netOutBuffer); - //prepare the results to be written + // prepare the results to be written netOutBuffer.flip(); - //set the status + // set the status handshakeStatus = result.getHandshakeStatus(); return result; } /** * Perform handshake unwrap + * * @return the result + * * @throws IOException An IO error occurred */ protected SSLEngineResult handshakeUnwrap() throws IOException { SSLEngineResult result; boolean cont; - //loop while we can perform pure SSLEngine data + // loop while we can perform pure SSLEngine data do { - //prepare the buffer with the incoming data + // prepare the buffer with the incoming data netInBuffer.flip(); - //call unwrap + // call unwrap getBufHandler().configureReadBufferForWrite(); result = sslEngine.unwrap(netInBuffer, getBufHandler().getReadBuffer()); /* * ByteBuffer.compact() is an optional method but netInBuffer is created from either ByteBuffer.allocate() - * or ByteBuffer.allocateDirect() and the ByteBuffers returned by those methods do implement compact(). - * The ByteBuffer must be in 'read from' mode when compact() is called and will be in 'write to' mode + * or ByteBuffer.allocateDirect() and the ByteBuffers returned by those methods do implement compact(). The + * ByteBuffer must be in 'read from' mode when compact() is called and will be in 'write to' mode * afterwards. */ netInBuffer.compact(); - //read in the status + // read in the status handshakeStatus = result.getHandshakeStatus(); if (result.getStatus() == SSLEngineResult.Status.OK && - result.getHandshakeStatus() == HandshakeStatus.NEED_TASK) { - //execute tasks if we need to + result.getHandshakeStatus() == HandshakeStatus.NEED_TASK) { + // execute tasks if we need to handshakeStatus = tasks(); } - //perform another unwrap? - cont = result.getStatus() == SSLEngineResult.Status.OK && - handshakeStatus == HandshakeStatus.NEED_UNWRAP; + // perform another unwrap? + cont = result.getStatus() == SSLEngineResult.Status.OK && handshakeStatus == HandshakeStatus.NEED_UNWRAP; } while (cont); return result; } @@ -597,11 +619,15 @@ /** * Sends an SSL close message, will not physically close the connection here.
      * To close the connection, you could do something like - *

      
      +     *
      +     * 
      +     * 
            *   close();
            *   while (isOpen() && !myTimeoutFunction()) Thread.sleep(25);
            *   if ( isOpen() ) close(true); //forces a close if you timed out
      -     * 
      + *
      + *
      + * * @throws IOException if an I/O error occurs * @throws IOException if there is data on the outgoing network buffer, and we are unable to flush it */ @@ -638,17 +664,17 @@ closeSilently(); throw new IOException(sm.getString("channel.nio.ssl.pendingWriteDuringClose"), e); } - //prep the buffer for the close message + // prep the buffer for the close message netOutBuffer.clear(); - //perform the close, since we called sslEngine.closeOutbound + // perform the close, since we called sslEngine.closeOutbound SSLEngineResult handshake = sslEngine.wrap(getEmptyBuf(), netOutBuffer); - //we should be in a close state + // we should be in a close state if (handshake.getStatus() != SSLEngineResult.Status.CLOSED) { throw new IOException(sm.getString("channel.nio.ssl.invalidCloseState")); } - //prepare the buffer for writing + // prepare the buffer for writing netOutBuffer.flip(); - //if there is data to be written + // if there is data to be written try { if (timeout > 0) { if (!flush().get(timeout, TimeUnit.MILLISECONDS).booleanValue()) { @@ -669,7 +695,7 @@ throw new IOException(sm.getString("channel.nio.ssl.pendingWriteDuringClose"), e); } - //is the channel closed? + // is the channel closed? closed = (!netOutBuffer.hasRemaining() && (handshake.getHandshakeStatus() != HandshakeStatus.NEED_WRAP)); } @@ -701,6 +727,7 @@ private class FutureRead implements Future { private ByteBuffer dst; private Future integer; + private FutureRead(ByteBuffer dst) { this.dst = dst; if (unwrapBeforeRead || netInBuffer.position() > 0) { @@ -709,61 +736,69 @@ this.integer = sc.read(netInBuffer); } } + @Override public boolean cancel(boolean mayInterruptIfRunning) { return integer != null && integer.cancel(mayInterruptIfRunning); } + @Override public boolean isCancelled() { return integer != null && integer.isCancelled(); } + @Override public boolean isDone() { return integer == null || integer.isDone(); } + @Override public Integer get() throws InterruptedException, ExecutionException { try { - return (integer == null) ? unwrap(netInBuffer.position(), -1, TimeUnit.MILLISECONDS) : unwrap(integer.get().intValue(), -1, TimeUnit.MILLISECONDS); + return (integer == null) ? unwrap(netInBuffer.position(), -1, TimeUnit.MILLISECONDS) : + unwrap(integer.get().intValue(), -1, TimeUnit.MILLISECONDS); } catch (TimeoutException e) { // Cannot happen: no timeout throw new ExecutionException(e); } } + @Override public Integer get(long timeout, TimeUnit unit) - throws InterruptedException, ExecutionException, - TimeoutException { - return (integer == null) ? unwrap(netInBuffer.position(), timeout, unit) : unwrap(integer.get(timeout, unit).intValue(), timeout, unit); + throws InterruptedException, ExecutionException, TimeoutException { + return (integer == null) ? unwrap(netInBuffer.position(), timeout, unit) : + unwrap(integer.get(timeout, unit).intValue(), timeout, unit); } - private Integer unwrap(int nRead, long timeout, TimeUnit unit) throws ExecutionException, TimeoutException, InterruptedException { - //are we in the middle of closing or closed? + + private Integer unwrap(int nRead, long timeout, TimeUnit unit) + throws ExecutionException, TimeoutException, InterruptedException { + // are we in the middle of closing or closed? if (closing || closed) { return Integer.valueOf(-1); } - //did we reach EOF? if so send EOF up one layer. + // did we reach EOF? if so send EOF up one layer. if (nRead < 0) { return Integer.valueOf(-1); } - //the data read + // the data read int read = 0; - //the SSL engine result + // the SSL engine result SSLEngineResult unwrap; do { - //prepare the buffer + // prepare the buffer netInBuffer.flip(); - //unwrap the data + // unwrap the data try { unwrap = sslEngine.unwrap(netInBuffer, dst); } catch (SSLException e) { throw new ExecutionException(e); } - //compact the buffer + // compact the buffer netInBuffer.compact(); if (unwrap.getStatus() == Status.OK || unwrap.getStatus() == Status.BUFFER_UNDERFLOW) { - //we did receive some data, add it to our total + // we did receive some data, add it to our total read += unwrap.bytesProduced(); - //perform any tasks if needed + // perform any tasks if needed if (unwrap.getHandshakeStatus() == HandshakeStatus.NEED_TASK) { tasks(); } else if (unwrap.getHandshakeStatus() == HandshakeStatus.NEED_WRAP) { @@ -772,7 +807,7 @@ new IOException(sm.getString("channel.nio.ssl.handshakeWrapQueueTooLong"))); } } - //if we need more network data, then bail out for now. + // if we need more network data, then bail out for now. if (unwrap.getStatus() == Status.BUFFER_UNDERFLOW) { if (read == 0) { integer = sc.read(netInBuffer); @@ -796,24 +831,24 @@ // since the buffer was created. if (dst == getBufHandler().getReadBuffer()) { // This is the normal case for this code - getBufHandler() - .expand(sslEngine.getSession().getApplicationBufferSize()); + getBufHandler().expand(sslEngine.getSession().getApplicationBufferSize()); dst = getBufHandler().getReadBuffer(); } else if (dst == getAppReadBufHandler().getByteBuffer()) { - getAppReadBufHandler() - .expand(sslEngine.getSession().getApplicationBufferSize()); + getAppReadBufHandler().expand(sslEngine.getSession().getApplicationBufferSize()); dst = getAppReadBufHandler().getByteBuffer(); } else { // Can't expand the buffer as there is no way to signal // to the caller that the buffer has been replaced. - throw new ExecutionException(new IOException(sm.getString("channel.nio.ssl.unwrapFailResize", unwrap.getStatus()))); + throw new ExecutionException(new IOException( + sm.getString("channel.nio.ssl.unwrapFailResize", unwrap.getStatus()))); } } } else { // Something else went wrong - throw new ExecutionException(new IOException(sm.getString("channel.nio.ssl.unwrapFail", unwrap.getStatus()))); + throw new ExecutionException( + new IOException(sm.getString("channel.nio.ssl.unwrapFail", unwrap.getStatus()))); } - } while (netInBuffer.position() != 0); //continue to unwrapping as long as the input buffer has stuff + } while (netInBuffer.position() != 0); // continue to unwrapping as long as the input buffer has stuff unwrapBeforeRead = !dst.hasRemaining(); return Integer.valueOf(read); } @@ -823,7 +858,9 @@ * Reads a sequence of bytes from this channel into the given buffer. * * @param dst The buffer into which bytes are to be transferred + * * @return The number of bytes read, possibly zero, or -1 if the channel has reached end-of-stream + * * @throws IllegalStateException if the handshake was not completed */ @Override @@ -839,27 +876,32 @@ private Future integer = null; private int written = 0; private Throwable t = null; + private FutureWrite(ByteBuffer src) { this.src = src; - //are we closing or closed? + // are we closing or closed? if (closing || closed) { t = new IOException(sm.getString("channel.nio.ssl.closing")); } else { wrap(); } } + @Override public boolean cancel(boolean mayInterruptIfRunning) { return integer.cancel(mayInterruptIfRunning); } + @Override public boolean isCancelled() { return integer.isCancelled(); } + @Override public boolean isDone() { return integer.isDone(); } + @Override public Integer get() throws InterruptedException, ExecutionException { if (t != null) { @@ -875,10 +917,10 @@ return Integer.valueOf(written); } } + @Override public Integer get(long timeout, TimeUnit unit) - throws InterruptedException, ExecutionException, - TimeoutException { + throws InterruptedException, ExecutionException, TimeoutException { if (t != null) { throw new ExecutionException(t); } @@ -892,6 +934,7 @@ return Integer.valueOf(written); } } + protected void wrap() { try { if (!netOutBuffer.hasRemaining()) { @@ -920,6 +963,7 @@ * Writes a sequence of bytes to this channel from the given buffer. * * @param src The buffer from which bytes are to be retrieved + * * @return The number of bytes written, possibly zero */ @Override @@ -928,9 +972,8 @@ } @Override - public void read(final ByteBuffer dst, - final long timeout, final TimeUnit unit, final A attachment, - final CompletionHandler handler) { + public void read(final ByteBuffer dst, final long timeout, final TimeUnit unit, final A attachment, + final CompletionHandler handler) { // Check state if (closing || closed) { handler.completed(Integer.valueOf(-1), attachment); @@ -939,7 +982,7 @@ if (!handshakeComplete) { throw new IllegalStateException(sm.getString("channel.nio.ssl.incompleteHandshake")); } - CompletionHandler readCompletionHandler = new CompletionHandler<>() { + CompletionHandler readCompletionHandler = new CompletionHandler<>() { @Override public void completed(Integer nBytes, A attach) { if (nBytes.intValue() < 0) { @@ -947,30 +990,31 @@ } else { try { ByteBuffer dst2 = dst; - //the data read + // the data read int read = 0; - //the SSL engine result + // the SSL engine result SSLEngineResult unwrap; do { - //prepare the buffer + // prepare the buffer netInBuffer.flip(); - //unwrap the data + // unwrap the data unwrap = sslEngine.unwrap(netInBuffer, dst2); - //compact the buffer + // compact the buffer netInBuffer.compact(); if (unwrap.getStatus() == Status.OK || unwrap.getStatus() == Status.BUFFER_UNDERFLOW) { - //we did receive some data, add it to our total + // we did receive some data, add it to our total read += unwrap.bytesProduced(); - //perform any tasks if needed + // perform any tasks if needed if (unwrap.getHandshakeStatus() == HandshakeStatus.NEED_TASK) { tasks(); } else if (unwrap.getHandshakeStatus() == HandshakeStatus.NEED_WRAP) { - if (handshakeWrapQueueLength.incrementAndGet() > HANDSHAKE_WRAP_QUEUE_LENGTH_LIMIT) { + if (handshakeWrapQueueLength + .incrementAndGet() > HANDSHAKE_WRAP_QUEUE_LENGTH_LIMIT) { throw new ExecutionException(new IOException( sm.getString("channel.nio.ssl.handshakeWrapQueueTooLong"))); } } - //if we need more network data, then bail out for now. + // if we need more network data, then bail out for now. if (unwrap.getStatus() == Status.BUFFER_UNDERFLOW) { if (read == 0) { sc.read(netInBuffer, timeout, unit, attachment, this); @@ -990,10 +1034,10 @@ // since the buffer was created. if (dst2 == getBufHandler().getReadBuffer()) { // This is the normal case for this code - getBufHandler().expand( - sslEngine.getSession().getApplicationBufferSize()); + getBufHandler().expand(sslEngine.getSession().getApplicationBufferSize()); dst2 = getBufHandler().getReadBuffer(); - } else if (getAppReadBufHandler() != null && dst2 == getAppReadBufHandler().getByteBuffer()) { + } else if (getAppReadBufHandler() != null && + dst2 == getAppReadBufHandler().getByteBuffer()) { getAppReadBufHandler() .expand(sslEngine.getSession().getApplicationBufferSize()); dst2 = getAppReadBufHandler().getByteBuffer(); @@ -1008,7 +1052,7 @@ // Something else went wrong throw new IOException(sm.getString("channel.nio.ssl.unwrapFail", unwrap.getStatus())); } - // continue to unwrap as long as the input buffer has stuff + // continue to unwrap as long as the input buffer has stuff } while (netInBuffer.position() != 0); unwrapBeforeRead = !dst2.hasRemaining(); // If everything is OK, so complete @@ -1018,6 +1062,7 @@ } } } + @Override public void failed(Throwable exc, A attach) { handler.failed(exc, attach); @@ -1031,9 +1076,8 @@ } @Override - public void read(final ByteBuffer[] dsts, final int offset, final int length, - final long timeout, final TimeUnit unit, final A attachment, - final CompletionHandler handler) { + public void read(final ByteBuffer[] dsts, final int offset, final int length, final long timeout, + final TimeUnit unit, final A attachment, final CompletionHandler handler) { if (offset < 0 || dsts == null || (offset + length) > dsts.length) { throw new IllegalArgumentException(); } @@ -1044,16 +1088,16 @@ if (!handshakeComplete) { throw new IllegalStateException(sm.getString("channel.nio.ssl.incompleteHandshake")); } - CompletionHandler readCompletionHandler = new CompletionHandler<>() { + CompletionHandler readCompletionHandler = new CompletionHandler<>() { @Override public void completed(Integer nBytes, A attach) { if (nBytes.intValue() < 0) { failed(new EOFException(), attach); } else { try { - //the data read + // the data read long read = 0; - //the SSL engine result + // the SSL engine result SSLEngineResult unwrap; ByteBuffer[] dsts2 = dsts; int length2 = length; @@ -1062,29 +1106,30 @@ if (overflowState == OverflowState.PROCESSING) { overflowState = OverflowState.DONE; } - //prepare the buffer + // prepare the buffer netInBuffer.flip(); - //unwrap the data + // unwrap the data unwrap = sslEngine.unwrap(netInBuffer, dsts2, offset, length2); - //compact the buffer + // compact the buffer netInBuffer.compact(); if (unwrap.getStatus() == Status.OK || unwrap.getStatus() == Status.BUFFER_UNDERFLOW) { - //we did receive some data, add it to our total + // we did receive some data, add it to our total read += unwrap.bytesProduced(); if (overflowState == OverflowState.DONE) { // Remove the data read into the overflow buffer read -= getBufHandler().getReadBuffer().position(); } - //perform any tasks if needed + // perform any tasks if needed if (unwrap.getHandshakeStatus() == HandshakeStatus.NEED_TASK) { tasks(); } else if (unwrap.getHandshakeStatus() == HandshakeStatus.NEED_WRAP) { - if (handshakeWrapQueueLength.incrementAndGet() > HANDSHAKE_WRAP_QUEUE_LENGTH_LIMIT) { + if (handshakeWrapQueueLength + .incrementAndGet() > HANDSHAKE_WRAP_QUEUE_LENGTH_LIMIT) { throw new ExecutionException(new IOException( sm.getString("channel.nio.ssl.handshakeWrapQueueTooLong"))); } } - //if we need more network data, then bail out for now. + // if we need more network data, then bail out for now. if (unwrap.getStatus() == Status.BUFFER_UNDERFLOW) { if (read == 0) { sc.read(netInBuffer, timeout, unit, attachment, this); @@ -1094,13 +1139,13 @@ } } } else if (unwrap.getStatus() == Status.BUFFER_OVERFLOW && read > 0) { - //buffer overflow can happen, if we have read data, then - //empty out the dst buffer before we do another read + // buffer overflow can happen, if we have read data, then + // empty out the dst buffer before we do another read break; } else if (unwrap.getStatus() == Status.BUFFER_OVERFLOW) { - //here we should trap BUFFER_OVERFLOW and call expand on the buffer - //for now, throw an exception, as we initialized the buffers - //in the constructor + // here we should trap BUFFER_OVERFLOW and call expand on the buffer + // for now, throw an exception, as we initialized the buffers + // in the constructor ByteBuffer readBuffer = getBufHandler().getReadBuffer(); boolean found = false; boolean resized = true; @@ -1114,8 +1159,10 @@ } dsts[offset + i] = getBufHandler().getReadBuffer(); found = true; - } else if (getAppReadBufHandler() != null && dsts[offset + i] == getAppReadBufHandler().getByteBuffer()) { - getAppReadBufHandler().expand(sslEngine.getSession().getApplicationBufferSize()); + } else if (getAppReadBufHandler() != null && + dsts[offset + i] == getAppReadBufHandler().getByteBuffer()) { + getAppReadBufHandler() + .expand(sslEngine.getSession().getApplicationBufferSize()); if (dsts[offset + i] == getAppReadBufHandler().getByteBuffer()) { resized = false; } @@ -1125,7 +1172,8 @@ } if (found) { if (!resized) { - throw new IOException(sm.getString("channel.nio.ssl.unwrapFail", unwrap.getStatus())); + throw new IOException( + sm.getString("channel.nio.ssl.unwrapFail", unwrap.getStatus())); } } else { // Add the main read buffer in the destinations and try again @@ -1163,6 +1211,7 @@ } } } + @Override public void failed(Throwable exc, A attach) { handler.failed(exc, attach); @@ -1176,8 +1225,8 @@ } @Override - public void write(final ByteBuffer src, final long timeout, final TimeUnit unit, - final A attachment, final CompletionHandler handler) { + public void write(final ByteBuffer src, final long timeout, final TimeUnit unit, final A attachment, + final CompletionHandler handler) { // Check state if (closing || closed) { handler.failed(new IOException(sm.getString("channel.nio.ssl.closing")), attachment); @@ -1197,29 +1246,28 @@ tasks(); } // Write data to the channel - sc.write(netOutBuffer, timeout, unit, attachment, - new CompletionHandler<>() { - @Override - public void completed(Integer nBytes, A attach) { - if (nBytes.intValue() < 0) { - failed(new EOFException(), attach); - } else if (netOutBuffer.hasRemaining()) { - sc.write(netOutBuffer, timeout, unit, attachment, this); - } else if (written == 0) { - // Special case, start over to avoid code duplication - write(src, timeout, unit, attachment, handler); - } else { - // Call the handler completed method with the - // consumed bytes number - handler.completed(Integer.valueOf(written), attach); - } + sc.write(netOutBuffer, timeout, unit, attachment, new CompletionHandler<>() { + @Override + public void completed(Integer nBytes, A attach) { + if (nBytes.intValue() < 0) { + failed(new EOFException(), attach); + } else if (netOutBuffer.hasRemaining()) { + sc.write(netOutBuffer, timeout, unit, attachment, this); + } else if (written == 0) { + // Special case, start over to avoid code duplication + write(src, timeout, unit, attachment, handler); + } else { + // Call the handler completed method with the + // consumed bytes number + handler.completed(Integer.valueOf(written), attach); } + } - @Override - public void failed(Throwable exc, A attach) { - handler.failed(exc, attach); - } - }); + @Override + public void failed(Throwable exc, A attach) { + handler.failed(exc, attach); + } + }); } else { throw new IOException(sm.getString("channel.nio.ssl.wrapFail", result.getStatus())); } @@ -1229,9 +1277,8 @@ } @Override - public void write(final ByteBuffer[] srcs, final int offset, final int length, - final long timeout, final TimeUnit unit, final A attachment, - final CompletionHandler handler) { + public void write(final ByteBuffer[] srcs, final int offset, final int length, final long timeout, + final TimeUnit unit, final A attachment, final CompletionHandler handler) { if ((offset < 0) || (length < 0) || (offset > srcs.length - length)) { throw new IndexOutOfBoundsException(); } @@ -1241,7 +1288,7 @@ return; } try { - // Prepare the output buffer + // Prepare the output buffer netOutBuffer.clear(); // Wrap the source data into the internal buffer SSLEngineResult result = sslEngine.wrap(srcs, offset, length, netOutBuffer); @@ -1280,7 +1327,7 @@ } catch (Exception e) { handler.failed(e, attachment); } - } + } @Override public boolean isHandshakeComplete() { diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/net/SecureNioChannel.java tomcat10-10.1.52/java/org/apache/tomcat/util/net/SecureNioChannel.java --- tomcat10-10.1.40/java/org/apache/tomcat/util/net/SecureNioChannel.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/net/SecureNioChannel.java 2026-01-23 19:33:36.000000000 +0000 @@ -41,6 +41,8 @@ import org.apache.tomcat.util.net.NioEndpoint.NioSocketWrapper; import org.apache.tomcat.util.net.TLSClientHelloExtractor.ExtractorResult; import org.apache.tomcat.util.net.openssl.ciphers.Cipher; +import org.apache.tomcat.util.net.openssl.ciphers.Group; +import org.apache.tomcat.util.net.openssl.ciphers.SignatureScheme; import org.apache.tomcat.util.res.StringManager; /** @@ -66,7 +68,7 @@ protected boolean handshakeComplete = false; protected boolean needHandshakeWrap = false; - protected HandshakeStatus handshakeStatus; //gets set by handshake + protected HandshakeStatus handshakeStatus; // gets set by handshake protected boolean closed = false; protected boolean closing = false; @@ -108,14 +110,17 @@ } } -//=========================================================================================== -// NIO SSL METHODS -//=========================================================================================== + // =========================================================================================== + // NIO SSL METHODS + // =========================================================================================== /** * Flushes the buffer to the network, non-blocking + * * @param buf ByteBuffer + * * @return boolean true if the buffer has been emptied out, false otherwise + * * @throws IOException An IO error occurred writing data */ protected boolean flush(ByteBuffer buf) throws IOException { @@ -128,26 +133,23 @@ } /** - * Performs SSL handshake, non-blocking, but performs NEED_TASK on the same - * thread. Hence, you should never call this method using your Acceptor - * thread, as you would slow down your system significantly. If the return - * value from this method is positive, the selection key should be - * registered interestOps given by the return value. + * Performs SSL handshake, non-blocking, but performs NEED_TASK on the same thread. Hence, you should never call + * this method using your Acceptor thread, as you would slow down your system significantly. If the return value + * from this method is positive, the selection key should be registered interestOps given by the return value. * - * @param read boolean - true if the underlying channel is readable + * @param read boolean - true if the underlying channel is readable * @param write boolean - true if the underlying channel is writable * - * @return 0 if handshake is complete, -1 if an error (other than an - * IOException) occurred, otherwise it returns a SelectionKey - * interestOps value + * @return 0 if handshake is complete, -1 if an error (other than an IOException) occurred, otherwise it returns a + * SelectionKey interestOps value * - * @throws IOException If an I/O error occurs during the handshake or if the - * handshake fails during wrapping or unwrapping + * @throws IOException If an I/O error occurs during the handshake or if the handshake fails during wrapping or + * unwrapping */ @Override public int handshake(boolean read, boolean write) throws IOException { if (handshakeComplete) { - return 0; //we have done our initial handshake + return 0; // we have done our initial handshake } if (!sniComplete) { @@ -160,7 +162,7 @@ } if (!flush(netOutBuffer)) { - return SelectionKey.OP_WRITE; //we still have data to write + return SelectionKey.OP_WRITE; // we still have data to write } SSLEngineResult handshake; @@ -168,23 +170,23 @@ while (!handshakeComplete) { switch (handshakeStatus) { case NOT_HANDSHAKING: - //should never happen + // should never happen throw new IOException(sm.getString("channel.nio.ssl.notHandshaking")); case FINISHED: if (endpoint.hasNegotiableProtocols()) { if (sslEngine instanceof SSLUtil.ProtocolInfo) { - socketWrapper.setNegotiatedProtocol( - ((SSLUtil.ProtocolInfo) sslEngine).getNegotiatedProtocol()); + socketWrapper + .setNegotiatedProtocol(((SSLUtil.ProtocolInfo) sslEngine).getNegotiatedProtocol()); } else { socketWrapper.setNegotiatedProtocol(sslEngine.getApplicationProtocol()); } } - //we are complete if we have delivered the last package + // we are complete if we have delivered the last package handshakeComplete = !netOutBuffer.hasRemaining(); - //return 0 if we are complete, otherwise we still have data to write + // return 0 if we are complete, otherwise we still have data to write return handshakeComplete ? 0 : SelectionKey.OP_WRITE; case NEED_WRAP: - //perform the wrap function + // perform the wrap function try { handshake = handshakeWrap(write); } catch (SSLException e) { @@ -199,28 +201,30 @@ flush(netOutBuffer); return -1; } else { - //wrap should always work with our buffers - throw new IOException(sm.getString("channel.nio.ssl.unexpectedStatusDuringWrap", handshake.getStatus())); + // wrap should always work with our buffers + throw new IOException( + sm.getString("channel.nio.ssl.unexpectedStatusDuringWrap", handshake.getStatus())); } if (handshakeStatus != HandshakeStatus.NEED_UNWRAP || (!flush(netOutBuffer))) { - //should actually return OP_READ if we have NEED_UNWRAP + // should actually return OP_READ if we have NEED_UNWRAP return SelectionKey.OP_WRITE; } - //fall down to NEED_UNWRAP on the same call, will result in a - //BUFFER_UNDERFLOW if it needs data - //$FALL-THROUGH$ + // fall down to NEED_UNWRAP on the same call, will result in a + // BUFFER_UNDERFLOW if it needs data + // $FALL-THROUGH$ case NEED_UNWRAP: - //perform the unwrap function + // perform the unwrap function handshake = handshakeUnwrap(read); if (handshake.getStatus() == Status.OK) { if (handshakeStatus == HandshakeStatus.NEED_TASK) { handshakeStatus = tasks(); } - } else if ( handshake.getStatus() == Status.BUFFER_UNDERFLOW ){ - //read more data, register again for OP_READ + } else if (handshake.getStatus() == Status.BUFFER_UNDERFLOW) { + // read more data, register again for OP_READ return SelectionKey.OP_READ; } else { - throw new IOException(sm.getString("channel.nio.ssl.unexpectedStatusDuringWrap", handshake.getStatus())); + throw new IOException( + sm.getString("channel.nio.ssl.unexpectedStatusDuringWrap", handshake.getStatus())); } break; case NEED_TASK: @@ -236,13 +240,11 @@ /* - * Peeks at the initial network bytes to determine if the SNI extension is - * present and, if it is, what host name has been requested. Based on the - * provided host name, configure the SSLEngine for this connection. - * - * @return 0 if SNI processing is complete, -1 if an error (other than an - * IOException) occurred, otherwise it returns a SelectionKey - * interestOps value + * Peeks at the initial network bytes to determine if the SNI extension is present and, if it is, what host name has + * been requested. Based on the provided host name, configure the SSLEngine for this connection. + * + * @return 0 if SNI processing is complete, -1 if an error (other than an IOException) occurred, otherwise it + * returns a SelectionKey interestOps value * * @throws IOException If an I/O error occurs during the SNI processing */ @@ -260,8 +262,7 @@ // extractor needed more data to process but netInBuffer was full so // expand the buffer and read some more data. int newLimit = Math.min(netInBuffer.capacity() * 2, endpoint.getSniParseLimit()); - log.info(sm.getString("channel.nio.ssl.expandNetInBuffer", - Integer.toString(newLimit))); + log.info(sm.getString("channel.nio.ssl.expandNetInBuffer", Integer.toString(newLimit))); netInBuffer = ByteBufferUtils.expand(netInBuffer, newLimit); if (sc.read(netInBuffer) < 0) { @@ -273,46 +274,57 @@ String hostName = null; List clientRequestedCiphers = null; List clientRequestedApplicationProtocols = null; + List clientSupportedGroups = null; + List clientSignatureSchemes = null; switch (extractor.getResult()) { - case COMPLETE: - hostName = extractor.getSNIValue(); - clientRequestedApplicationProtocols = - extractor.getClientRequestedApplicationProtocols(); - //$FALL-THROUGH$ to set the client requested ciphers - case NOT_PRESENT: - clientRequestedCiphers = extractor.getClientRequestedCiphers(); - break; - case NEED_READ: - return SelectionKey.OP_READ; - case UNDERFLOW: - // Unable to buffer enough data to read SNI extension data - if (log.isDebugEnabled()) { - log.debug(sm.getString("channel.nio.ssl.sniDefault")); - } - hostName = endpoint.getDefaultSSLHostConfigName(); - clientRequestedCiphers = Collections.emptyList(); - break; - case NON_SECURE: - netOutBuffer.clear(); - netOutBuffer.put(TLSClientHelloExtractor.USE_TLS_RESPONSE); - netOutBuffer.flip(); - flushOutbound(); - throw new IOException(sm.getString("channel.nio.ssl.foundHttp")); + case COMPLETE: + hostName = extractor.getSNIValue(); + socketWrapper.setSniHostName(hostName); + clientRequestedApplicationProtocols = extractor.getClientRequestedApplicationProtocols(); + //$FALL-THROUGH$ to set the client requested ciphers + case NOT_PRESENT: + clientRequestedCiphers = extractor.getClientRequestedCiphers(); + clientSupportedGroups = extractor.getClientSupportedGroups(); + clientSignatureSchemes = extractor.getClientSignatureSchemes(); + break; + case NEED_READ: + return SelectionKey.OP_READ; + case UNDERFLOW: + // Unable to buffer enough data to read SNI extension data + if (log.isDebugEnabled()) { + log.debug(sm.getString("channel.nio.ssl.sniDefault")); + } + hostName = endpoint.getDefaultSSLHostConfigName(); + clientRequestedCiphers = Collections.emptyList(); + break; + case NON_SECURE: + netOutBuffer.clear(); + netOutBuffer.put(TLSClientHelloExtractor.USE_TLS_RESPONSE); + netOutBuffer.flip(); + flushOutbound(); + throw new IOException(sm.getString("channel.nio.ssl.foundHttp")); } if (log.isTraceEnabled()) { log.trace(sm.getString("channel.nio.ssl.sniHostName", sc, hostName)); } - sslEngine = endpoint.createSSLEngine(hostName, clientRequestedCiphers, - clientRequestedApplicationProtocols); + try { + AbstractJsseEndpoint.clientRequestedProtocolsThreadLocal.set(extractor.getClientRequestedProtocols()); + AbstractJsseEndpoint.clientSupportedGroupsThreadLocal.set(clientSupportedGroups); + AbstractJsseEndpoint.clientSignatureSchemesThreadLocal.set(clientSignatureSchemes); + sslEngine = endpoint.createSSLEngine(hostName, clientRequestedCiphers, clientRequestedApplicationProtocols); + } finally { + AbstractJsseEndpoint.clientRequestedProtocolsThreadLocal.set(null); + AbstractJsseEndpoint.clientSupportedGroupsThreadLocal.set(null); + AbstractJsseEndpoint.clientSignatureSchemesThreadLocal.set(null); + } // Populate additional TLS attributes obtained from the handshake that // aren't available from the session additionalTlsAttributes.put(SSLSupport.REQUESTED_PROTOCOL_VERSIONS_KEY, extractor.getClientRequestedProtocols()); - additionalTlsAttributes.put(SSLSupport.REQUESTED_CIPHERS_KEY, - extractor.getClientRequestedCipherNames()); + additionalTlsAttributes.put(SSLSupport.REQUESTED_CIPHERS_KEY, extractor.getClientRequestedCipherNames()); // Ensure the application buffers (which have to be created earlier) are // big enough. @@ -338,16 +350,17 @@ /** - * Force a blocking handshake to take place for this key. - * This requires that both network and application buffers have been emptied out prior to this call taking place, or a - * IOException will be thrown. + * Force a blocking handshake to take place for this key. This requires that both network and application buffers + * have been emptied out prior to this call taking place, or a IOException will be thrown. + * * @param timeout - timeout in milliseconds for each socket operation - * @throws IOException - if an IO exception occurs or if application or network buffers contain data + * + * @throws IOException - if an IO exception occurs or if application or network buffers contain data * @throws SocketTimeoutException - if a socket operation timed out */ @SuppressWarnings("null") // key cannot be null public void rehandshake(long timeout) throws IOException { - //validate the network buffers are empty + // validate the network buffers are empty if (netInBuffer.position() > 0 && netInBuffer.position() < netInBuffer.limit()) { throw new IOException(sm.getString("channel.nio.ssl.netInputNotEmpty")); } @@ -372,12 +385,12 @@ while (handshaking) { int hsStatus = this.handshake(isReadable, isWritable); switch (hsStatus) { - case -1 : + case -1: throw new EOFException(sm.getString("channel.nio.ssl.eofDuringHandshake")); - case 0 : + case 0: handshaking = false; break; - default : + default: long now = System.currentTimeMillis(); if (selector == null) { selector = Selector.open(); @@ -386,39 +399,41 @@ key.interestOps(hsStatus); // null warning suppressed } int keyCount = selector.select(timeout); - if (keyCount == 0 && ((System.currentTimeMillis()-now) >= timeout)) { + if (keyCount == 0 && ((System.currentTimeMillis() - now) >= timeout)) { throw new SocketTimeoutException(sm.getString("channel.nio.ssl.timeoutDuringHandshake")); } isReadable = key.isReadable(); isWritable = key.isWritable(); } } - } catch (IOException x) { + } catch (IOException ioe) { closeSilently(); - throw x; - } catch (Exception cx) { + throw ioe; + } catch (Exception e) { closeSilently(); - throw new IOException(cx); + throw new IOException(e); } finally { if (key != null) { try { key.cancel(); } catch (Exception ignore) { + // Ignore } } if (selector != null) { try { selector.close(); } catch (Exception ignore) { + // Ignore } } } } - /** * Executes all the tasks needed on the same thread. + * * @return the status */ protected SSLEngineResult.HandshakeStatus tasks() { @@ -431,22 +446,25 @@ /** * Performs the WRAP function + * * @param doWrite boolean + * * @return the result + * * @throws IOException An IO error occurred */ protected SSLEngineResult handshakeWrap(boolean doWrite) throws IOException { - //this should never be called with a network buffer that contains data - //so we can clear it here. + // this should never be called with a network buffer that contains data + // so we can clear it here. netOutBuffer.clear(); - //perform the wrap + // perform the wrap getBufHandler().configureWriteBufferForRead(); SSLEngineResult result = sslEngine.wrap(getBufHandler().getWriteBuffer(), netOutBuffer); - //prepare the results to be written + // prepare the results to be written netOutBuffer.flip(); - //set the status + // set the status handshakeStatus = result.getHandshakeStatus(); - //optimization, if we do have a writable channel, write it now + // optimization, if we do have a writable channel, write it now if (doWrite) { flush(netOutBuffer); } @@ -455,14 +473,17 @@ /** * Perform handshake unwrap + * * @param doread boolean + * * @return the result + * * @throws IOException An IO error occurred */ protected SSLEngineResult handshakeUnwrap(boolean doread) throws IOException { - if (doread) { - //if we have data to read, read it + if (doread) { + // if we have data to read, read it int read = sc.read(netInBuffer); if (read == -1) { throw new IOException(sm.getString("channel.nio.ssl.eofDuringHandshake")); @@ -470,30 +491,29 @@ } SSLEngineResult result; boolean cont; - //loop while we can perform pure SSLEngine data + // loop while we can perform pure SSLEngine data do { - //prepare the buffer with the incoming data + // prepare the buffer with the incoming data netInBuffer.flip(); - //call unwrap + // call unwrap getBufHandler().configureReadBufferForWrite(); result = sslEngine.unwrap(netInBuffer, getBufHandler().getReadBuffer()); /* * ByteBuffer.compact() is an optional method but netInBuffer is created from either ByteBuffer.allocate() - * or ByteBuffer.allocateDirect() and the ByteBuffers returned by those methods do implement compact(). - * The ByteBuffer must be in 'read from' mode when compact() is called and will be in 'write to' mode + * or ByteBuffer.allocateDirect() and the ByteBuffers returned by those methods do implement compact(). The + * ByteBuffer must be in 'read from' mode when compact() is called and will be in 'write to' mode * afterwards. */ netInBuffer.compact(); - //read in the status + // read in the status handshakeStatus = result.getHandshakeStatus(); if (result.getStatus() == SSLEngineResult.Status.OK && - result.getHandshakeStatus() == HandshakeStatus.NEED_TASK) { - //execute tasks if we need to + result.getHandshakeStatus() == HandshakeStatus.NEED_TASK) { + // execute tasks if we need to handshakeStatus = tasks(); } - //perform another unwrap? - cont = result.getStatus() == SSLEngineResult.Status.OK && - handshakeStatus == HandshakeStatus.NEED_UNWRAP; + // perform another unwrap? + cont = result.getStatus() == SSLEngineResult.Status.OK && handshakeStatus == HandshakeStatus.NEED_UNWRAP; } while (cont); return result; } @@ -507,16 +527,19 @@ } /** - * Sends an SSL close message, will not physically close the connection here. - *
      To close the connection, you could do something like - *
      
      +     * Sends an SSL close message, will not physically close the connection here. 
      + * To close the connection, you could do something like + * + *
      +     * 
            *   close();
            *   while (isOpen() && !myTimeoutFunction()) Thread.sleep(25);
            *   if ( isOpen() ) close(true); //forces a close if you timed out
      -     * 
      + *
      + *
      + * * @throws IOException if an I/O error occurs - * @throws IOException if there is data on the outgoing network buffer, and - * we are unable to flush it + * @throws IOException if there is data on the outgoing network buffer, and we are unable to flush it */ @Override public void close() throws IOException { @@ -534,20 +557,20 @@ if (!flush(netOutBuffer)) { throw new IOException(sm.getString("channel.nio.ssl.remainingDataDuringClose")); } - //prep the buffer for the close message + // prep the buffer for the close message netOutBuffer.clear(); - //perform the close, since we called sslEngine.closeOutbound + // perform the close, since we called sslEngine.closeOutbound SSLEngineResult handshake = sslEngine.wrap(getEmptyBuf(), netOutBuffer); - //we should be in a close state + // we should be in a close state if (handshake.getStatus() != SSLEngineResult.Status.CLOSED) { throw new IOException(sm.getString("channel.nio.ssl.invalidCloseState")); } - //prepare the buffer for writing + // prepare the buffer for writing netOutBuffer.flip(); - //if there is data to be written + // if there is data to be written flush(netOutBuffer); - //is the channel closed? + // is the channel closed? closed = (!netOutBuffer.hasRemaining() && (handshake.getHandshakeStatus() != HandshakeStatus.NEED_WRAP)); } @@ -571,7 +594,9 @@ } catch (IOException ioe) { // This is expected - swallowing the exception is the reason this // method exists. Log at debug in case someone is interested. - log.debug(sm.getString("channel.nio.ssl.closeSilentError"), ioe); + if (log.isDebugEnabled()) { + log.debug(sm.getString("channel.nio.ssl.closeSilentError"), ioe); + } } } @@ -580,45 +605,46 @@ * Reads a sequence of bytes from this channel into the given buffer. * * @param dst The buffer into which bytes are to be transferred - * @return The number of bytes read, possibly zero, or -1 if - * the channel has reached end-of-stream - * @throws IOException If some other I/O error occurs + * + * @return The number of bytes read, possibly zero, or -1 if the channel has reached end-of-stream + * + * @throws IOException If some other I/O error occurs * @throws IllegalStateException if the handshake was not completed */ @Override public int read(ByteBuffer dst) throws IOException { - //are we in the middle of closing or closed? + // are we in the middle of closing or closed? if (closing || closed) { return -1; } - //did we finish our handshake? + // did we finish our handshake? if (!handshakeComplete) { throw new IllegalStateException(sm.getString("channel.nio.ssl.incompleteHandshake")); } - //read from the network + // read from the network int netread = sc.read(netInBuffer); - //did we reach EOF? if so send EOF up one layer. + // did we reach EOF? if so send EOF up one layer. if (netread == -1) { return -1; } - //the data read + // the data read int read = 0; - //the SSL engine result + // the SSL engine result SSLEngineResult unwrap; do { - //prepare the buffer + // prepare the buffer netInBuffer.flip(); - //unwrap the data + // unwrap the data unwrap = sslEngine.unwrap(netInBuffer, dst); - //compact the buffer + // compact the buffer netInBuffer.compact(); if (unwrap.getStatus() == Status.OK || unwrap.getStatus() == Status.BUFFER_UNDERFLOW) { - //we did receive some data, add it to our total + // we did receive some data, add it to our total read += unwrap.bytesProduced(); - //perform any tasks if needed + // perform any tasks if needed if (unwrap.getHandshakeStatus() == HandshakeStatus.NEED_TASK) { tasks(); } else if (unwrap.getHandshakeStatus() == HandshakeStatus.NEED_WRAP) { @@ -630,7 +656,7 @@ needHandshakeWrap = true; } } - //if we need more network data, then bail out for now. + // if we need more network data, then bail out for now. if (unwrap.getStatus() == Status.BUFFER_UNDERFLOW) { break; } @@ -653,8 +679,7 @@ } else { // Can't expand the buffer as there is no way to signal // to the caller that the buffer has been replaced. - throw new IOException( - sm.getString("channel.nio.ssl.unwrapFailResize", unwrap.getStatus())); + throw new IOException(sm.getString("channel.nio.ssl.unwrapFailResize", unwrap.getStatus())); } } } else if (unwrap.getStatus() == Status.CLOSED && netInBuffer.position() == 0 && read > 0) { @@ -669,53 +694,52 @@ // Something else went wrong throw new IOException(sm.getString("channel.nio.ssl.unwrapFail", unwrap.getStatus())); } - } while (netInBuffer.position() != 0); //continue unwrapping as long as the input buffer has stuff + } while (netInBuffer.position() != 0); // continue unwrapping as long as the input buffer has stuff return read; } @Override - public long read(ByteBuffer[] dsts, int offset, int length) - throws IOException { - //are we in the middle of closing or closed? + public long read(ByteBuffer[] dsts, int offset, int length) throws IOException { + // are we in the middle of closing or closed? if (closing || closed) { return -1; } - //did we finish our handshake? + // did we finish our handshake? if (!handshakeComplete) { throw new IllegalStateException(sm.getString("channel.nio.ssl.incompleteHandshake")); } - //read from the network + // read from the network int netread = sc.read(netInBuffer); - //did we reach EOF? if so send EOF up one layer. + // did we reach EOF? if so send EOF up one layer. if (netread == -1) { return -1; } - //the data read + // the data read int read = 0; - //the SSL engine result + // the SSL engine result SSLEngineResult unwrap; OverflowState overflowState = OverflowState.NONE; do { if (overflowState == OverflowState.PROCESSING) { overflowState = OverflowState.DONE; } - //prepare the buffer + // prepare the buffer netInBuffer.flip(); - //unwrap the data + // unwrap the data unwrap = sslEngine.unwrap(netInBuffer, dsts, offset, length); - //compact the buffer + // compact the buffer netInBuffer.compact(); if (unwrap.getStatus() == Status.OK || unwrap.getStatus() == Status.BUFFER_UNDERFLOW) { - //we did receive some data, add it to our total + // we did receive some data, add it to our total read += unwrap.bytesProduced(); if (overflowState == OverflowState.DONE) { // Remove the data read into the overflow buffer read -= getBufHandler().getReadBuffer().position(); } - //perform any tasks if needed + // perform any tasks if needed if (unwrap.getHandshakeStatus() == HandshakeStatus.NEED_TASK) { tasks(); } else if (unwrap.getHandshakeStatus() == HandshakeStatus.NEED_WRAP) { @@ -727,7 +751,7 @@ needHandshakeWrap = true; } } - //if we need more network data, then bail out for now. + // if we need more network data, then bail out for now. if (unwrap.getStatus() == Status.BUFFER_UNDERFLOW) { break; } @@ -751,7 +775,8 @@ } dsts[offset + i] = getBufHandler().getReadBuffer(); found = true; - } else if (getAppReadBufHandler() != null && dsts[offset + i] == getAppReadBufHandler().getByteBuffer()) { + } else if (getAppReadBufHandler() != null && + dsts[offset + i] == getAppReadBufHandler().getByteBuffer()) { getAppReadBufHandler().expand(sslEngine.getSession().getApplicationBufferSize()); if (dsts[offset + i] == getAppReadBufHandler().getByteBuffer()) { resized = false; @@ -795,7 +820,9 @@ * Writes a sequence of bytes to this channel from the given buffer. * * @param src The buffer from which bytes are to be retrieved + * * @return The number of bytes written, possibly zero + * * @throws IOException If some other I/O error occurs */ @Override @@ -845,8 +872,7 @@ } @Override - public long write(ByteBuffer[] srcs, int offset, int length) - throws IOException { + public long write(ByteBuffer[] srcs, int offset, int length) throws IOException { checkInterruptStatus(); // Are we closing or closed? if (closing || closed) { diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/net/SendfileDataBase.java tomcat10-10.1.52/java/org/apache/tomcat/util/net/SendfileDataBase.java --- tomcat10-10.1.40/java/org/apache/tomcat/util/net/SendfileDataBase.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/net/SendfileDataBase.java 2026-01-23 19:33:36.000000000 +0000 @@ -19,30 +19,26 @@ public abstract class SendfileDataBase { /** - * Is the current request being processed on a keep-alive connection? This - * determines if the socket is closed once the send file completes or if - * processing continues with the next request on the connection or waiting - * for that next request to arrive. + * Is the current request being processed on a keep-alive connection? This determines if the socket is closed once + * the send file completes or if processing continues with the next request on the connection or waiting for that + * next request to arrive. */ public SendfileKeepAliveState keepAliveState = SendfileKeepAliveState.NONE; /** - * The full path to the file that contains the data to be written to the - * socket. + * The full path to the file that contains the data to be written to the socket. */ public final String fileName; /** - * The position of the next byte in the file to be written to the socket. - * This is initialised to the start point and then updated as the file is - * written. + * The position of the next byte in the file to be written to the socket. This is initialised to the start point and + * then updated as the file is written. */ public long pos; /** - * The number of bytes remaining to be written from the file (from the - * current {@link #pos}). This is initialised to the end point - the start - * point and then updated as the file is written. + * The number of bytes remaining to be written from the file (from the current {@link #pos}). This is initialised to + * the end point - the start point and then updated as the file is written. */ public long length; diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/net/SendfileKeepAliveState.java tomcat10-10.1.52/java/org/apache/tomcat/util/net/SendfileKeepAliveState.java --- tomcat10-10.1.40/java/org/apache/tomcat/util/net/SendfileKeepAliveState.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/net/SendfileKeepAliveState.java 2026-01-23 19:33:36.000000000 +0000 @@ -19,21 +19,19 @@ public enum SendfileKeepAliveState { /** - * Keep-alive is not in use. The socket can be closed when the response has - * been written. + * Keep-alive is not in use. The socket can be closed when the response has been written. */ NONE, /** - * Keep-alive is in use and there is pipelined data in the input buffer to - * be read as soon as the current response has been written. + * Keep-alive is in use and there is pipelined data in the input buffer to be read as soon as the current response + * has been written. */ PIPELINED, /** - * Keep-alive is in use. The socket should be added to the poller (or - * equivalent) to await more data as soon as the current response has been - * written. + * Keep-alive is in use. The socket should be added to the poller (or equivalent) to await more data as soon as the + * current response has been written. */ OPEN } diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/net/SendfileState.java tomcat10-10.1.52/java/org/apache/tomcat/util/net/SendfileState.java --- tomcat10-10.1.40/java/org/apache/tomcat/util/net/SendfileState.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/net/SendfileState.java 2026-01-23 19:33:36.000000000 +0000 @@ -19,8 +19,7 @@ public enum SendfileState { /** - * The sending of the file has started but has not completed. Sendfile is - * still using the socket. + * The sending of the file has started but has not completed. Sendfile is still using the socket. */ PENDING, @@ -30,8 +29,7 @@ DONE, /** - * Something went wrong. The file may or may not have been sent. The socket - * is in an unknown state. + * Something went wrong. The file may or may not have been sent. The socket is in an unknown state. */ ERROR } diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/net/SocketBufferHandler.java tomcat10-10.1.52/java/org/apache/tomcat/util/net/SocketBufferHandler.java --- tomcat10-10.1.40/java/org/apache/tomcat/util/net/SocketBufferHandler.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/net/SocketBufferHandler.java 2026-01-23 19:33:36.000000000 +0000 @@ -27,13 +27,12 @@ @Override public void expand(int newSize) { } + /* - * Http2AsyncParser$FrameCompletionHandler will return incomplete - * frame(s) to the buffer. If the previous frame (or concurrent write to - * a stream) triggered a connection close this call would fail with a - * BufferOverflowException as data can't be returned to a buffer of zero - * length. Override the method and make it a NO-OP to avoid triggering - * the exception. + * Http2AsyncParser$FrameCompletionHandler will return incomplete frame(s) to the buffer. If the previous frame + * (or concurrent write to a stream) triggered a connection close this call would fail with a + * BufferOverflowException as data can't be returned to a buffer of zero length. Override the method and make it + * a NO-OP to avoid triggering the exception. */ @Override public void unReadReadBuffer(ByteBuffer returnedData) { @@ -48,8 +47,7 @@ private final boolean direct; - public SocketBufferHandler(int readBufferSize, int writeBufferSize, - boolean direct) { + public SocketBufferHandler(int readBufferSize, int writeBufferSize, boolean direct) { this.direct = direct; if (direct) { readBuffer = ByteBuffer.allocateDirect(readBufferSize); diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/net/SocketEvent.java tomcat10-10.1.52/java/org/apache/tomcat/util/net/SocketEvent.java --- tomcat10-10.1.40/java/org/apache/tomcat/util/net/SocketEvent.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/net/SocketEvent.java 2026-01-23 19:33:36.000000000 +0000 @@ -17,9 +17,8 @@ package org.apache.tomcat.util.net; /** - * Defines events that occur per socket that require further processing by the - * container. Usually these events are triggered by the socket implementation, - * but they may be triggered by the container. + * Defines events that occur per socket that require further processing by the container. Usually these events are + * triggered by the socket implementation, but they may be triggered by the container. */ public enum SocketEvent { @@ -34,14 +33,13 @@ OPEN_WRITE, /** - * The associated Connector/Endpoint is stopping and the connection/socket - * needs to be closed cleanly. + * The associated Connector/Endpoint is stopping and the connection/socket needs to be closed cleanly. */ STOP, /** - * A timeout has occurred and the connection needs to be closed cleanly. - * Currently, this is only used by the Servlet 3.0 async processing. + * A timeout has occurred and the connection needs to be closed cleanly. Currently, this is only used by the Servlet + * 3.0 async processing. */ TIMEOUT, @@ -51,20 +49,18 @@ DISCONNECT, /** - * An error has occurred on a non-container thread and processing needs to - * return to the container for any necessary clean-up. Examples of where - * this is used include: + * An error has occurred on a non-container thread and processing needs to return to the container for any necessary + * clean-up. Examples of where this is used include: *
        *
      • by NIO2 to signal the failure of a completion handler
      • - *
      • by the container to signal an I/O error on a non-container thread - * during Servlet 3.0 asynchronous processing.
      • + *
      • by the container to signal an I/O error on a non-container thread during Servlet 3.0 asynchronous + * processing.
      • *
      */ ERROR, /** - * A client attempted to establish a connection but failed. Examples of - * where this is used include: + * A client attempted to establish a connection but failed. Examples of where this is used include: *
        *
      • TLS handshake failures
      • *
      diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/net/SocketProperties.java tomcat10-10.1.52/java/org/apache/tomcat/util/net/SocketProperties.java --- tomcat10-10.1.40/java/org/apache/tomcat/util/net/SocketProperties.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/net/SocketProperties.java 2026-01-23 19:33:36.000000000 +0000 @@ -31,9 +31,8 @@ import org.apache.tomcat.util.res.StringManager; /** - * Properties that can be set in the <Connector> element - * in server.xml. All properties are prefixed with "socket." - * and are currently only working for the Nio connector + * Properties that can be set in the <Connector> element in server.xml. All properties are prefixed with + * "socket." and are currently only working for the Nio connector */ public class SocketProperties { @@ -41,75 +40,71 @@ private static final StringManager sm = StringManager.getManager(SocketProperties.class); /** - * Enable/disable socket processor cache, this bounded cache stores - * SocketProcessor objects to reduce GC - * Default is 0 - * -1 is unlimited + * Enable/disable socket processor cache, this bounded cache stores SocketProcessor objects to reduce GC. + *

      + * Default is 0
      + * -1 is unlimited
      * 0 is disabled */ protected int processorCache = 0; /** - * Enable/disable poller event cache, this bounded cache stores - * PollerEvent objects to reduce GC for the poller - * Default is 0 - * -1 is unlimited - * 0 is disabled + * Enable/disable poller event cache, this bounded cache stores PollerEvent objects to reduce GC for the poller + *

      + * Default is 0
      + * -1 is unlimited
      + * 0 is disabled
      * >0 the max number of objects to keep in cache. */ protected int eventCache = 0; /** - * Enable/disable direct buffers for the network buffers - * Default value is disabled + * Enable/disable direct buffers for the network buffers. Default value is disabled. */ protected boolean directBuffer = false; /** - * Enable/disable direct buffers for the network buffers for SSL - * Default value is disabled + * Enable/disable direct buffers for the network buffers for SSL. Default value is disabled. */ protected boolean directSslBuffer = false; /** - * Socket receive buffer size in bytes (SO_RCVBUF). - * JVM default used if not set. + * Socket receive buffer size in bytes (SO_RCVBUF). JVM default used if not set. */ protected Integer rxBufSize = null; /** - * Socket send buffer size in bytes (SO_SNDBUF). - * JVM default used if not set. + * Socket send buffer size in bytes (SO_SNDBUF). JVM default used if not set. */ protected Integer txBufSize = null; /** - * The application read buffer size in bytes. - * Default value is 8192 + * The application read buffer size in bytes. Default value is 8192. */ protected int appReadBufSize = 8192; /** - * The application write buffer size in bytes - * Default value is 8192 + * The application write buffer size in bytes. Default value is 8192. */ protected int appWriteBufSize = 8192; /** - * NioChannel pool size for the endpoint, - * this value is how many channels - * -1 means unlimited cached, 0 means no cache, - * -2 means bufferPoolSize will be used + * NioChannel pool size for the endpoint, this value is how many channels. + *

      + * 0 means no cache
      + * -1 means unlimited cached
      + * -2 means bufferPoolSize will be used
      * Default value is -2 */ protected int bufferPool = -2; /** - * Buffer pool size in bytes to be cached - * -1 means unlimited, 0 means no cache - * Default value is based on the max memory reported by the JVM, - * if less than 1GB, then 0, else the value divided by 32. This value - * will then be used to compute bufferPool if its value is -2 + * Buffer pool size in bytes to be cached. + *

      + * -1 means unlimited
      + * 0 means no cache
      + * Default value is based on the max memory reported by the JVM, if less than 1GB, then 0, else the value divided by + * 32. This value will then be used to compute bufferPool if its value is -2 */ protected int bufferPoolSize = -2; @@ -134,14 +129,14 @@ protected Boolean soReuseAddress = null; /** - * SO_LINGER option, paired with the soLingerTime value. - * JVM defaults used unless both attributes are set. + * SO_LINGER option, paired with the soLingerTime value. JVM defaults used unless both attributes are + * set. */ protected Boolean soLingerOn = null; /** - * SO_LINGER option, paired with the soLingerOn value. - * JVM defaults used unless both attributes are set. + * SO_LINGER option, paired with the soLingerOn value. JVM defaults used unless both attributes are + * set. */ protected Integer soLingerTime = null; @@ -151,32 +146,28 @@ protected Integer soTimeout = Integer.valueOf(20000); /** - * Performance preferences according to - *
      setPerformancePreferences - * All three performance attributes must be set or the JVM defaults will be - * used. + * Performance preferences according to setPerformancePreferences + * All three performance attributes must be set or the JVM defaults will be used. */ protected Integer performanceConnectionTime = null; /** - * Performance preferences according to - * setPerformancePreferences - * All three performance attributes must be set or the JVM defaults will be - * used. + * Performance preferences according to setPerformancePreferences + * All three performance attributes must be set or the JVM defaults will be used. */ protected Integer performanceLatency = null; /** - * Performance preferences according to - * setPerformancePreferences - * All three performance attributes must be set or the JVM defaults will be - * used. + * Performance preferences according to setPerformancePreferences + * All three performance attributes must be set or the JVM defaults will be used. */ protected Integer performanceBandwidth = null; /** - * The minimum frequency of the timeout interval to avoid excess load from - * the poller during high traffic + * The minimum frequency of the timeout interval to avoid excess load from the poller during high traffic */ protected long timeoutInterval = 1000; @@ -188,32 +179,28 @@ private ObjectName oname = null; - public void setProperties(Socket socket) throws SocketException{ + public void setProperties(Socket socket) throws SocketException { if (rxBufSize != null) { socket.setReceiveBufferSize(rxBufSize.intValue()); } if (txBufSize != null) { socket.setSendBufferSize(txBufSize.intValue()); } - if (ooBInline !=null) { + if (ooBInline != null) { socket.setOOBInline(ooBInline.booleanValue()); } if (soKeepAlive != null) { socket.setKeepAlive(soKeepAlive.booleanValue()); } - if (performanceConnectionTime != null && performanceLatency != null && - performanceBandwidth != null) { - socket.setPerformancePreferences( - performanceConnectionTime.intValue(), - performanceLatency.intValue(), + if (performanceConnectionTime != null && performanceLatency != null && performanceBandwidth != null) { + socket.setPerformancePreferences(performanceConnectionTime.intValue(), performanceLatency.intValue(), performanceBandwidth.intValue()); } if (soReuseAddress != null) { socket.setReuseAddress(soReuseAddress.booleanValue()); } if (soLingerOn != null && soLingerTime != null) { - socket.setSoLinger(soLingerOn.booleanValue(), - soLingerTime.intValue()); + socket.setSoLinger(soLingerOn.booleanValue(), soLingerTime.intValue()); } if (soTimeout != null && soTimeout.intValue() >= 0) { socket.setSoTimeout(soTimeout.intValue()); @@ -227,15 +214,12 @@ } } - public void setProperties(ServerSocket socket) throws SocketException{ + public void setProperties(ServerSocket socket) throws SocketException { if (rxBufSize != null) { socket.setReceiveBufferSize(rxBufSize.intValue()); } - if (performanceConnectionTime != null && performanceLatency != null && - performanceBandwidth != null) { - socket.setPerformancePreferences( - performanceConnectionTime.intValue(), - performanceLatency.intValue(), + if (performanceConnectionTime != null && performanceLatency != null && performanceBandwidth != null) { + socket.setPerformancePreferences(performanceConnectionTime.intValue(), performanceLatency.intValue(), performanceBandwidth.intValue()); } if (soReuseAddress != null) { @@ -365,8 +349,7 @@ } public void setPerformanceConnectionTime(int performanceConnectionTime) { - this.performanceConnectionTime = - Integer.valueOf(performanceConnectionTime); + this.performanceConnectionTime = Integer.valueOf(performanceConnectionTime); } public void setTxBufSize(int txBufSize) { @@ -467,8 +450,10 @@ /** * Get the actual buffer pool size to use. - * @param bufferOverhead When TLS is enabled, additional network buffers - * are needed and will be added to the application buffer size + * + * @param bufferOverhead When TLS is enabled, additional network buffers are needed and will be added to the + * application buffer size + * * @return the actual buffer pool size that will be used */ public int getActualBufferPool(int bufferOverhead) { diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/net/SocketWrapperBase.java tomcat10-10.1.52/java/org/apache/tomcat/util/net/SocketWrapperBase.java --- tomcat10-10.1.40/java/org/apache/tomcat/util/net/SocketWrapperBase.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/net/SocketWrapperBase.java 2026-01-23 19:33:36.000000000 +0000 @@ -48,14 +48,12 @@ protected static final StringManager sm = StringManager.getManager(SocketWrapperBase.class); /* - * At 100,000 connections a second there are enough IDs here for ~3,000,000 - * years before it overflows (and then we have another 3,000,000 years - * before it gets back to zero). - * - * Local testing shows that 5 threads can obtain 60,000,000+ IDs a second - * from a single AtomicLong. That is about 17ns per request. It does - * not appear that the introduction of this counter will cause a bottleneck - * for connection processing. + * At 100,000 connections a second there are enough IDs here for ~3,000,000 years before it overflows (and then we + * have another 3,000,000 years before it gets back to zero). + * + * Local testing shows that 5 threads can obtain 60,000,000+ IDs a second from a single AtomicLong. That is about + * 17ns per request. It does not appear that the introduction of this counter will cause a bottleneck for connection + * processing. */ private static final AtomicLong connectionIdGenerator = new AtomicLong(0); @@ -88,10 +86,11 @@ protected int remotePort = -1; protected volatile ServletConnection servletConnection = null; + protected String sniHostName = null; + /** - * Used to record the first IOException that occurs during non-blocking - * read/writes that can't be usefully propagated up the stack since there is - * no user code or appropriate container code in the stack to handle it. + * Used to record the first IOException that occurs during non-blocking read/writes that can't be usefully + * propagated up the stack since there is no user code or appropriate container code in the stack to handle it. */ private volatile IOException error = null; @@ -106,13 +105,10 @@ protected int bufferedWriteSize = 64 * 1024; // 64k default write buffer /** - * Additional buffer used for non-blocking writes. Non-blocking writes need - * to return immediately even if the data cannot be written immediately but - * the socket buffer may not be big enough to hold all of the unwritten - * data. This structure provides an additional buffer to hold the data until - * it can be written. - * Not that while the Servlet API only allows one non-blocking write at a - * time, due to buffering and the possible need to write HTTP headers, this + * Additional buffer used for non-blocking writes. Non-blocking writes need to return immediately even if the data + * cannot be written immediately but the socket buffer may not be big enough to hold all of the unwritten data. This + * structure provides an additional buffer to hold the data until it can be written. Not that while the Servlet API + * only allows one non-blocking write at a time, due to buffering and the possible need to write HTTP headers, this * layer may see multiple writes. */ protected final WriteBuffer nonBlockingWriteBuffer = new WriteBuffer(bufferedWriteSize); @@ -126,9 +122,8 @@ protected volatile OperationState writeOperation = null; /** - * The org.apache.coyote.Processor instance currently associated with the - * wrapper. Only populated when required to maintain wrapper<->Processor - * mapping between calls to + * The org.apache.coyote.Processor instance currently associated with the wrapper. Only populated when required to + * maintain wrapper<->Processor mapping between calls to * {@link AbstractEndpoint.Handler#process(SocketWrapperBase, SocketEvent)}. */ private final AtomicReference currentProcessor = new AtomicReference<>(); @@ -189,7 +184,10 @@ executor.execute(runnable); } - public IOException getError() { return error; } + public IOException getError() { + return error; + } + public void setError(IOException error) { // Not perfectly thread-safe but good enough. Just needs to ensure that // once this.error is non-null, it can never be null. @@ -198,23 +196,39 @@ } this.error = error; } + public void checkError() throws IOException { if (error != null) { throw error; } } - public String getNegotiatedProtocol() { return negotiatedProtocol; } + public String getNegotiatedProtocol() { + return negotiatedProtocol; + } + public void setNegotiatedProtocol(String negotiatedProtocol) { this.negotiatedProtocol = negotiatedProtocol; } /** - * Set the timeout for reading. Values of zero or less will be changed to - * -1. + * @return the sniHostName + */ + public String getSniHostName() { + return this.sniHostName; + } + + /** + * @param sniHostName the SNI host name to set + */ + public void setSniHostName(String sniHostName) { + this.sniHostName = sniHostName; + } + + /** + * Set the timeout for reading. Values of zero or less will be changed to -1. * - * @param readTimeout The timeout in milliseconds. A value of -1 indicates - * an infinite timeout. + * @param readTimeout The timeout in milliseconds. A value of -1 indicates an infinite timeout. */ public void setReadTimeout(long readTimeout) { if (readTimeout > 0) { @@ -229,11 +243,9 @@ } /** - * Set the timeout for writing. Values of zero or less will be changed to - * -1. + * Set the timeout for writing. Values of zero or less will be changed to -1. * - * @param writeTimeout The timeout in milliseconds. A value of zero or less - * indicates an infinite timeout. + * @param writeTimeout The timeout in milliseconds. A value of zero or less indicates an infinite timeout. */ public void setWriteTimeout(long writeTimeout) { if (writeTimeout > 0) { @@ -248,8 +260,13 @@ } - public void setKeepAliveLeft(int keepAliveLeft) { this.keepAliveLeft = keepAliveLeft; } - public int decrementKeepAlive() { return (--keepAliveLeft); } + public void setKeepAliveLeft(int keepAliveLeft) { + this.keepAliveLeft = keepAliveLeft; + } + + public int decrementKeepAlive() { + return (--keepAliveLeft); + } public String getRemoteHost() { if (remoteHost == null) { @@ -257,6 +274,7 @@ } return remoteHost; } + protected abstract void populateRemoteHost(); public String getRemoteAddr() { @@ -265,6 +283,7 @@ } return remoteAddr; } + protected abstract void populateRemoteAddr(); public int getRemotePort() { @@ -273,6 +292,7 @@ } return remotePort; } + protected abstract void populateRemotePort(); public String getLocalName() { @@ -281,6 +301,7 @@ } return localName; } + protected abstract void populateLocalName(); public String getLocalAddr() { @@ -289,6 +310,7 @@ } return localAddr; } + protected abstract void populateLocalAddr(); public int getLocalPort() { @@ -297,9 +319,12 @@ } return localPort; } + protected abstract void populateLocalPort(); - public SocketBufferHandler getSocketBufferHandler() { return socketBufferHandler; } + public SocketBufferHandler getSocketBufferHandler() { + return socketBufferHandler; + } public boolean hasDataToRead() { // Return true because it is always safe to make a read attempt @@ -311,18 +336,14 @@ } /** - * Checks to see if there are any writes pending and if there are calls - * {@link #registerWriteInterest()} to trigger a callback once the pending - * writes have completed. + * Checks to see if there are any writes pending and if there are calls {@link #registerWriteInterest()} to trigger + * a callback once the pending writes have completed. *

      - * Note: Once this method has returned false it MUST NOT - * be called again until the pending write has completed and the - * callback has been fired. - * TODO: Modify {@link #registerWriteInterest()} so the above - * restriction is enforced there rather than relying on the caller. + * Note: Once this method has returned false it MUST NOT be called again until the pending write + * has completed and the callback has been fired. TODO: Modify {@link #registerWriteInterest()} so the above + * restriction is enforced there rather than relying on the caller. * - * @return true if no writes are pending and data can be - * written otherwise false + * @return true if no writes are pending and data can be written otherwise false */ public boolean isReadyForWrite() { boolean result = canWrite(); @@ -342,8 +363,8 @@ /** - * Overridden for debug purposes. No guarantees are made about the format of - * this message which may vary significantly between point releases. + * Overridden for debug purposes. No guarantees are made about the format of this message which may vary + * significantly between point releases. *

      * {@inheritDoc} */ @@ -354,8 +375,11 @@ public abstract int read(boolean block, byte[] b, int off, int len) throws IOException; + public abstract int read(boolean block, ByteBuffer to) throws IOException; + public abstract boolean isReadyForRead() throws IOException; + public abstract void setAppReadBufHandler(ApplicationBufferHandler handler); protected int populateReadBuffer(byte[] b, int off, int len) { @@ -391,13 +415,11 @@ /** - * Return input that has been read to the input buffer for re-reading by the - * correct component. There are times when a component may read more data - * than it needs before it passes control to another component. One example - * of this is during HTTP upgrade. If an (arguably misbehaving client) sends - * data associated with the upgraded protocol before the HTTP upgrade - * completes, the HTTP handler may read it. This method provides a way for - * that data to be returned so it can be processed by the correct component. + * Return input that has been read to the input buffer for re-reading by the correct component. There are times when + * a component may read more data than it needs before it passes control to another component. One example of this + * is during HTTP upgrade. If an (arguably misbehaving client) sends data associated with the upgraded protocol + * before the HTTP upgrade completes, the HTTP handler may read it. This method provides a way for that data to be + * returned so it can be processed by the correct component. * * @param returnedInput The input to return to the input buffer. */ @@ -415,10 +437,10 @@ if (closed.compareAndSet(false, true)) { try { getEndpoint().getHandler().release(this); - } catch (Throwable e) { - ExceptionUtils.handleThrowable(e); + } catch (Throwable t) { + ExceptionUtils.handleThrowable(t); if (log.isDebugEnabled()) { - log.error(sm.getString("endpoint.debug.handlerRelease"), e); + log.error(sm.getString("endpoint.debug.handlerRelease"), t); } } finally { getEndpoint().countDownConnection(); @@ -428,8 +450,7 @@ } /** - * Perform the actual close. The closed atomic boolean guarantees this will - * be called only once per wrapper. + * Perform the actual close. The closed atomic boolean guarantees this will be called only once per wrapper. */ protected abstract void doClose(); @@ -442,25 +463,19 @@ /** - * Writes the provided data to the socket write buffer. If the socket write - * buffer fills during the write, the content of the socket write buffer is - * written to the network and this method starts to fill the socket write - * buffer again. Depending on the size of the data to write, there may be - * multiple writes to the network. + * Writes the provided data to the socket write buffer. If the socket write buffer fills during the write, the + * content of the socket write buffer is written to the network and this method starts to fill the socket write + * buffer again. Depending on the size of the data to write, there may be multiple writes to the network. *

      - * Non-blocking writes must return immediately and the byte array holding - * the data to be written must be immediately available for re-use. It may - * not be possible to write sufficient data to the network to allow this to - * happen. In this case data that cannot be written to the network and - * cannot be held by the socket buffer is stored in the non-blocking write - * buffer. + * Non-blocking writes must return immediately and the byte array holding the data to be written must be immediately + * available for re-use. It may not be possible to write sufficient data to the network to allow this to happen. In + * this case data that cannot be written to the network and cannot be held by the socket buffer is stored in the + * non-blocking write buffer. *

      - * Note: There is an implementation assumption that, before switching from - * non-blocking writes to blocking writes, any data remaining in the - * non-blocking write buffer will have been written to the network. + * Note: There is an implementation assumption that, before switching from non-blocking writes to blocking writes, + * any data remaining in the non-blocking write buffer will have been written to the network. * - * @param block true if a blocking write should be used, - * otherwise a non-blocking write will be used + * @param block true if a blocking write should be used, otherwise a non-blocking write will be used * @param buf The byte array containing the data to be written * @param off The offset within the byte array of the data to be written * @param len The length of the data to be written @@ -473,14 +488,11 @@ } /* - * While the implementations for blocking and non-blocking writes are - * very similar they have been split into separate methods: - * - To allow subclasses to override them individually. NIO2, for - * example, overrides the non-blocking write but not the blocking - * write. - * - To enable a marginally more efficient implemented for blocking - * writes which do not require the additional checks related to the - * use of the non-blocking write buffer + * While the implementations for blocking and non-blocking writes are very similar they have been split into + * separate methods: - To allow subclasses to override them individually. NIO2, for example, overrides the + * non-blocking write but not the blocking write. - To enable a marginally more efficient implemented for + * blocking writes which do not require the additional checks related to the use of the non-blocking write + * buffer */ if (block) { writeBlocking(buf, off, len); @@ -491,26 +503,20 @@ /** - * Writes the provided data to the socket write buffer. If the socket write - * buffer fills during the write, the content of the socket write buffer is - * written to the network and this method starts to fill the socket write - * buffer again. Depending on the size of the data to write, there may be - * multiple writes to the network. + * Writes the provided data to the socket write buffer. If the socket write buffer fills during the write, the + * content of the socket write buffer is written to the network and this method starts to fill the socket write + * buffer again. Depending on the size of the data to write, there may be multiple writes to the network. *

      - * Non-blocking writes must return immediately and the ByteBuffer holding - * the data to be written must be immediately available for re-use. It may - * not be possible to write sufficient data to the network to allow this to - * happen. In this case data that cannot be written to the network and - * cannot be held by the socket buffer is stored in the non-blocking write - * buffer. + * Non-blocking writes must return immediately and the ByteBuffer holding the data to be written must be immediately + * available for re-use. It may not be possible to write sufficient data to the network to allow this to happen. In + * this case data that cannot be written to the network and cannot be held by the socket buffer is stored in the + * non-blocking write buffer. *

      - * Note: There is an implementation assumption that, before switching from - * non-blocking writes to blocking writes, any data remaining in the - * non-blocking write buffer will have been written to the network. - * - * @param block true if a blocking write should be used, - * otherwise a non-blocking write will be used - * @param from The ByteBuffer containing the data to be written + * Note: There is an implementation assumption that, before switching from non-blocking writes to blocking writes, + * any data remaining in the non-blocking write buffer will have been written to the network. + * + * @param block true if a blocking write should be used, otherwise a non-blocking write will be used + * @param from The ByteBuffer containing the data to be written * * @throws IOException If an IO error occurs during the write */ @@ -520,14 +526,11 @@ } /* - * While the implementations for blocking and non-blocking writes are - * very similar they have been split into separate methods: - * - To allow subclasses to override them individually. NIO2, for - * example, overrides the non-blocking write but not the blocking - * write. - * - To enable a marginally more efficient implemented for blocking - * writes which do not require the additional checks related to the - * use of the non-blocking write buffer + * While the implementations for blocking and non-blocking writes are very similar they have been split into + * separate methods: - To allow subclasses to override them individually. NIO2, for example, overrides the + * non-blocking write but not the blocking write. - To enable a marginally more efficient implemented for + * blocking writes which do not require the additional checks related to the use of the non-blocking write + * buffer */ if (block) { writeBlocking(from); @@ -538,17 +541,15 @@ /** - * Writes the provided data to the socket write buffer. If the socket write - * buffer fills during the write, the content of the socket write buffer is - * written to the network using a blocking write. Once that blocking write - * is complete, this method starts to fill the socket write buffer again. - * Depending on the size of the data to write, there may be multiple writes - * to the network. On completion of this method there will always be space - * remaining in the socket write buffer. - * - * @param buf The byte array containing the data to be written - * @param off The offset within the byte array of the data to be written - * @param len The length of the data to be written + * Writes the provided data to the socket write buffer. If the socket write buffer fills during the write, the + * content of the socket write buffer is written to the network using a blocking write. Once that blocking write is + * complete, this method starts to fill the socket write buffer again. Depending on the size of the data to write, + * there may be multiple writes to the network. On completion of this method there will always be space remaining in + * the socket write buffer. + * + * @param buf The byte array containing the data to be written + * @param off The offset within the byte array of the data to be written + * @param len The length of the data to be written * * @throws IOException If an IO error occurs during the write */ @@ -569,13 +570,11 @@ /** - * Writes the provided data to the socket write buffer. If the socket write - * buffer fills during the write, the content of the socket write buffer is - * written to the network using a blocking write. Once that blocking write - * is complete, this method starts to fill the socket write buffer again. - * Depending on the size of the data to write, there may be multiple writes - * to the network. On completion of this method there will always be space - * remaining in the socket write buffer. + * Writes the provided data to the socket write buffer. If the socket write buffer fills during the write, the + * content of the socket write buffer is written to the network using a blocking write. Once that blocking write is + * complete, this method starts to fill the socket write buffer again. Depending on the size of the data to write, + * there may be multiple writes to the network. On completion of this method there will always be space remaining in + * the socket write buffer. * * @param from The ByteBuffer containing the data to be written * @@ -595,25 +594,21 @@ /** - * Transfers the data to the socket write buffer (writing that data to the - * socket if the buffer fills up using a non-blocking write) until either - * all the data has been transferred and space remains in the socket write - * buffer or a non-blocking write leaves data in the socket write buffer. - * After an incomplete write, any data remaining to be transferred to the - * socket write buffer will be copied to the socket write buffer. If the - * remaining data is too big for the socket write buffer, the socket write - * buffer will be filled and the additional data written to the non-blocking - * write buffer. - * - * @param buf The byte array containing the data to be written - * @param off The offset within the byte array of the data to be written - * @param len The length of the data to be written + * Transfers the data to the socket write buffer (writing that data to the socket if the buffer fills up using a + * non-blocking write) until either all the data has been transferred and space remains in the socket write buffer + * or a non-blocking write leaves data in the socket write buffer. After an incomplete write, any data remaining to + * be transferred to the socket write buffer will be copied to the socket write buffer. If the remaining data is too + * big for the socket write buffer, the socket write buffer will be filled and the additional data written to the + * non-blocking write buffer. + * + * @param buf The byte array containing the data to be written + * @param off The offset within the byte array of the data to be written + * @param len The length of the data to be written * * @throws IOException If an IO error occurs during the write */ protected void writeNonBlocking(byte[] buf, int off, int len) throws IOException { - if (len > 0 && nonBlockingWriteBuffer.isEmpty() - && socketBufferHandler.isWriteBufferWritable()) { + if (len > 0 && nonBlockingWriteBuffer.isEmpty() && socketBufferHandler.isWriteBufferWritable()) { socketBufferHandler.configureWriteBufferForWrite(); int thisTime = transfer(buf, off, len, socketBufferHandler.getWriteBuffer()); len -= thisTime; @@ -641,25 +636,20 @@ /** - * Transfers the data to the socket write buffer (writing that data to the - * socket if the buffer fills up using a non-blocking write) until either - * all the data has been transferred and space remains in the socket write - * buffer or a non-blocking write leaves data in the socket write buffer. - * After an incomplete write, any data remaining to be transferred to the - * socket write buffer will be copied to the socket write buffer. If the - * remaining data is too big for the socket write buffer, the socket write - * buffer will be filled and the additional data written to the non-blocking - * write buffer. + * Transfers the data to the socket write buffer (writing that data to the socket if the buffer fills up using a + * non-blocking write) until either all the data has been transferred and space remains in the socket write buffer + * or a non-blocking write leaves data in the socket write buffer. After an incomplete write, any data remaining to + * be transferred to the socket write buffer will be copied to the socket write buffer. If the remaining data is too + * big for the socket write buffer, the socket write buffer will be filled and the additional data written to the + * non-blocking write buffer. * * @param from The ByteBuffer containing the data to be written * * @throws IOException If an IO error occurs during the write */ - protected void writeNonBlocking(ByteBuffer from) - throws IOException { + protected void writeNonBlocking(ByteBuffer from) throws IOException { - if (from.hasRemaining() && nonBlockingWriteBuffer.isEmpty() - && socketBufferHandler.isWriteBufferWritable()) { + if (from.hasRemaining() && nonBlockingWriteBuffer.isEmpty() && socketBufferHandler.isWriteBufferWritable()) { writeNonBlockingInternal(from); } @@ -671,8 +661,7 @@ /** - * Separate method so it can be re-used by the socket write buffer to write - * data to the network + * Separate method so it can be re-used by the socket write buffer to write data to the network * * @param from The ByteBuffer containing the data to be written * @@ -696,12 +685,10 @@ /** * Writes as much data as possible from any that remains in the buffers. * - * @param block true if a blocking write should be used, - * otherwise a non-blocking write will be used + * @param block true if a blocking write should be used, otherwise a non-blocking write will be used * - * @return true if data remains to be flushed after this method - * completes, otherwise false. In blocking mode - * therefore, the return value should always be false + * @return true if data remains to be flushed after this method completes, otherwise + * false. In blocking mode therefore, the return value should always be false * * @throws IOException If an IO error occurs during the write */ @@ -719,8 +706,7 @@ /** - * Writes all remaining data from the buffers and blocks until the write is - * complete. + * Writes all remaining data from the buffers and blocks until the write is complete. * * @throws IOException If an IO error occurs during the write */ @@ -741,8 +727,8 @@ /** * Writes as much data as possible from any that remains in the buffers. * - * @return true if data remains to be flushed after this method - * completes, otherwise false. + * @return true if data remains to be flushed after this method completes, otherwise + * false. * * @throws IOException If an IO error occurs during the write */ @@ -750,14 +736,12 @@ /** - * Write the contents of the socketWriteBuffer to the socket. For blocking - * writes either then entire contents of the buffer will be written or an - * IOException will be thrown. Partial blocking writes will not occur. + * Write the contents of the socketWriteBuffer to the socket. For blocking writes either then entire contents of the + * buffer will be written or an IOException will be thrown. Partial blocking writes will not occur. * * @param block Should the write be blocking or not? * - * @throws IOException If an I/O error such as a timeout occurs during the - * write + * @throws IOException If an I/O error such as a timeout occurs during the write */ protected void doWrite(boolean block) throws IOException { socketBufferHandler.configureWriteBufferForRead(); @@ -766,15 +750,13 @@ /** - * Write the contents of the ByteBuffer to the socket. For blocking writes - * either then entire contents of the buffer will be written or an - * IOException will be thrown. Partial blocking writes will not occur. + * Write the contents of the ByteBuffer to the socket. For blocking writes either then entire contents of the buffer + * will be written or an IOException will be thrown. Partial blocking writes will not occur. * * @param block Should the write be blocking or not? - * @param from the ByteBuffer containing the data to be written + * @param from the ByteBuffer containing the data to be written * - * @throws IOException If an I/O error such as a timeout occurs during the - * write + * @throws IOException If an I/O error such as a timeout occurs during the write */ protected abstract void doWrite(boolean block, ByteBuffer from) throws IOException; @@ -791,10 +773,9 @@ public abstract SendfileDataBase createSendfileData(String filename, long pos, long length); /** - * Starts the sendfile process. It is expected that if the sendfile process - * does not complete during this call and does not report an error, that the - * caller will not add the socket to the poller (or equivalent). That - * is the responsibility of this method. + * Starts the sendfile process. It is expected that if the sendfile process does not complete during this call and + * does not report an error, that the caller will not add the socket to the poller (or equivalent). That is + * the responsibility of this method. * * @param sendfileData Data representing the file to send * @@ -803,16 +784,13 @@ public abstract SendfileState processSendfile(SendfileDataBase sendfileData); /** - * Require the client to perform CLIENT-CERT authentication if it hasn't - * already done so. + * Require the client to perform CLIENT-CERT authentication if it hasn't already done so. + * + * @param sslSupport The SSL/TLS support instance currently being used by the connection that may need updating + * after the client authentication * - * @param sslSupport The SSL/TLS support instance currently being used by - * the connection that may need updating after the client - * authentication - * - * @throws IOException If authentication is required then there will be I/O - * with the client and this exception will be thrown if - * that goes wrong + * @throws IOException If authentication is required then there will be I/O with the client and this exception will + * be thrown if that goes wrong */ public abstract void doClientAuth(SSLSupport sslSupport) throws IOException; @@ -829,18 +807,16 @@ public enum BlockingMode { /** - * The operation will not block. If there are pending operations, - * the operation will throw a pending exception. + * The operation will not block. If there are pending operations, the operation will throw a pending exception. */ CLASSIC, /** - * The operation will not block. If there are pending operations, - * the operation will return CompletionState.NOT_DONE. + * The operation will not block. If there are pending operations, the operation will return + * CompletionState.NOT_DONE. */ NON_BLOCK, /** - * The operation will block until pending operations are completed, but - * will not block after performing it. + * The operation will block until pending operations are completed, but will not block after performing it. */ SEMI_BLOCK, /** @@ -874,44 +850,36 @@ public enum CompletionHandlerCall { /** - * Operation should continue, the completion handler shouldn't be - * called. + * Operation should continue, the completion handler shouldn't be called. */ CONTINUE, /** - * The operation completed but the completion handler shouldn't be - * called. + * The operation completed but the completion handler shouldn't be called. */ NONE, /** - * The operation is complete, the completion handler should be - * called. + * The operation is complete, the completion handler should be called. */ DONE } public interface CompletionCheck { /** - * Determine what call, if any, should be made to the completion - * handler. + * Determine what call, if any, should be made to the completion handler. * - * @param state of the operation (done or done in-line since the - * IO call is done) - * @param buffers ByteBuffer[] that has been passed to the - * original IO call - * @param offset that has been passed to the original IO call - * @param length that has been passed to the original IO call + * @param state of the operation (done or done in-line since the IO call is done) + * @param buffers ByteBuffer[] that has been passed to the original IO call + * @param offset that has been passed to the original IO call + * @param length that has been passed to the original IO call * * @return The call, if any, to make to the completion handler */ - CompletionHandlerCall callHandler(CompletionState state, ByteBuffer[] buffers, - int offset, int length); + CompletionHandlerCall callHandler(CompletionState state, ByteBuffer[] buffers, int offset, int length); } /** - * This utility CompletionCheck will cause the write to fully write - * all remaining data. If the operation completes inline, the - * completion handler will not be called. + * This utility CompletionCheck will cause the write to fully write all remaining data. If the operation completes + * inline, the completion handler will not be called. */ public static final CompletionCheck COMPLETE_WRITE = (state, buffers, offset, length) -> { for (int i = 0; i < length; i++) { @@ -919,13 +887,12 @@ return CompletionHandlerCall.CONTINUE; } } - return (state == CompletionState.DONE) ? CompletionHandlerCall.DONE - : CompletionHandlerCall.NONE; + return (state == CompletionState.DONE) ? CompletionHandlerCall.DONE : CompletionHandlerCall.NONE; }; /** - * This utility CompletionCheck will cause the write to fully write - * all remaining data. The completion handler will then be called. + * This utility CompletionCheck will cause the write to fully write all remaining data. The completion handler will + * then be called. */ public static final CompletionCheck COMPLETE_WRITE_WITH_COMPLETION = (state, buffers, offset, length) -> { for (int i = 0; i < length; i++) { @@ -937,24 +904,21 @@ }; /** - * This utility CompletionCheck will cause the completion handler - * to be called once some data has been read. If the operation - * completes inline, the completion handler will not be called. + * This utility CompletionCheck will cause the completion handler to be called once some data has been read. If the + * operation completes inline, the completion handler will not be called. */ - public static final CompletionCheck READ_DATA = (state, buffers, offset, length) -> - (state == CompletionState.DONE) ? CompletionHandlerCall.DONE : CompletionHandlerCall.NONE; + public static final CompletionCheck READ_DATA = (state, buffers, offset, + length) -> (state == CompletionState.DONE) ? CompletionHandlerCall.DONE : CompletionHandlerCall.NONE; /** - * This utility CompletionCheck will cause the completion handler - * to be called once the given buffers are full. The completion - * handler will then be called. + * This utility CompletionCheck will cause the completion handler to be called once the given buffers are full. The + * completion handler will then be called. */ public static final CompletionCheck COMPLETE_READ_WITH_COMPLETION = COMPLETE_WRITE_WITH_COMPLETION; /** - * This utility CompletionCheck will cause the completion handler - * to be called once the given buffers are full. If the operation - * completes inline, the completion handler will not be called. + * This utility CompletionCheck will cause the completion handler to be called once the given buffers are full. If + * the operation completes inline, the completion handler will not be called. */ public static final CompletionCheck COMPLETE_READ = COMPLETE_WRITE; @@ -971,14 +935,15 @@ protected final TimeUnit unit; protected final BlockingMode block; protected final CompletionCheck check; - protected final CompletionHandler handler; + protected final CompletionHandler handler; protected final Semaphore semaphore; protected final VectoredIOCompletionHandler completion; protected final AtomicBoolean callHandler; - protected OperationState(boolean read, ByteBuffer[] buffers, int offset, int length, - BlockingMode block, long timeout, TimeUnit unit, A attachment, - CompletionCheck check, CompletionHandler handler, - Semaphore semaphore, VectoredIOCompletionHandler completion) { + + protected OperationState(boolean read, ByteBuffer[] buffers, int offset, int length, BlockingMode block, + long timeout, TimeUnit unit, A attachment, CompletionCheck check, + CompletionHandler handler, Semaphore semaphore, + VectoredIOCompletionHandler completion) { this.read = read; this.buffers = buffers; this.offset = offset; @@ -993,13 +958,14 @@ this.completion = completion; callHandler = (handler != null) ? new AtomicBoolean(true) : null; } + protected volatile long nBytes = 0; protected volatile CompletionState state = CompletionState.PENDING; protected boolean completionDone = true; /** - * @return true if the operation is still inline, false if the operation - * is running on a thread that is not the original caller + * @return true if the operation is still inline, false if the operation is running on a thread that is not the + * original caller */ protected abstract boolean isInline(); @@ -1012,15 +978,15 @@ /** * Process the operation using the connector executor. - * @return true if the operation was accepted, false if the executor - * rejected execution + * + * @return true if the operation was accepted, false if the executor rejected execution */ protected boolean process() { try { getEndpoint().getExecutor().execute(this); return true; } catch (RejectedExecutionException ree) { - log.warn(sm.getString("endpoint.executor.fail", SocketWrapperBase.this) , ree); + log.warn(sm.getString("endpoint.executor.fail", SocketWrapperBase.this), ree); } catch (Throwable t) { ExceptionUtils.handleThrowable(t); // This means we got an OOM or similar creating a thread, or that @@ -1046,10 +1012,10 @@ } /** - * Completion handler for vectored operations. This will check the completion of the operation, - * then either continue or call the user provided completion handler. + * Completion handler for vectored operations. This will check the completion of the operation, then either continue + * or call the user provided completion handler. */ - protected class VectoredIOCompletionHandler implements CompletionHandler> { + protected class VectoredIOCompletionHandler implements CompletionHandler> { @Override public void completed(Long nBytes, OperationState state) { if (nBytes.longValue() < 0) { @@ -1060,7 +1026,8 @@ boolean complete = true; boolean completion = true; if (state.check != null) { - CompletionHandlerCall call = state.check.callHandler(currentState, state.buffers, state.offset, state.length); + CompletionHandlerCall call = + state.check.callHandler(currentState, state.buffers, state.offset, state.length); if (call == CompletionHandlerCall.CONTINUE || (!state.read && state.hasOutboundRemaining())) { complete = false; } else if (call == CompletionHandlerCall.NONE) { @@ -1103,6 +1070,7 @@ } } } + @Override public void failed(Throwable exc, OperationState state) { IOException ioe = null; @@ -1173,8 +1141,9 @@ /** * Allows checking if an asynchronous read operation is currently pending. - * @return true if the endpoint supports asynchronous IO and - * a read operation is being processed asynchronously + * + * @return true if the endpoint supports asynchronous IO and a read operation is being processed + * asynchronously */ public boolean isReadPending() { return false; @@ -1182,30 +1151,30 @@ /** * Allows checking if an asynchronous write operation is currently pending. - * @return true if the endpoint supports asynchronous IO and - * a write operation is being processed asynchronously + * + * @return true if the endpoint supports asynchronous IO and a write operation is being processed + * asynchronously */ public boolean isWritePending() { return false; } /** - * Scatter read. The completion handler will be called once some - * data has been read or an error occurred. The default NIO2 - * behavior is used: the completion handler will be called as soon - * as some data has been read, even if the read has completed inline. - * - * @param timeout timeout duration for the read - * @param unit units for the timeout duration - * @param attachment an object to attach to the I/O operation that will be - * used when calling the completion handler - * @param handler to call when the IO is complete - * @param dsts buffers - * @param The attachment type + * Scatter read. The completion handler will be called once some data has been read or an error occurred. The + * default NIO2 behavior is used: the completion handler will be called as soon as some data has been read, even if + * the read has completed inline. + * + * @param timeout timeout duration for the read + * @param unit units for the timeout duration + * @param attachment an object to attach to the I/O operation that will be used when calling the completion handler + * @param handler to call when the IO is complete + * @param dsts buffers + * @param The attachment type + * * @return the completion state (done, done inline, or still pending) */ public final CompletionState read(long timeout, TimeUnit unit, A attachment, - CompletionHandler handler, ByteBuffer... dsts) { + CompletionHandler handler, ByteBuffer... dsts) { if (dsts == null) { throw new IllegalArgumentException(); } @@ -1213,28 +1182,24 @@ } /** - * Scatter read. The completion handler will be called once some - * data has been read or an error occurred. If a CompletionCheck - * object has been provided, the completion handler will only be - * called if the callHandler method returned true. If no - * CompletionCheck object has been provided, the default NIO2 - * behavior is used: the completion handler will be called as soon - * as some data has been read, even if the read has completed inline. - * - * @param block is the blocking mode that will be used for this operation - * @param timeout timeout duration for the read - * @param unit units for the timeout duration - * @param attachment an object to attach to the I/O operation that will be - * used when calling the completion handler - * @param check for the IO operation completion - * @param handler to call when the IO is complete - * @param dsts buffers - * @param The attachment type + * Scatter read. The completion handler will be called once some data has been read or an error occurred. If a + * CompletionCheck object has been provided, the completion handler will only be called if the callHandler method + * returned true. If no CompletionCheck object has been provided, the default NIO2 behavior is used: the completion + * handler will be called as soon as some data has been read, even if the read has completed inline. + * + * @param block is the blocking mode that will be used for this operation + * @param timeout timeout duration for the read + * @param unit units for the timeout duration + * @param attachment an object to attach to the I/O operation that will be used when calling the completion handler + * @param check for the IO operation completion + * @param handler to call when the IO is complete + * @param dsts buffers + * @param The attachment type + * * @return the completion state (done, done inline, or still pending) */ - public final CompletionState read(BlockingMode block, long timeout, - TimeUnit unit, A attachment, CompletionCheck check, - CompletionHandler handler, ByteBuffer... dsts) { + public final CompletionState read(BlockingMode block, long timeout, TimeUnit unit, A attachment, + CompletionCheck check, CompletionHandler handler, ByteBuffer... dsts) { if (dsts == null) { throw new IllegalArgumentException(); } @@ -1242,51 +1207,45 @@ } /** - * Scatter read. The completion handler will be called once some - * data has been read or an error occurred. If a CompletionCheck - * object has been provided, the completion handler will only be - * called if the callHandler method returned true. If no - * CompletionCheck object has been provided, the default NIO2 - * behavior is used: the completion handler will be called as soon - * as some data has been read, even if the read has completed inline. - * - * @param dsts buffers - * @param offset in the buffer array - * @param length in the buffer array - * @param block is the blocking mode that will be used for this operation - * @param timeout timeout duration for the read - * @param unit units for the timeout duration - * @param attachment an object to attach to the I/O operation that will be - * used when calling the completion handler - * @param check for the IO operation completion - * @param handler to call when the IO is complete - * @param The attachment type + * Scatter read. The completion handler will be called once some data has been read or an error occurred. If a + * CompletionCheck object has been provided, the completion handler will only be called if the callHandler method + * returned true. If no CompletionCheck object has been provided, the default NIO2 behavior is used: the completion + * handler will be called as soon as some data has been read, even if the read has completed inline. + * + * @param dsts buffers + * @param offset in the buffer array + * @param length in the buffer array + * @param block is the blocking mode that will be used for this operation + * @param timeout timeout duration for the read + * @param unit units for the timeout duration + * @param attachment an object to attach to the I/O operation that will be used when calling the completion handler + * @param check for the IO operation completion + * @param handler to call when the IO is complete + * @param The attachment type + * * @return the completion state (done, done inline, or still pending) */ - public final CompletionState read(ByteBuffer[] dsts, int offset, int length, - BlockingMode block, long timeout, TimeUnit unit, A attachment, - CompletionCheck check, CompletionHandler handler) { + public final CompletionState read(ByteBuffer[] dsts, int offset, int length, BlockingMode block, long timeout, + TimeUnit unit, A attachment, CompletionCheck check, CompletionHandler handler) { return vectoredOperation(true, dsts, offset, length, block, timeout, unit, attachment, check, handler); } /** - * Gather write. The completion handler will be called once some - * data has been written or an error occurred. The default NIO2 - * behavior is used: the completion handler will be called, even - * if the write is incomplete and data remains in the buffers, or - * if the write completed inline. - * - * @param timeout timeout duration for the write - * @param unit units for the timeout duration - * @param attachment an object to attach to the I/O operation that will be - * used when calling the completion handler - * @param handler to call when the IO is complete - * @param srcs buffers - * @param The attachment type + * Gather write. The completion handler will be called once some data has been written or an error occurred. The + * default NIO2 behavior is used: the completion handler will be called, even if the write is incomplete and data + * remains in the buffers, or if the write completed inline. + * + * @param timeout timeout duration for the write + * @param unit units for the timeout duration + * @param attachment an object to attach to the I/O operation that will be used when calling the completion handler + * @param handler to call when the IO is complete + * @param srcs buffers + * @param The attachment type + * * @return the completion state (done, done inline, or still pending) */ public final CompletionState write(long timeout, TimeUnit unit, A attachment, - CompletionHandler handler, ByteBuffer... srcs) { + CompletionHandler handler, ByteBuffer... srcs) { if (srcs == null) { throw new IllegalArgumentException(); } @@ -1294,29 +1253,25 @@ } /** - * Gather write. The completion handler will be called once some - * data has been written or an error occurred. If a CompletionCheck - * object has been provided, the completion handler will only be - * called if the callHandler method returned true. If no - * CompletionCheck object has been provided, the default NIO2 - * behavior is used: the completion handler will be called, even - * if the write is incomplete and data remains in the buffers, or - * if the write completed inline. - * - * @param block is the blocking mode that will be used for this operation - * @param timeout timeout duration for the write - * @param unit units for the timeout duration - * @param attachment an object to attach to the I/O operation that will be - * used when calling the completion handler - * @param check for the IO operation completion - * @param handler to call when the IO is complete - * @param srcs buffers - * @param The attachment type + * Gather write. The completion handler will be called once some data has been written or an error occurred. If a + * CompletionCheck object has been provided, the completion handler will only be called if the callHandler method + * returned true. If no CompletionCheck object has been provided, the default NIO2 behavior is used: the completion + * handler will be called, even if the write is incomplete and data remains in the buffers, or if the write + * completed inline. + * + * @param block is the blocking mode that will be used for this operation + * @param timeout timeout duration for the write + * @param unit units for the timeout duration + * @param attachment an object to attach to the I/O operation that will be used when calling the completion handler + * @param check for the IO operation completion + * @param handler to call when the IO is complete + * @param srcs buffers + * @param The attachment type + * * @return the completion state (done, done inline, or still pending) */ - public final CompletionState write(BlockingMode block, long timeout, - TimeUnit unit, A attachment, CompletionCheck check, - CompletionHandler handler, ByteBuffer... srcs) { + public final CompletionState write(BlockingMode block, long timeout, TimeUnit unit, A attachment, + CompletionCheck check, CompletionHandler handler, ByteBuffer... srcs) { if (srcs == null) { throw new IllegalArgumentException(); } @@ -1324,62 +1279,54 @@ } /** - * Gather write. The completion handler will be called once some - * data has been written or an error occurred. If a CompletionCheck - * object has been provided, the completion handler will only be - * called if the callHandler method returned true. If no - * CompletionCheck object has been provided, the default NIO2 - * behavior is used: the completion handler will be called, even - * if the write is incomplete and data remains in the buffers, or - * if the write completed inline. - * - * @param srcs buffers - * @param offset in the buffer array - * @param length in the buffer array - * @param block is the blocking mode that will be used for this operation - * @param timeout timeout duration for the write - * @param unit units for the timeout duration - * @param attachment an object to attach to the I/O operation that will be - * used when calling the completion handler - * @param check for the IO operation completion - * @param handler to call when the IO is complete - * @param The attachment type + * Gather write. The completion handler will be called once some data has been written or an error occurred. If a + * CompletionCheck object has been provided, the completion handler will only be called if the callHandler method + * returned true. If no CompletionCheck object has been provided, the default NIO2 behavior is used: the completion + * handler will be called, even if the write is incomplete and data remains in the buffers, or if the write + * completed inline. + * + * @param srcs buffers + * @param offset in the buffer array + * @param length in the buffer array + * @param block is the blocking mode that will be used for this operation + * @param timeout timeout duration for the write + * @param unit units for the timeout duration + * @param attachment an object to attach to the I/O operation that will be used when calling the completion handler + * @param check for the IO operation completion + * @param handler to call when the IO is complete + * @param The attachment type + * * @return the completion state (done, done inline, or still pending) */ - public final CompletionState write(ByteBuffer[] srcs, int offset, int length, - BlockingMode block, long timeout, TimeUnit unit, A attachment, - CompletionCheck check, CompletionHandler handler) { + public final CompletionState write(ByteBuffer[] srcs, int offset, int length, BlockingMode block, long timeout, + TimeUnit unit, A attachment, CompletionCheck check, CompletionHandler handler) { return vectoredOperation(false, srcs, offset, length, block, timeout, unit, attachment, check, handler); } /** - * Vectored operation. The completion handler will be called once - * the operation is complete or an error occurred. If a CompletionCheck - * object has been provided, the completion handler will only be - * called if the callHandler method returned true. If no - * CompletionCheck object has been provided, the default NIO2 - * behavior is used: the completion handler will be called, even - * if the operation is incomplete, or if the operation completed inline. - * - * @param read true if the operation is a read, false if it is a write - * @param buffers buffers - * @param offset in the buffer array - * @param length in the buffer array - * @param block is the blocking mode that will be used for this operation - * @param timeout timeout duration for the write - * @param unit units for the timeout duration - * @param attachment an object to attach to the I/O operation that will be - * used when calling the completion handler - * @param check for the IO operation completion - * @param handler to call when the IO is complete - * @param The attachment type + * Vectored operation. The completion handler will be called once the operation is complete or an error occurred. If + * a CompletionCheck object has been provided, the completion handler will only be called if the callHandler method + * returned true. If no CompletionCheck object has been provided, the default NIO2 behavior is used: the completion + * handler will be called, even if the operation is incomplete, or if the operation completed inline. + * + * @param read true if the operation is a read, false if it is a write + * @param buffers buffers + * @param offset in the buffer array + * @param length in the buffer array + * @param block is the blocking mode that will be used for this operation + * @param timeout timeout duration for the write + * @param unit units for the timeout duration + * @param attachment an object to attach to the I/O operation that will be used when calling the completion handler + * @param check for the IO operation completion + * @param handler to call when the IO is complete + * @param The attachment type + * * @return the completion state (done, done inline, or still pending) */ - protected final CompletionState vectoredOperation(boolean read, - ByteBuffer[] buffers, int offset, int length, - BlockingMode block, long timeout, TimeUnit unit, A attachment, - CompletionCheck check, CompletionHandler handler) { + protected final CompletionState vectoredOperation(boolean read, ByteBuffer[] buffers, int offset, int length, + BlockingMode block, long timeout, TimeUnit unit, A attachment, CompletionCheck check, + CompletionHandler handler) { IOException ioe = getError(); if (ioe != null) { handler.failed(ioe, attachment); @@ -1388,7 +1335,8 @@ if (timeout == -1) { timeout = AbstractEndpoint.toTimeout(read ? getReadTimeout() : getWriteTimeout()); unit = TimeUnit.MILLISECONDS; - } else if (!hasPerOperationTimeout() && (unit.toMillis(timeout) != (read ? getReadTimeout() : getWriteTimeout()))) { + } else if (!hasPerOperationTimeout() && + (unit.toMillis(timeout) != (read ? getReadTimeout() : getWriteTimeout()))) { if (read) { setReadTimeout(unit.toMillis(timeout)); } else { @@ -1416,8 +1364,8 @@ } } VectoredIOCompletionHandler completion = new VectoredIOCompletionHandler<>(); - OperationState state = newOperationState(read, buffers, offset, length, block, timeout, unit, - attachment, check, handler, read ? readPending : writePending, completion); + OperationState state = newOperationState(read, buffers, offset, length, block, timeout, unit, attachment, + check, handler, read ? readPending : writePending, completion); if (read) { readOperation = state; } else { @@ -1428,7 +1376,13 @@ synchronized (state) { if (state.state == CompletionState.PENDING) { try { - state.wait(unit.toMillis(timeout)); + long timeoutExpiry = System.nanoTime() + unit.toNanos(timeout); + long timeoutMillis = unit.toMillis(timeout); + // Spurious wake-ups are possible. Keep waiting until state changes or timeout expires. + while (state.state == CompletionState.PENDING && timeoutMillis > 0) { + state.wait(unit.toMillis(timeout)); + timeoutMillis = (timeoutExpiry - System.nanoTime()) / 1_000_000; + } if (state.state == CompletionState.PENDING) { if (handler != null && state.callHandler.compareAndSet(true, false)) { handler.failed(new SocketTimeoutException(getTimeoutMsg(read)), attachment); @@ -1457,11 +1411,9 @@ } - protected abstract OperationState newOperationState(boolean read, - ByteBuffer[] buffers, int offset, int length, - BlockingMode block, long timeout, TimeUnit unit, A attachment, - CompletionCheck check, CompletionHandler handler, - Semaphore semaphore, VectoredIOCompletionHandler completion); + protected abstract OperationState newOperationState(boolean read, ByteBuffer[] buffers, int offset, + int length, BlockingMode block, long timeout, TimeUnit unit, A attachment, CompletionCheck check, + CompletionHandler handler, Semaphore semaphore, VectoredIOCompletionHandler completion); // --------------------------------------------------------- Utility methods @@ -1499,8 +1451,8 @@ public ServletConnection getServletConnection(String protocol, String protocolConnectionId) { if (servletConnection == null) { - servletConnection = new ServletConnectionImpl( - connectionId, protocol, protocolConnectionId, endpoint.isSSLEnabled()); + servletConnection = + new ServletConnectionImpl(connectionId, protocol, protocolConnectionId, endpoint.isSSLEnabled()); } return servletConnection; } diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/net/TLSClientHelloExtractor.java tomcat10-10.1.52/java/org/apache/tomcat/util/net/TLSClientHelloExtractor.java --- tomcat10-10.1.40/java/org/apache/tomcat/util/net/TLSClientHelloExtractor.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/net/TLSClientHelloExtractor.java 2026-01-23 19:33:36.000000000 +0000 @@ -29,11 +29,12 @@ import org.apache.tomcat.util.buf.HexUtils; import org.apache.tomcat.util.http.parser.HttpParser; import org.apache.tomcat.util.net.openssl.ciphers.Cipher; +import org.apache.tomcat.util.net.openssl.ciphers.Group; +import org.apache.tomcat.util.net.openssl.ciphers.SignatureScheme; import org.apache.tomcat.util.res.StringManager; /** - * This class extracts the SNI host name and ALPN protocols from a TLS - * client-hello message. + * This class extracts the SNI host name and ALPN protocols from a TLS client-hello message. */ public class TLSClientHelloExtractor { @@ -46,28 +47,33 @@ private final String sniValue; private final List clientRequestedApplicationProtocols; private final List clientRequestedProtocols; + private final List clientSupportedGroups; + private final List clientSignatureSchemes; private static final int TLS_RECORD_HEADER_LEN = 5; private static final int TLS_EXTENSION_SERVER_NAME = 0; + private static final int TLS_EXTENSION_SUPPORTED_GROUPS = 10; + // Note: Signature algorithms is the name of the extension + // Starting with TLS 1.3, this contains signature schemes + // For TLS before 1.3, this contains signature algorithms + private static final int TLS_EXTENSION_SIGNATURE_ALGORITHMS = 13; private static final int TLS_EXTENSION_ALPN = 16; private static final int TLS_EXTENSION_SUPPORTED_VERSION = 43; - public static byte[] USE_TLS_RESPONSE = ("HTTP/1.1 400 \r\n" + - "Content-Type: text/plain;charset=UTF-8\r\n" + - "Connection: close\r\n" + - "\r\n" + - "Bad Request\r\n" + - "This combination of host and port requires TLS.\r\n").getBytes(StandardCharsets.UTF_8); + public static byte[] USE_TLS_RESPONSE = + ("HTTP/1.1 400 \r\n" + "Content-Type: text/plain;charset=UTF-8\r\n" + "Connection: close\r\n" + "\r\n" + + "Bad Request\r\n" + "This combination of host and port requires TLS.\r\n") + .getBytes(StandardCharsets.UTF_8); /** - * Creates the instance of the parser and processes the provided buffer. The - * buffer position and limit will be modified during the execution of this - * method, but they will be returned to the original values before the method + * Creates the instance of the parser and processes the provided buffer. The buffer position and limit will be + * modified during the execution of this method, but they will be returned to the original values before the method * exits. * * @param netInBuffer The buffer containing the TLS data to process + * * @throws IOException If the client hello message is malformed */ public TLSClientHelloExtractor(ByteBuffer netInBuffer) throws IOException { @@ -80,6 +86,8 @@ List clientRequestedCipherNames = new ArrayList<>(); List clientRequestedApplicationProtocols = new ArrayList<>(); List clientRequestedProtocols = new ArrayList<>(); + List clientSupportedGroups = new ArrayList<>(); + List clientSignatureSchemes = new ArrayList<>(); String sniValue = null; try { // Switch to read mode. @@ -150,26 +158,32 @@ skipBytes(netInBuffer, 2); // Read the extensions until we run out of data or find the data // we need - while (netInBuffer.hasRemaining() && (sniValue == null || - clientRequestedApplicationProtocols.isEmpty() || clientRequestedProtocols.isEmpty())) { + while (netInBuffer.hasRemaining() && (sniValue == null || clientRequestedApplicationProtocols.isEmpty() || + clientRequestedProtocols.isEmpty())) { // Extension type is two byte char extensionType = netInBuffer.getChar(); // Extension size is another two bytes char extensionDataSize = netInBuffer.getChar(); switch (extensionType) { - case TLS_EXTENSION_SERVER_NAME: { - sniValue = readSniExtension(netInBuffer); - break; - } - case TLS_EXTENSION_ALPN: - readAlpnExtension(netInBuffer, clientRequestedApplicationProtocols); - break; - case TLS_EXTENSION_SUPPORTED_VERSION: - readSupportedVersions(netInBuffer, clientRequestedProtocols); - break; - default: { - skipBytes(netInBuffer, extensionDataSize); - } + case TLS_EXTENSION_SERVER_NAME: { + sniValue = readSniExtension(netInBuffer); + break; + } + case TLS_EXTENSION_SUPPORTED_GROUPS: + readSupportedGroups(netInBuffer, clientSupportedGroups); + break; + case TLS_EXTENSION_SIGNATURE_ALGORITHMS: + readSignatureSchemes(netInBuffer, clientSignatureSchemes); + break; + case TLS_EXTENSION_ALPN: + readAlpnExtension(netInBuffer, clientRequestedApplicationProtocols); + break; + case TLS_EXTENSION_SUPPORTED_VERSION: + readSupportedVersions(netInBuffer, clientRequestedProtocols); + break; + default: { + skipBytes(netInBuffer, extensionDataSize); + } } } if (clientRequestedProtocols.isEmpty()) { @@ -185,6 +199,14 @@ this.clientRequestedApplicationProtocols = clientRequestedApplicationProtocols; this.sniValue = sniValue; this.clientRequestedProtocols = clientRequestedProtocols; + this.clientSupportedGroups = clientSupportedGroups; + this.clientSignatureSchemes = clientSignatureSchemes; + if (log.isTraceEnabled()) { + log.trace("TLS Client Hello: " + clientRequestedCiphers + " Names " + clientRequestedCipherNames + + " Protocols " + clientRequestedApplicationProtocols + " sniValue " + sniValue + + " clientRequestedProtocols " + clientRequestedProtocols + " clientSupportedGroups " + clientSupportedGroups + + " clientSignatureSchemes " + clientSignatureSchemes); + } // Whatever happens, return the buffer to its original state netInBuffer.limit(limit); netInBuffer.position(pos); @@ -198,8 +220,7 @@ /** - * @return The SNI value provided by the client converted to lower case if - * not already lower case. + * @return The SNI value provided by the client converted to lower case if not already lower case. */ public String getSNIValue() { if (result == ExtractorResult.COMPLETE) { @@ -246,6 +267,24 @@ } + public List getClientSupportedGroups() { + if (result == ExtractorResult.COMPLETE || result == ExtractorResult.NOT_PRESENT) { + return clientSupportedGroups; + } else { + throw new IllegalStateException(sm.getString("sniExtractor.tooEarly")); + } + } + + + public List getClientSignatureSchemes() { + if (result == ExtractorResult.COMPLETE || result == ExtractorResult.NOT_PRESENT) { + return clientSignatureSchemes; + } else { + throw new IllegalStateException(sm.getString("sniExtractor.tooEarly")); + } + } + + private static ExtractorResult handleIncompleteRead(ByteBuffer bb) { if (bb.limit() == bb.capacity()) { // Buffer not big enough @@ -281,8 +320,8 @@ private static boolean isHttp(ByteBuffer bb) { // Based on code in Http11InputBuffer // Note: The actual request is not important. This code only checks that - // the buffer contains a correctly formatted HTTP request line. - // The method, target and protocol are not validated. + // the buffer contains a correctly formatted HTTP request line. + // The method, target and protocol are not validated. byte chr; bb.position(0); @@ -427,6 +466,34 @@ } } + + private static void readSupportedGroups(ByteBuffer bb, List groups) { + // First 2 bytes are size of the group list + int toRead = bb.getChar() / 2; + // Then the list of groups + for (int i = 0; i < toRead; i++) { + char id = bb.getChar(); + Group group = Group.valueOf(id); + if (group != null) { + groups.add(group); + } + } + } + + + private static void readSignatureSchemes(ByteBuffer bb, List signatureSchemes) { + // First 2 bytes are size of the signature algorithm list + int toRead = bb.getChar() / 2; + // Then the list of schemes + for (int i = 0; i < toRead; i++) { + char id = bb.getChar(); + SignatureScheme signatureScheme = SignatureScheme.valueOf(id); + if (signatureScheme != null) { + signatureSchemes.add(signatureScheme); + } + } + } + public enum ExtractorResult { COMPLETE, diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/net/WriteBuffer.java tomcat10-10.1.52/java/org/apache/tomcat/util/net/WriteBuffer.java --- tomcat10-10.1.40/java/org/apache/tomcat/util/net/WriteBuffer.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/net/WriteBuffer.java 2026-01-23 19:33:36.000000000 +0000 @@ -26,12 +26,10 @@ import org.apache.tomcat.util.buf.ByteBufferHolder; /** - * Provides an expandable set of buffers for writes. Non-blocking writes can be - * of any size and may not be able to be written immediately or wholly contained - * in the buffer used to perform the writes to the next layer. This class - * provides a buffering capability to allow such writes to return immediately - * and also allows for the user provided buffers to be re-used / recycled as - * required. + * Provides an expandable set of buffers for writes. Non-blocking writes can be of any size and may not be able to be + * written immediately or wholly contained in the buffer used to perform the writes to the next layer. This class + * provides a buffering capability to allow such writes to return immediately and also allows for the user provided + * buffers to be re-used / recycled as required. */ public class WriteBuffer { @@ -76,14 +74,11 @@ /** - * Create an array of ByteBuffers from the current WriteBuffer, prefixing - * that array with the provided ByteBuffers. + * Create an array of ByteBuffers from the current WriteBuffer, prefixing that array with the provided ByteBuffers. * - * @param prefixes The additional ByteBuffers to add to the start of the - * array + * @param prefixes The additional ByteBuffers to add to the start of the array * - * @return an array of ByteBuffers from the current WriteBuffer prefixed by - * the provided ByteBuffers + * @return an array of ByteBuffers from the current WriteBuffer prefixed by the provided ByteBuffers */ ByteBuffer[] toArray(ByteBuffer... prefixes) { List result = new ArrayList<>(); @@ -138,8 +133,7 @@ /** - * Interface implemented by clients of the WriteBuffer to enable data to be - * written back out from the buffer. + * Interface implemented by clients of the WriteBuffer to enable data to be written back out from the buffer. */ public interface Sink { boolean writeFromBuffer(ByteBuffer buffer, boolean block) throws IOException; diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/net/jsse/JSSEImplementation.java tomcat10-10.1.52/java/org/apache/tomcat/util/net/jsse/JSSEImplementation.java --- tomcat10-10.1.40/java/org/apache/tomcat/util/net/jsse/JSSEImplementation.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/net/jsse/JSSEImplementation.java 2026-01-23 19:33:36.000000000 +0000 @@ -26,13 +26,6 @@ import org.apache.tomcat.util.net.SSLSupport; import org.apache.tomcat.util.net.SSLUtil; -/* JSSEImplementation: - - Concrete implementation class for JSSE - - @author EKR - */ - public class JSSEImplementation extends SSLImplementation { public JSSEImplementation() { @@ -43,7 +36,7 @@ } @Override - public SSLSupport getSSLSupport(SSLSession session, Map> additionalAttributes) { + public SSLSupport getSSLSupport(SSLSession session, Map> additionalAttributes) { return new JSSESupport(session, additionalAttributes); } diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/net/jsse/JSSEKeyManager.java tomcat10-10.1.52/java/org/apache/tomcat/util/net/jsse/JSSEKeyManager.java --- tomcat10-10.1.40/java/org/apache/tomcat/util/net/jsse/JSSEKeyManager.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/net/jsse/JSSEKeyManager.java 2026-01-23 19:33:36.000000000 +0000 @@ -26,11 +26,8 @@ import javax.net.ssl.X509KeyManager; /** - * X509KeyManager which allows selection of a specific key pair and certificate - * chain (identified by their keystore alias name) to be used by the server to - * authenticate itself to SSL clients. - * - * @author Jan Luehe + * X509KeyManager which allows selection of a specific key pair and certificate chain (identified by their keystore + * alias name) to be used by the server to authenticate itself to SSL clients. */ public final class JSSEKeyManager extends X509ExtendedKeyManager { @@ -41,9 +38,8 @@ /** * Constructor. * - * @param mgr The X509KeyManager used as a delegate - * @param serverKeyAlias The alias name of the server's key pair and - * supporting certificate chain + * @param mgr The X509KeyManager used as a delegate + * @param serverKeyAlias The alias name of the server's key pair and supporting certificate chain */ public JSSEKeyManager(X509KeyManager mgr, String serverKeyAlias) { super(); @@ -53,9 +49,8 @@ /** - * Returns the server key alias that was provided in the constructor or the - * result from {@link X509KeyManager#chooseServerAlias(String, Principal[], - * Socket)} for the delegate if no alias is specified. + * Returns the server key alias that was provided in the constructor or the result from + * {@link X509KeyManager#chooseServerAlias(String, Principal[], Socket)} for the delegate if no alias is specified. */ @Override public String chooseServerAlias(String keyType, Principal[] issuers, Socket socket) { @@ -68,14 +63,13 @@ /** - * Returns the server key alias that was provided in the constructor or the - * result from {@link X509ExtendedKeyManager#chooseEngineServerAlias(String, - * Principal[], SSLEngine)} for the delegate if no alias is specified. + * Returns the server key alias that was provided in the constructor or the result from + * {@link X509ExtendedKeyManager#chooseEngineServerAlias(String, Principal[], SSLEngine)} for the delegate if no + * alias is specified. */ @Override - public String chooseEngineServerAlias(String keyType, Principal[] issuers, - SSLEngine engine) { - if (serverKeyAlias!=null) { + public String chooseEngineServerAlias(String keyType, Principal[] issuers, SSLEngine engine) { + if (serverKeyAlias != null) { return serverKeyAlias; } @@ -84,8 +78,7 @@ @Override - public String chooseClientAlias(String[] keyType, Principal[] issuers, - Socket socket) { + public String chooseClientAlias(String[] keyType, Principal[] issuers, Socket socket) { return delegate.chooseClientAlias(keyType, issuers, socket); } @@ -115,8 +108,7 @@ @Override - public String chooseEngineClientAlias(String[] keyType, Principal[] issuers, - SSLEngine engine) { + public String chooseEngineClientAlias(String[] keyType, Principal[] issuers, SSLEngine engine) { return delegate.chooseClientAlias(keyType, issuers, null); } } diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/net/jsse/JSSESSLContext.java tomcat10-10.1.52/java/org/apache/tomcat/util/net/jsse/JSSESSLContext.java --- tomcat10-10.1.40/java/org/apache/tomcat/util/net/jsse/JSSESSLContext.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/net/jsse/JSSESSLContext.java 2026-01-23 19:33:36.000000000 +0000 @@ -46,8 +46,7 @@ } @Override - public void init(KeyManager[] kms, TrustManager[] tms, SecureRandom sr) - throws KeyManagementException { + public void init(KeyManager[] kms, TrustManager[] tms, SecureRandom sr) throws KeyManagementException { this.kms = kms; this.tms = tms; context.init(kms, tms, sr); diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/net/jsse/JSSESupport.java tomcat10-10.1.52/java/org/apache/tomcat/util/net/jsse/JSSESupport.java --- tomcat10-10.1.40/java/org/apache/tomcat/util/net/jsse/JSSESupport.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/net/jsse/JSSESupport.java 2026-01-23 19:33:36.000000000 +0000 @@ -36,13 +36,7 @@ import org.apache.tomcat.util.res.StringManager; /** - * JSSESupport. - * Concrete implementation class for JSSE Support classes. - * - * @author EKR - * @author Craig R. McClanahan - * Parts cribbed from JSSECertCompat - * Parts cribbed from CertificatesValve + * JSSESupport. Concrete implementation class for JSSE Support classes. */ public class JSSESupport implements SSLSupport, SSLSessionManager { @@ -61,9 +55,8 @@ } /* - * NO-OP method provided to make it easy for other classes in this package - * to trigger the loading of this class and the population of the - * keySizeCache. + * NO-OP method provided to make it easy for other classes in this package to trigger the loading of this class and + * the population of the keySizeCache. */ static void init() { // NO-OP @@ -101,11 +94,13 @@ return null; } - Certificate [] certs; + Certificate[] certs; try { certs = session.getPeerCertificates(); - } catch( Throwable t ) { - log.debug(sm.getString("jsseSupport.clientCertError"), t); + } catch (Throwable t) { + if (log.isDebugEnabled()) { + log.debug(sm.getString("jsseSupport.clientCertError"), t); + } return null; } @@ -114,31 +109,31 @@ private static X509Certificate[] convertCertificates(Certificate[] certs) { - if( certs==null ) { + if (certs == null) { return null; } - X509Certificate [] x509Certs = new X509Certificate[certs.length]; - for(int i=0; i < certs.length; i++) { - if (certs[i] instanceof X509Certificate ) { + X509Certificate[] x509Certs = new X509Certificate[certs.length]; + for (int i = 0; i < certs.length; i++) { + if (certs[i] instanceof X509Certificate) { // always currently true with the JSSE 1.1.x x509Certs[i] = (X509Certificate) certs[i]; } else { try { - byte [] buffer = certs[i].getEncoded(); + byte[] buffer = certs[i].getEncoded(); CertificateFactory cf = CertificateFactory.getInstance("X.509"); ByteArrayInputStream stream = new ByteArrayInputStream(buffer); x509Certs[i] = (X509Certificate) cf.generateCertificate(stream); - } catch(Exception ex) { - log.info(sm.getString("jsseSupport.certTranslationError", certs[i]), ex); + } catch (Exception e) { + log.info(sm.getString("jsseSupport.certTranslationError", certs[i]), e); return null; } } - if(log.isTraceEnabled()) { + if (log.isTraceEnabled()) { log.trace("Cert #" + i + " = " + x509Certs[i]); } } - if(x509Certs.length < 1) { + if (x509Certs.length < 1) { return null; } return x509Certs; @@ -161,18 +156,17 @@ } @Override - public String getSessionId() - throws IOException { + public String getSessionId() throws IOException { // Look up the current SSLSession if (session == null) { return null; } // Expose ssl_session (getId) - byte [] ssl_session = session.getId(); + byte[] ssl_session = session.getId(); if (ssl_session == null || ssl_session.length == 0) { return null; } - StringBuilder buf=new StringBuilder(); + StringBuilder buf = new StringBuilder(); for (byte b : ssl_session) { String digit = Integer.toHexString(b); if (digit.length() < 2) { @@ -203,9 +197,9 @@ @Override public String getProtocol() throws IOException { if (session == null) { - return null; + return null; } - return session.getProtocol(); + return session.getProtocol(); } @Override diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/net/jsse/JSSEUtil.java tomcat10-10.1.52/java/org/apache/tomcat/util/net/jsse/JSSEUtil.java --- tomcat10-10.1.40/java/org/apache/tomcat/util/net/jsse/JSSEUtil.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/net/jsse/JSSEUtil.java 2026-01-23 19:33:36.000000000 +0000 @@ -34,12 +34,6 @@ /** * SSLUtil implementation for JSSE. - * - * @author Harish Prabandham - * @author Costin Manolache - * @author Stefan Freyr Stefansson - * @author EKR - * @author Jan Luehe */ public class JSSEUtil extends SSLUtilBase { @@ -52,12 +46,12 @@ private volatile Set implementedCiphers; - public JSSEUtil (SSLHostConfigCertificate certificate) { + public JSSEUtil(SSLHostConfigCertificate certificate) { this(certificate, true); } - public JSSEUtil (SSLHostConfigCertificate certificate, boolean warnOnSkip) { + public JSSEUtil(SSLHostConfigCertificate certificate, boolean warnOnSkip) { super(certificate, warnOnSkip); } @@ -90,8 +84,7 @@ @Override - public SSLContext createSSLContextInternal(List negotiableProtocols) - throws NoSuchAlgorithmException { + public SSLContext createSSLContextInternal(List negotiableProtocols) throws NoSuchAlgorithmException { return new JSSESSLContext(sslHostConfig.getSslProtocol()); } @@ -103,7 +96,7 @@ SSLContext context; try { context = new JSSESSLContext(sslHostConfig.getSslProtocol()); - context.init(null, null, null); + context.init(null, null, null); } catch (NoSuchAlgorithmException | KeyManagementException e) { // This is fatal for the connector so throw an exception to prevent // it from starting @@ -149,6 +142,11 @@ } else { implementedCiphers = new HashSet<>(Arrays.asList(implementedCipherSuiteArray)); } + + if (sslHostConfig.getOpenSslConf() != null) { + log.warn(sm.getString("jsseUtil.opensslconf.present")); + } + initialized = true; } } diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/net/jsse/LocalStrings.properties tomcat10-10.1.52/java/org/apache/tomcat/util/net/jsse/LocalStrings.properties --- tomcat10-10.1.40/java/org/apache/tomcat/util/net/jsse/LocalStrings.properties 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/net/jsse/LocalStrings.properties 2026-01-23 19:33:36.000000000 +0000 @@ -21,12 +21,14 @@ jsseUtil.excludeProtocol=The SSL protocol [{0}] which is supported in this JRE was excluded from the protocols available to Tomcat jsseUtil.noDefaultProtocols=Unable to determine a default for sslEnabledProtocols. Set an explicit value to ensure the connector can start. +jsseUtil.opensslconf.present=A connector is configured to use a JSSE TLS implementation with OpenSSL specific OpenSSLConf configuration elements. The OpenSSLConf configuration elements will be ignored. pemFile.noMultiPrimes=The PKCS#1 certificate is in multi-prime format and Java does not provide an API for constructing an RSA private key object from that format pemFile.noPassword=A password is required to decrypt the private key pemFile.notPbkdf2=The OID [{0}] is not the correct OID for PKBDF2 which is the only permitted KDF for PBES2 pemFile.notValidRFC5915=The provided key file does not conform to RFC 5915 pemFile.parseError=Unable to parse the key from [{0}] +pemFile.parseError.algorithm=Unable to parse the key using algorithm [{0}] pemFile.unknownEncryptedFormat=The format [{0}] is not a recognised encrypted PEM file format pemFile.unknownEncryptionAlgorithm=The encryption algorithm with DER encoded OID of [{0}] was not recognised pemFile.unknownPkcs8Algorithm=The PKCS#8 encryption algorithm with DER encoded OID of [{0}] was not recognised diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/net/jsse/LocalStrings_fr.properties tomcat10-10.1.52/java/org/apache/tomcat/util/net/jsse/LocalStrings_fr.properties --- tomcat10-10.1.40/java/org/apache/tomcat/util/net/jsse/LocalStrings_fr.properties 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/net/jsse/LocalStrings_fr.properties 2026-01-23 19:33:36.000000000 +0000 @@ -27,6 +27,7 @@ pemFile.notPbkdf2=L''OID [{0}] n''est pas un OID correct pour PKBDF2 qui est le seul KDF autorisé pour PBES2 pemFile.notValidRFC5915=La fichier de clé fourni ne se conforme pas à la RFC 5915 pemFile.parseError=Impossible de parser la clé de [{0}] +pemFile.parseError.algorithm=Impossible de traiter la clé en utilisant l''algorithme [{0}] pemFile.unknownEncryptedFormat=Le format [{0}] n''est pas un format de cryptage reconnu pour un fichier PEM pemFile.unknownEncryptionAlgorithm=L''algorithme de cryptage avec un OID encodé en DER de [{0}] n''est pas reconnu pemFile.unknownPkcs8Algorithm=L''algorithme de cryptage PKCS#8 avec un OID encodé en DER de [{0}] n''est pas reconnu diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/net/jsse/LocalStrings_ja.properties tomcat10-10.1.52/java/org/apache/tomcat/util/net/jsse/LocalStrings_ja.properties --- tomcat10-10.1.40/java/org/apache/tomcat/util/net/jsse/LocalStrings_ja.properties 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/net/jsse/LocalStrings_ja.properties 2026-01-23 19:33:36.000000000 +0000 @@ -27,6 +27,7 @@ pemFile.notPbkdf2=OID [{0}] は、PBES2 に唯一許可される KDF である PKBDF2 の正しい OID ではありません pemFile.notValidRFC5915=与えられたキーファイルは RFC 5915 に準拠していません pemFile.parseError=秘密鍵ファイル [{0}] を解析できません +pemFile.parseError.algorithm=アルゴリズム [{0}] を使用してキーを解析できません pemFile.unknownEncryptedFormat=フォーマット [{0}] は認識される暗号化 PEM ファイル形式ではありません pemFile.unknownEncryptionAlgorithm=[{0}] の DER エンコードされた OID を持つ暗号化アルゴリズムが認識されませんでした pemFile.unknownPkcs8Algorithm=[{0}] の DER エンコードされた OID を持つ PKCS#8 暗号化アルゴリズムが認識されませんでした diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/net/jsse/PEMFile.java tomcat10-10.1.52/java/org/apache/tomcat/util/net/jsse/PEMFile.java --- tomcat10-10.1.40/java/org/apache/tomcat/util/net/jsse/PEMFile.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/net/jsse/PEMFile.java 2026-01-23 19:33:36.000000000 +0000 @@ -107,10 +107,9 @@ } public static String toPEM(X509Certificate certificate) throws CertificateEncodingException { - return Part.BEGIN_BOUNDARY + Part.CERTIFICATE + Part.FINISH_BOUNDARY + - System.lineSeparator() + - Base64.getMimeEncoder().encodeToString(certificate.getEncoded()) + - Part.END_BOUNDARY + Part.CERTIFICATE + Part.FINISH_BOUNDARY; + return Part.BEGIN_BOUNDARY + Part.CERTIFICATE + Part.FINISH_BOUNDARY + System.lineSeparator() + + Base64.getMimeEncoder().encodeToString(certificate.getEncoded()) + Part.END_BOUNDARY + + Part.CERTIFICATE + Part.FINISH_BOUNDARY; } private final List certificates = new ArrayList<>(); @@ -412,7 +411,8 @@ byte[] oidPRF = p.parseOIDAsBytes(); prf = OID_TO_PRF.get(HexUtils.toHexString(oidPRF)); if (prf == null) { - throw new NoSuchAlgorithmException(sm.getString("pemFile.unknownPrfAlgorithm", toDottedOidString(oidPRF))); + throw new NoSuchAlgorithmException( + sm.getString("pemFile.unknownPrfAlgorithm", toDottedOidString(oidPRF))); } p.parseNull(); @@ -482,11 +482,12 @@ InvalidKeyException exception = new InvalidKeyException(sm.getString("pemFile.parseError", filename)); if (keyAlgorithm == null) { - for (String algorithm : new String[] { "RSA", "DSA", "EC" }) { + for (String algorithm : new String[] { "RSA", "DSA", "EC", "ML-DSA" }) { try { return KeyFactory.getInstance(algorithm).generatePrivate(keySpec); } catch (InvalidKeySpecException e) { - exception.addSuppressed(e); + exception.addSuppressed(new InvalidKeySpecException( + sm.getString("pemFile.parseError.algorithm", algorithm), e)); } } } else { diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/net/mbeans-descriptors.xml tomcat10-10.1.52/java/org/apache/tomcat/util/net/mbeans-descriptors.xml --- tomcat10-10.1.40/java/org/apache/tomcat/util/net/mbeans-descriptors.xml 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/net/mbeans-descriptors.xml 2026-01-23 19:33:36.000000000 +0000 @@ -151,6 +151,9 @@ + + negotiableProtocols) - throws SSLException { + public OpenSSLContext(SSLHostConfigCertificate certificate, List negotiableProtocols) throws SSLException { this.sslHostConfig = certificate.getSSLHostConfig(); this.certificate = certificate; long aprPool = Pool.create(0); @@ -101,17 +102,24 @@ boolean success = false; try { // Create OpenSSLConfCmd context if used - OpenSSLConf openSslConf = sslHostConfig.getOpenSslConf(); - if (openSslConf != null) { + if (sslHostConfig.getOpenSslConf() == null && sslHostConfig.getTrustManagerClassName() == null && + sslHostConfig.getTruststore() == null) { + /* + * If an instance of OpenSSLConf is required, it must be created here so the reference can be placed in + * the (immutable) OpenSSLState record. + * + * If OpenSSL managed trust is used, an instance of OpenSSLConf is required to pass OCSP configuration + * parameters to Tomcat Native. Create one if one hasn't already been created. + */ + sslHostConfig.setOpenSslConf(new OpenSSLConf()); + } + if (sslHostConfig.getOpenSslConf() != null) { try { if (log.isTraceEnabled()) { log.trace(sm.getString("openssl.makeConf")); } - cctx = SSLConf.make(aprPool, - SSL.SSL_CONF_FLAG_FILE | - SSL.SSL_CONF_FLAG_SERVER | - SSL.SSL_CONF_FLAG_CERTIFICATE | - SSL.SSL_CONF_FLAG_SHOW_ERRORS); + cctx = SSLConf.make(aprPool, SSL.SSL_CONF_FLAG_FILE | SSL.SSL_CONF_FLAG_SERVER | + SSL.SSL_CONF_FLAG_CERTIFICATE | SSL.SSL_CONF_FLAG_SHOW_ERRORS); } catch (Exception e) { throw new SSLException(sm.getString("openssl.errMakeConf"), e); } @@ -157,20 +165,17 @@ this.negotiableProtocols = negotiableProtocols; success = true; - } catch(Exception e) { + } catch (Exception e) { throw new SSLException(sm.getString("openssl.errorSSLCtxInit"), e); } finally { state = new OpenSSLState(aprPool, cctx, ctx); /* - * When an SSLHostConfig is replaced at runtime, it is not possible to - * call destroy() on the associated OpenSSLContext since it is likely - * that there will be in-progress connections using the OpenSSLContext. - * A reference chain has been deliberately established (see - * OpenSSLSessionContext) to ensure that the OpenSSLContext remains - * ineligible for GC while those connections are alive. Once those - * connections complete, the OpenSSLContext will become eligible for GC - * and this method will ensure that the associated native resources are - * cleaned up. + * When an SSLHostConfig is replaced at runtime, it is not possible to call destroy() on the associated + * OpenSSLContext since it is likely that there will be in-progress connections using the OpenSSLContext. A + * reference chain has been deliberately established (see OpenSSLSessionContext) to ensure that the + * OpenSSLContext remains ineligible for GC while those connections are alive. Once those connections + * complete, the OpenSSLContext will become eligible for GC and this method will ensure that the associated + * native resources are cleaned up. */ cleanable = cleaner.register(this, state); @@ -222,12 +227,10 @@ return false; } if (rc <= 0) { - log.error(sm.getString("opensslconf.failedCommand", name, value, - Integer.toString(rc))); + log.error(sm.getString("opensslconf.failedCommand", name, value, Integer.toString(rc))); result = false; } else if (log.isTraceEnabled()) { - log.trace(sm.getString("opensslconf.resultCommand", name, value, - Integer.toString(rc))); + log.trace(sm.getString("opensslconf.resultCommand", name, value, Integer.toString(rc))); } } if (!result) { @@ -262,12 +265,10 @@ return false; } if (rc <= 0) { - log.error(sm.getString("opensslconf.failedCommand", name, value, - Integer.toString(rc))); + log.error(sm.getString("opensslconf.failedCommand", name, value, Integer.toString(rc))); result = false; } else if (log.isTraceEnabled()) { - log.trace(sm.getString("opensslconf.resultCommand", name, value, - Integer.toString(rc))); + log.trace(sm.getString("opensslconf.resultCommand", name, value, Integer.toString(rc))); } } rc = SSLConf.finish(cctx); @@ -284,16 +285,14 @@ /** * Setup the SSL_CTX. * - * @param kms Must contain a KeyManager of the type - * {@code OpenSSLKeyManager} - * @param tms Must contain a TrustManager of the type - * {@code X509TrustManager} - * @param sr Is not used for this implementation. + * @param kms Must contain a KeyManager of the type {@code OpenSSLKeyManager} + * @param tms Must contain a TrustManager of the type {@code X509TrustManager} + * @param sr Is not used for this implementation. + * * @throws KeyManagementException if an error occurs */ @Override - public void init(KeyManager[] kms, TrustManager[] tms, SecureRandom sr) - throws KeyManagementException { + public void init(KeyManager[] kms, TrustManager[] tms, SecureRandom sr) throws KeyManagementException { if (initialized) { log.warn(sm.getString("openssl.doubleInit")); return; @@ -327,8 +326,9 @@ SSLContext.clearOptions(state.ctx, SSL.SSL_OP_NO_TICKET); } - // List the ciphers that the client is permitted to negotiate + // Configure the ciphers that the client is permitted to negotiate SSLContext.setCipherSuite(state.ctx, sslHostConfig.getCiphers()); + SSLContext.setCipherSuitesEx(state.ctx, sslHostConfig.getCipherSuites()); // If there is no certificate file must be using a KeyStore so a KeyManager is required. // If there is a certificate file a KeyManager is helpful but not strictly necessary. @@ -340,34 +340,25 @@ // Client certificate verification int value = 0; switch (sslHostConfig.getCertificateVerification()) { - case NONE: - value = SSL.SSL_CVERIFY_NONE; - break; - case OPTIONAL: - value = SSL.SSL_CVERIFY_OPTIONAL; - break; - case OPTIONAL_NO_CA: - value = SSL.SSL_CVERIFY_OPTIONAL_NO_CA; - break; - case REQUIRED: - value = SSL.SSL_CVERIFY_REQUIRE; - break; + case NONE: + value = SSL.SSL_CVERIFY_NONE; + break; + case OPTIONAL: + value = SSL.SSL_CVERIFY_OPTIONAL; + break; + case OPTIONAL_NO_CA: + value = SSL.SSL_CVERIFY_OPTIONAL_NO_CA; + break; + case REQUIRED: + value = SSL.SSL_CVERIFY_REQUIRE; + break; } SSLContext.setVerify(state.ctx, value, sslHostConfig.getCertificateVerificationDepth()); if (tms != null) { // Client certificate verification based on custom trust managers x509TrustManager = chooseTrustManager(tms); - SSLContext.setCertVerifyCallback(state.ctx, (ssl, chain, auth) -> { - X509Certificate[] peerCerts = certificates(chain); - try { - x509TrustManager.checkClientTrusted(peerCerts, auth); - return true; - } catch (Exception e) { - log.debug(sm.getString("openssl.certificateVerificationFailed"), e); - } - return false; - }); + SSLContext.setCertVerifyCallback(state.ctx, new OpenSSLCertificateVerifier(x509TrustManager)); // Pass along the DER encoded certificates of the accepted client // certificate issuers, so that their subjects can be presented // by the server during the handshake to allow the client choosing @@ -383,6 +374,14 @@ SSLContext.setCACertificate(state.ctx, SSLHostConfig.adjustRelativePath(sslHostConfig.getCaCertificateFile()), SSLHostConfig.adjustRelativePath(sslHostConfig.getCaCertificatePath())); + sslHostConfig.getOpenSslConf().addCmd(new OpenSSLConfCmd(OpenSSLConfCmd.NO_OCSP_CHECK, + Boolean.toString(!sslHostConfig.getOcspEnabled()))); + sslHostConfig.getOpenSslConf().addCmd(new OpenSSLConfCmd(OpenSSLConfCmd.OCSP_SOFT_FAIL, + Boolean.toString(sslHostConfig.getOcspSoftFail()))); + sslHostConfig.getOpenSslConf().addCmd(new OpenSSLConfCmd(OpenSSLConfCmd.OCSP_TIMEOUT, + Integer.toString(sslHostConfig.getOcspTimeout()))); + sslHostConfig.getOpenSslConf().addCmd(new OpenSSLConfCmd(OpenSSLConfCmd.OCSP_VERIFY_FLAGS, + Integer.toString(sslHostConfig.getOcspVerifyFlags()))); } if (negotiableProtocols != null && !negotiableProtocols.isEmpty()) { @@ -439,8 +438,7 @@ if ((opts & SSL.SSL_OP_NO_SSLv3) == 0) { enabled.add(Constants.SSL_PROTO_SSLv3); } - sslHostConfig.setEnabledProtocols( - enabled.toArray(new String[0])); + sslHostConfig.setEnabledProtocols(enabled.toArray(new String[0])); // Reconfigure the enabled ciphers sslHostConfig.setEnabledCiphers(SSLContext.getCiphers(state.ctx)); } @@ -465,29 +463,25 @@ // Set certificate String passwordToUse; if (certificate.getCertificateKeyPasswordFile() != null) { - try (BufferedReader reader = - new BufferedReader(new InputStreamReader( - new FileInputStream( + try (BufferedReader reader = new BufferedReader(new InputStreamReader( + new FileInputStream( SSLHostConfig.adjustRelativePath(certificate.getCertificateKeyPasswordFile())), - StandardCharsets.UTF_8))) { + StandardCharsets.UTF_8))) { passwordToUse = reader.readLine(); } } else { passwordToUse = certificate.getCertificateKeyPassword(); } - SSLContext.setCertificate(state.ctx, - SSLHostConfig.adjustRelativePath(certificate.getCertificateFile()), - SSLHostConfig.adjustRelativePath(certificate.getCertificateKeyFile()), - passwordToUse, getCertificateIndex(certificate)); + SSLContext.setCertificate(state.ctx, SSLHostConfig.adjustRelativePath(certificate.getCertificateFile()), + SSLHostConfig.adjustRelativePath(certificate.getCertificateKeyFile()), passwordToUse, + getCertificateIndex(certificate)); // Set certificate chain file SSLContext.setCertificateChainFile(state.ctx, SSLHostConfig.adjustRelativePath(certificate.getCertificateChainFile()), false); // Set revocation SSLContext.setCARevocation(state.ctx, - SSLHostConfig.adjustRelativePath( - sslHostConfig.getCertificateRevocationListFile()), - SSLHostConfig.adjustRelativePath( - sslHostConfig.getCertificateRevocationListPath())); + SSLHostConfig.adjustRelativePath(sslHostConfig.getCertificateRevocationListFile()), + SSLHostConfig.adjustRelativePath(sslHostConfig.getCertificateRevocationListPath())); } else { String alias = certificate.getCertificateKeyAlias(); X509KeyManager x509KeyManager = certificate.getCertificateKeyManager(); @@ -500,12 +494,10 @@ chain = x509KeyManager.getCertificateChain(alias); } PrivateKey key = x509KeyManager.getPrivateKey(alias); - String encodedKey = - BEGIN_KEY + - Base64.getMimeEncoder(64, new byte[]{'\n'}).encodeToString(key.getEncoded()) + - END_KEY; + String encodedKey = BEGIN_KEY + + Base64.getMimeEncoder(64, new byte[] { '\n' }).encodeToString(key.getEncoded()) + END_KEY; SSLContext.setCertificateRaw(state.ctx, chain[0].getEncoded(), - encodedKey.getBytes(StandardCharsets.US_ASCII), getCertificateIndex(certificate)); + encodedKey.getBytes(StandardCharsets.US_ASCII), getCertificateIndex(certificate)); for (int i = 1; i < chain.length; i++) { SSLContext.addChainCertificateRaw(state.ctx, chain[i].getEncoded()); } @@ -521,7 +513,7 @@ result = SSL.SSL_AIDX_RSA; } else if (certificate.getType() == Type.EC) { result = SSL.SSL_AIDX_ECC; - } else if (certificate.getType() == Type.DSA) { + } else if (certificate.getType() == Type.DSA || certificate.getType() == Type.MLDSA) { result = SSL.SSL_AIDX_DSA; } else { result = SSL.SSL_AIDX_MAX; @@ -533,8 +525,7 @@ /* * Find a valid alias when none was specified in the config. */ - private static String findAlias(X509KeyManager keyManager, - SSLHostConfigCertificate certificate) { + private static String findAlias(X509KeyManager keyManager, SSLHostConfigCertificate certificate) { Type type = certificate.getType(); String result = null; @@ -551,7 +542,7 @@ Iterator iter = candidateTypes.iterator(); while (result == null && iter.hasNext()) { - result = keyManager.chooseServerAlias(iter.next().toString(), null, null); + result = keyManager.chooseServerAlias(iter.next().getKeyType(), null, null); } return result; @@ -566,14 +557,6 @@ throw new IllegalStateException(sm.getString("openssl.trustManagerMissing")); } - private static X509Certificate[] certificates(byte[][] chain) { - X509Certificate[] peerCerts = new X509Certificate[chain.length]; - for (int i = 0; i < peerCerts.length; i++) { - peerCerts[i] = new OpenSSLX509Certificate(chain[i]); - } - return peerCerts; - } - long getSSLContextID() { return state.ctx; @@ -647,14 +630,33 @@ @Override public void run() { - if (ctx != 0) { - SSLContext.free(ctx); - } - if (cctx != 0) { - SSLConf.free(cctx); - } - if (aprPool != 0) { - Pool.destroy(aprPool); + /* + * During shutdown there is a possibility that both the cleaner and the APR library termination code try and + * free these resources. If both call free, there will be a JVM crash. + * + * If the cleaner frees the resources, the APR library termination won't try free them as well. + * + * If the APR library termination frees the resources, the cleaner MUST NOT attempt to do so. + * + * The locks and checks below ensure that a) the cleaner only runs if the APR library has not yet been + * terminated and that the APR library status will not change while the cleaner is running. + */ + Lock readLock = AprStatus.getStatusLock().readLock(); + readLock.lock(); + try { + if (AprStatus.isAprInitialized()) { + if (ctx != 0) { + SSLContext.free(ctx); + } + if (cctx != 0) { + SSLConf.free(cctx); + } + if (aprPool != 0) { + Pool.destroy(aprPool); + } + } + } finally { + readLock.unlock(); } } } diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/net/openssl/OpenSSLEngine.java tomcat10-10.1.52/java/org/apache/tomcat/util/net/openssl/OpenSSLEngine.java --- tomcat10-10.1.40/java/org/apache/tomcat/util/net/openssl/OpenSSLEngine.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/net/openssl/OpenSSLEngine.java 2026-01-23 19:33:36.000000000 +0000 @@ -30,6 +30,7 @@ import java.util.List; import java.util.Map; import java.util.Set; +import java.util.concurrent.locks.Lock; import javax.net.ssl.SSLEngine; import javax.net.ssl.SSLEngineResult; @@ -42,6 +43,7 @@ import org.apache.juli.logging.Log; import org.apache.juli.logging.LogFactory; +import org.apache.tomcat.jni.AprStatus; import org.apache.tomcat.jni.Buffer; import org.apache.tomcat.jni.Pool; import org.apache.tomcat.jni.SSL; @@ -53,9 +55,8 @@ import org.apache.tomcat.util.res.StringManager; /** - * Implements a {@link SSLEngine} using - * OpenSSL - * BIO abstractions. + * Implements a {@link SSLEngine} using OpenSSL BIO + * abstractions. */ public final class OpenSSLEngine extends SSLEngine implements SSLUtil.ProtocolInfo { @@ -78,7 +79,7 @@ SSLContext.setCipherSuite(sslCtx, "ALL"); final long ssl = SSL.newSSL(sslCtx, true); try { - for (String c: SSL.getCiphers(ssl)) { + for (String c : SSL.getCiphers(ssl)) { // Filter out bad input. if (c == null || c.isEmpty() || availableCipherSuites.contains(c)) { continue; @@ -137,7 +138,12 @@ private final OpenSSLState state; private final Cleanable cleanable; - private enum Accepted { NOT, IMPLICIT, EXPLICIT } + private enum Accepted { + NOT, + IMPLICIT, + EXPLICIT + } + private Accepted accepted = Accepted.NOT; private boolean handshakeFinished; private int currentHandshake; @@ -145,7 +151,8 @@ private volatile boolean destroyed; // Use an invalid cipherSuite until the handshake is completed - // See https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/net/Socket.html#setPerformancePreferences(int,int,int) + // See + // https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/net/Socket.html#setPerformancePreferences(int,int,int) private volatile String version; private volatile String cipher; private volatile String applicationProtocol; @@ -176,25 +183,20 @@ /** * Creates a new instance * - * @param cleaner Used to clean up references to instances before they are - * garbage collected - * @param sslCtx an OpenSSL {@code SSL_CTX} object - * @param fallbackApplicationProtocol the fallback application protocol - * @param clientMode {@code true} if this is used for clients, {@code false} - * otherwise - * @param sessionContext the {@link OpenSSLSessionContext} this - * {@link SSLEngine} belongs to. - * @param alpn {@code true} if alpn should be used, {@code false} - * otherwise - * @param initialized {@code true} if this instance gets its protocol, - * cipher and client verification from the {@code SSL_CTX} {@code sslCtx} - * @param certificateVerificationDepth Certificate verification depth - * @param certificateVerificationOptionalNoCA Skip CA verification in - * optional mode + * @param cleaner Used to clean up references to instances before they are garbage + * collected + * @param sslCtx an OpenSSL {@code SSL_CTX} object + * @param fallbackApplicationProtocol the fallback application protocol + * @param clientMode {@code true} if this is used for clients, {@code false} otherwise + * @param sessionContext the {@link OpenSSLSessionContext} this {@link SSLEngine} belongs to. + * @param alpn {@code true} if alpn should be used, {@code false} otherwise + * @param initialized {@code true} if this instance gets its protocol, cipher and client + * verification from the {@code SSL_CTX} {@code sslCtx} + * @param certificateVerificationDepth Certificate verification depth + * @param certificateVerificationOptionalNoCA Skip CA verification in optional mode */ - OpenSSLEngine(Cleaner cleaner, long sslCtx, String fallbackApplicationProtocol, - boolean clientMode, OpenSSLSessionContext sessionContext, boolean alpn, - boolean initialized, int certificateVerificationDepth, + OpenSSLEngine(Cleaner cleaner, long sslCtx, String fallbackApplicationProtocol, boolean clientMode, + OpenSSLSessionContext sessionContext, boolean alpn, boolean initialized, int certificateVerificationDepth, boolean certificateVerificationOptionalNoCA) { if (sslCtx == 0) { throw new IllegalArgumentException(sm.getString("engine.noSSLContext")); @@ -224,15 +226,15 @@ public synchronized void shutdown() { if (!destroyed) { destroyed = true; - cleanable.clean(); // internal errors can cause shutdown without marking the engine closed isInboundDone = isOutboundDone = engineClosed = true; + cleanable.clean(); } } /** - * Write plain text data to the OpenSSL internal BIO - * Calling this function with src.remaining == 0 is undefined. + * Write plain text data to the OpenSSL internal BIO Calling this function with src.remaining == 0 is undefined. + * * @throws SSLException if the OpenSSL error check fails */ private int writePlaintextData(final long ssl, final ByteBuffer src) throws SSLException { @@ -278,12 +280,12 @@ } } - throw new IllegalStateException( - sm.getString("engine.writeToSSLFailed", Integer.toString(sslWrote))); + throw new IllegalStateException(sm.getString("engine.writeToSSLFailed", Integer.toString(sslWrote))); } /** * Write encrypted data to the OpenSSL network BIO. + * * @throws SSLException if the OpenSSL error check fails */ private int writeEncryptedData(final long networkBIO, final ByteBuffer src) throws SSLException { @@ -328,6 +330,7 @@ /** * Read plain text data from the OpenSSL internal BIO + * * @throws SSLException if the OpenSSL error check fails */ private int readPlaintextData(final long ssl, final ByteBuffer dst) throws SSLException { @@ -372,6 +375,7 @@ /** * Read encrypted data from the OpenSSL network BIO + * * @throws SSLException if the OpenSSL error check fails */ private int readEncryptedData(final long networkBIO, final ByteBuffer dst, final int pending) throws SSLException { @@ -412,11 +416,13 @@ } @Override - public synchronized SSLEngineResult wrap(final ByteBuffer[] srcs, final int offset, final int length, final ByteBuffer dst) throws SSLException { + public synchronized SSLEngineResult wrap(final ByteBuffer[] srcs, final int offset, final int length, + final ByteBuffer dst) throws SSLException { // Check to make sure the engine has not been closed if (destroyed) { - return new SSLEngineResult(SSLEngineResult.Status.CLOSED, SSLEngineResult.HandshakeStatus.NOT_HANDSHAKING, 0, 0); + return new SSLEngineResult(SSLEngineResult.Status.CLOSED, SSLEngineResult.HandshakeStatus.NOT_HANDSHAKING, + 0, 0); } // Throw required runtime exceptions @@ -424,9 +430,8 @@ throw new IllegalArgumentException(sm.getString("engine.nullBuffer")); } if (offset >= srcs.length || offset + length > srcs.length) { - throw new IndexOutOfBoundsException(sm.getString("engine.invalidBufferArray", - Integer.toString(offset), Integer.toString(length), - Integer.toString(srcs.length))); + throw new IndexOutOfBoundsException(sm.getString("engine.invalidBufferArray", Integer.toString(offset), + Integer.toString(length), Integer.toString(srcs.length))); } if (dst.isReadOnly()) { throw new ReadOnlyBufferException(); @@ -497,8 +502,8 @@ // Do we have enough room in dst to write encrypted data? int capacity = dst.remaining(); if (capacity < pendingNet) { - return new SSLEngineResult( - SSLEngineResult.Status.BUFFER_OVERFLOW, getHandshakeStatus(), bytesConsumed, bytesProduced); + return new SSLEngineResult(SSLEngineResult.Status.BUFFER_OVERFLOW, getHandshakeStatus(), + bytesConsumed, bytesProduced); } // Write the pending data from the network BIO into the dst buffer @@ -516,10 +521,12 @@ } @Override - public synchronized SSLEngineResult unwrap(final ByteBuffer src, final ByteBuffer[] dsts, final int offset, final int length) throws SSLException { + public synchronized SSLEngineResult unwrap(final ByteBuffer src, final ByteBuffer[] dsts, final int offset, + final int length) throws SSLException { // Check to make sure the engine has not been closed if (destroyed) { - return new SSLEngineResult(SSLEngineResult.Status.CLOSED, SSLEngineResult.HandshakeStatus.NOT_HANDSHAKING, 0, 0); + return new SSLEngineResult(SSLEngineResult.Status.CLOSED, SSLEngineResult.HandshakeStatus.NOT_HANDSHAKING, + 0, 0); } // Throw required runtime exceptions @@ -527,9 +534,8 @@ throw new IllegalArgumentException(sm.getString("engine.nullBuffer")); } if (offset >= dsts.length || offset + length > dsts.length) { - throw new IndexOutOfBoundsException(sm.getString("engine.invalidBufferArray", - Integer.toString(offset), Integer.toString(length), - Integer.toString(dsts.length))); + throw new IndexOutOfBoundsException(sm.getString("engine.invalidBufferArray", Integer.toString(offset), + Integer.toString(length), Integer.toString(dsts.length))); } int capacity = 0; final int endOffset = offset + length; @@ -633,7 +639,8 @@ } // Check to see if we received a close_notify message from the peer - if (!receivedShutdown && (SSL.getShutdown(state.ssl) & SSL.SSL_RECEIVED_SHUTDOWN) == SSL.SSL_RECEIVED_SHUTDOWN) { + if (!receivedShutdown && + (SSL.getShutdown(state.ssl) & SSL.SSL_RECEIVED_SHUTDOWN) == SSL.SSL_RECEIVED_SHUTDOWN) { receivedShutdown = true; closeInbound(); } @@ -644,8 +651,7 @@ } } - private int pendingReadableBytesInSSL() - throws SSLException { + private int pendingReadableBytesInSSL() throws SSLException { // NOTE: Calling a fake read is necessary before calling pendingReadableBytesInSSL because // SSL_pending will return 0 if OpenSSL has not started the current TLS record // See https://www.openssl.org/docs/manmaster/man3/SSL_pending.html @@ -661,8 +667,7 @@ // TLS 1.0 needs additional handling // TODO Figure out why this is necessary and if a simpler / better // solution is available - if (Constants.SSL_PROTO_TLSv1.equals(version) && lastPrimingReadResult == 0 && - pendingReadableBytesInSSL == 0) { + if (Constants.SSL_PROTO_TLSv1.equals(version) && lastPrimingReadResult == 0 && pendingReadableBytesInSSL == 0) { // Perform another priming read lastPrimingReadResult = SSL.readFromSSL(state.ssl, EMPTY_ADDR, 0); if (lastPrimingReadResult <= 0) { @@ -890,22 +895,23 @@ throw new SSLException(sm.getString("engine.engineClosed")); } switch (accepted) { - case NOT: - handshake(); - accepted = Accepted.EXPLICIT; - break; - case IMPLICIT: - // A user did not start handshake by calling this method by themselves, - // but handshake has been started already by wrap() or unwrap() implicitly. - // Because it's the user's first time to call this method, it is unfair to - // raise an exception. From the user's standpoint, they never asked for - // renegotiation. - - accepted = Accepted.EXPLICIT; // Next time this method is invoked by the user, we should raise an exception. - break; - case EXPLICIT: - renegotiate(); - break; + case NOT: + handshake(); + accepted = Accepted.EXPLICIT; + break; + case IMPLICIT: + // A user did not start handshake by calling this method by themselves, + // but handshake has been started already by wrap() or unwrap() implicitly. + // Because it's the user's first time to call this method, it is unfair to + // raise an exception. From the user's standpoint, they never asked for + // renegotiation. + + accepted = Accepted.EXPLICIT; // Next time this method is invoked by the user, we should raise an + // exception. + break; + case EXPLICIT: + renegotiate(); + break; } } @@ -973,12 +979,11 @@ } /** - * Many calls to SSL methods do not check the last error. Those that do - * check the last error need to ensure that any previously ignored error is - * cleared prior to the method call else errors may be falsely reported. - * Ideally, before any SSL_read, SSL_write, clearLastError should always - * be called, and getLastError should be called after on any negative or - * zero result. + * Many calls to SSL methods do not check the last error. Those that do check the last error need to ensure that any + * previously ignored error is cleared prior to the method call else errors may be falsely reported. Ideally, before + * any SSL_read, SSL_write, clearLastError should always be called, and getLastError should be called after on any + * negative or zero result. + * * @return the first error in the stack */ private static String getLastError() { @@ -1021,34 +1026,24 @@ } /* - * Tomcat Native stores a count of the completed handshakes in the - * SSL instance and increments it every time a handshake is - * completed. Comparing the handshake count when the handshake - * started to the current handshake count enables this code to - * detect when the handshake has completed. + * Tomcat Native stores a count of the completed handshakes in the SSL instance and increments it every time + * a handshake is completed. Comparing the handshake count when the handshake started to the current + * handshake count enables this code to detect when the handshake has completed. * - * Obtaining client certificates after the connection has been - * established requires additional checks. We need to trigger - * additional reads until the certificates have been read, but we - * don't know how many reads we will need as it depends on both - * client and network behaviour. + * Obtaining client certificates after the connection has been established requires additional checks. We + * need to trigger additional reads until the certificates have been read, but we don't know how many reads + * we will need as it depends on both client and network behaviour. * - * The additional reads are triggered by returning NEED_UNWRAP - * rather than FINISHED. This allows the standard I/O code to be - * used. + * The additional reads are triggered by returning NEED_UNWRAP rather than FINISHED. This allows the + * standard I/O code to be used. * - * For TLSv1.2 and below, the handshake completes before the - * renegotiation. We therefore use SSL.renegotiatePending() to - * check on the current status of the renegotiation and return - * NEED_UNWRAP until it completes which means the client - * certificates will have been read from the client. + * For TLSv1.2 and below, the handshake completes before the renegotiation. We therefore use + * SSL.renegotiatePending() to check on the current status of the renegotiation and return NEED_UNWRAP until + * it completes which means the client certificates will have been read from the client. * - * For TLSv1.3, Tomcat Native sets a flag when post handshake - * authentication is started and updates it once the client - * certificate has been received. We therefore use - * SSL.getPostHandshakeAuthInProgress() to check the current status - * and return NEED_UNWRAP until that methods indicates that PHA is - * no longer in progress. + * For TLSv1.3, Tomcat Native sets a flag when post handshake authentication is started and updates it once + * the client certificate has been received. We therefore use SSL.getPostHandshakeAuthInProgress() to check + * the current status and return NEED_UNWRAP until that methods indicates that PHA is no longer in progress. */ // No pending data to be sent to the peer @@ -1136,9 +1131,8 @@ SSL.setVerify(state.ssl, SSL.SSL_CVERIFY_REQUIRE, certificateVerificationDepth); break; case OPTIONAL: - SSL.setVerify(state.ssl, - certificateVerificationOptionalNoCA ? SSL.SSL_CVERIFY_OPTIONAL_NO_CA : SSL.SSL_CVERIFY_OPTIONAL, - certificateVerificationDepth); + SSL.setVerify(state.ssl, certificateVerificationOptionalNoCA ? SSL.SSL_CVERIFY_OPTIONAL_NO_CA : + SSL.SSL_CVERIFY_OPTIONAL, certificateVerificationDepth); break; } clientAuth = mode; @@ -1162,7 +1156,7 @@ private class OpenSSLSession implements SSLSession { // lazy init for memory reasons - private Map values; + private Map values; // Last accessed time private long lastAccessedTime = -1; @@ -1219,7 +1213,7 @@ if (value == null) { throw new IllegalArgumentException(sm.getString("engine.nullValue")); } - Map values = this.values; + Map values = this.values; if (values == null) { // Use size of 2 to keep the memory overhead small values = this.values = new HashMap<>(2); @@ -1247,7 +1241,7 @@ if (name == null) { throw new IllegalArgumentException(sm.getString("engine.nullName")); } - Map values = this.values; + Map values = this.values; if (values == null) { return; } @@ -1257,7 +1251,7 @@ @Override public String[] getValueNames() { - Map values = this.values; + Map values = this.values; if (values == null || values.isEmpty()) { return new String[0]; } @@ -1283,7 +1277,8 @@ } chain = SSL.getPeerCertChain(state.ssl); if (!clientMode) { - // if used on the server side SSL_get_peer_cert_chain(...) will not include the remote peer certificate. + // if used on the server side SSL_get_peer_cert_chain(...) will not include the remote peer + // certificate. // We use SSL_get_peer_certificate to get it in this case and add it to our array later. // // See https://www.openssl.org/docs/ssl/SSL_get_peer_cert_chain.html @@ -1328,8 +1323,7 @@ @Deprecated @Override - public javax.security.cert.X509Certificate[] getPeerCertificateChain() - throws SSLPeerUnverifiedException { + public javax.security.cert.X509Certificate[] getPeerCertificateChain() throws SSLPeerUnverifiedException { // these are lazy created to reduce memory overhead javax.security.cert.X509Certificate[] c = x509PeerCerts; if (c == null) { @@ -1343,8 +1337,7 @@ if (chain == null) { throw new SSLPeerUnverifiedException(sm.getString("engine.unverifiedPeer")); } - javax.security.cert.X509Certificate[] peerCerts = - new javax.security.cert.X509Certificate[chain.length]; + javax.security.cert.X509Certificate[] peerCerts = new javax.security.cert.X509Certificate[chain.length]; for (int i = 0; i < peerCerts.length; i++) { try { peerCerts[i] = javax.security.cert.X509Certificate.getInstance(chain[i]); @@ -1376,7 +1369,7 @@ } private Principal principal(Certificate[] certs) { - return ((java.security.cert.X509Certificate) certs[0]).getIssuerX500Principal(); + return ((java.security.cert.X509Certificate) certs[0]).getSubjectX500Principal(); } @Override @@ -1461,11 +1454,19 @@ @Override public void run() { - if (networkBIO != 0) { - SSL.freeBIO(networkBIO); - } - if (ssl != 0) { - SSL.freeSSL(ssl); + Lock readLock = AprStatus.getStatusLock().readLock(); + readLock.lock(); + try { + if (AprStatus.isAprInitialized()) { + if (networkBIO != 0) { + SSL.freeBIO(networkBIO); + } + if (ssl != 0) { + SSL.freeSSL(ssl); + } + } + } finally { + readLock.unlock(); } } } diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/net/openssl/OpenSSLImplementation.java tomcat10-10.1.52/java/org/apache/tomcat/util/net/openssl/OpenSSLImplementation.java --- tomcat10-10.1.40/java/org/apache/tomcat/util/net/openssl/OpenSSLImplementation.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/net/openssl/OpenSSLImplementation.java 2026-01-23 19:33:36.000000000 +0000 @@ -30,7 +30,7 @@ public class OpenSSLImplementation extends SSLImplementation { @Override - public SSLSupport getSSLSupport(SSLSession session, Map> additionalAttributes) { + public SSLSupport getSSLSupport(SSLSession session, Map> additionalAttributes) { return new JSSESupport(session, additionalAttributes); } diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/net/openssl/OpenSSLSessionContext.java tomcat10-10.1.52/java/org/apache/tomcat/util/net/openssl/OpenSSLSessionContext.java --- tomcat10-10.1.40/java/org/apache/tomcat/util/net/openssl/OpenSSLSessionContext.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/net/openssl/OpenSSLSessionContext.java 2026-01-23 19:33:36.000000000 +0000 @@ -81,8 +81,7 @@ } /** - * @return {@code true} if caching of SSL sessions is enabled, {@code false} - * otherwise. + * @return {@code true} if caching of SSL sessions is enabled, {@code false} otherwise. */ public boolean isSessionCacheEnabled() { return SSLContext.getSessionCacheMode(contextID) == SSL.SSL_SESS_CACHE_SERVER; @@ -122,12 +121,13 @@ } /** - * Set the context within which session be reused (server side only) - * See - * man SSL_CTX_set_session_id_context + * Set the context within which session be reused (server side only) See + * man + * SSL_CTX_set_session_id_context + * + * @param sidCtx can be any kind of binary data, it is therefore possible to use e.g. the name of the application + * and/or the hostname and/or service name * - * @param sidCtx can be any kind of binary data, it is therefore possible to use e.g. the name - * of the application and/or the hostname and/or service name * @return {@code true} if success, {@code false} otherwise. */ public boolean setSessionIdContext(byte[] sidCtx) { diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/net/openssl/OpenSSLSessionStats.java tomcat10-10.1.52/java/org/apache/tomcat/util/net/openssl/OpenSSLSessionStats.java --- tomcat10-10.1.40/java/org/apache/tomcat/util/net/openssl/OpenSSLSessionStats.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/net/openssl/OpenSSLSessionStats.java 2026-01-23 19:33:36.000000000 +0000 @@ -81,44 +81,40 @@ } /** - * @return The number of successfully reused sessions. In client mode, a - * session set with {@code SSL_set_session} successfully reused is - * counted as a hit. In server mode, a session successfully - * retrieved from internal or external cache is counted as a hit. + * @return The number of successfully reused sessions. In client mode, a session set with {@code SSL_set_session} + * successfully reused is counted as a hit. In server mode, a session successfully retrieved from + * internal or external cache is counted as a hit. */ public long hits() { return SSLContext.sessionHits(context); } /** - * @return The number of successfully retrieved sessions from the external - * session cache in server mode. + * @return The number of successfully retrieved sessions from the external session cache in server mode. */ public long cbHits() { return SSLContext.sessionCbHits(context); } /** - * @return The number of sessions proposed by clients that were not found in - * the internal session cache in server mode. + * @return The number of sessions proposed by clients that were not found in the internal session cache in server + * mode. */ public long misses() { return SSLContext.sessionMisses(context); } /** - * @return The number of sessions proposed by clients and either found in - * the internal or external session cache in server mode, but that - * were invalid due to timeout. These sessions are not included in - * the {@link #hits()} count. + * @return The number of sessions proposed by clients and either found in the internal or external session cache in + * server mode, but that were invalid due to timeout. These sessions are not included in the + * {@link #hits()} count. */ public long timeouts() { return SSLContext.sessionTimeouts(context); } /** - * @return The number of sessions that were removed because the maximum - * session cache size was exceeded. + * @return The number of sessions that were removed because the maximum session cache size was exceeded. */ public long cacheFull() { return SSLContext.sessionCacheFull(context); diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/net/openssl/OpenSSLStatus.java tomcat10-10.1.52/java/org/apache/tomcat/util/net/openssl/OpenSSLStatus.java --- tomcat10-10.1.40/java/org/apache/tomcat/util/net/openssl/OpenSSLStatus.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/net/openssl/OpenSSLStatus.java 2026-01-23 19:33:36.000000000 +0000 @@ -25,7 +25,11 @@ * OpenSSL library variant that has been identified */ public enum Name { - OPENSSL, OPENSSL3, LIBRESSL, BORINGSSL, UNKNOWN + OPENSSL, + OPENSSL3, + LIBRESSL, + BORINGSSL, + UNKNOWN } private static volatile boolean libraryInitialized = false; @@ -34,9 +38,10 @@ private static volatile boolean useOpenSSL = true; private static volatile boolean instanceCreated = false; private static volatile long version = 0; + private static volatile int majorVersion = 0; + private static volatile int minorVersion = 0; private static volatile Name name = Name.UNKNOWN; - public static boolean isLibraryInitialized() { return libraryInitialized; } @@ -92,6 +97,34 @@ } /** + * @return the majorVersion + */ + public static int getMajorVersion() { + return majorVersion; + } + + /** + * @param majorVersion the majorVersion to set + */ + public static void setMajorVersion(int majorVersion) { + OpenSSLStatus.majorVersion = majorVersion; + } + + /** + * @return the minorVersion + */ + public static int getMinorVersion() { + return minorVersion; + } + + /** + * @param minorVersion the minorVersion to set + */ + public static void setMinorVersion(int minorVersion) { + OpenSSLStatus.minorVersion = minorVersion; + } + + /** * @return the library name */ public static Name getName() { @@ -112,4 +145,18 @@ return Name.OPENSSL3.equals(name); } + /** + * @return true if running with BoringSSL + */ + public static boolean isBoringSSL() { + return Name.BORINGSSL.equals(name); + } + + /** + * @return true if running with LibreSSL < 3.5 + */ + public static boolean isLibreSSLPre35() { + return Name.LIBRESSL.equals(name) && ((majorVersion == 3 && minorVersion < 5) || majorVersion < 3); + } + } diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/net/openssl/OpenSSLUtil.java tomcat10-10.1.52/java/org/apache/tomcat/util/net/openssl/OpenSSLUtil.java --- tomcat10-10.1.40/java/org/apache/tomcat/util/net/openssl/OpenSSLUtil.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/net/openssl/OpenSSLUtil.java 2026-01-23 19:33:36.000000000 +0000 @@ -17,6 +17,7 @@ package org.apache.tomcat.util.net.openssl; import java.io.IOException; +import java.security.KeyException; import java.security.KeyStoreException; import java.util.List; import java.util.Set; @@ -110,20 +111,20 @@ // No (or invalid?) certificate chain was provided for the cert String msg = sm.getString("openssl.nonJsseChain", certificate.getCertificateChainFile()); if (log.isDebugEnabled()) { - log.info(msg, e); + log.debug(msg, e); } else { log.info(msg); } return null; - } catch (KeyStoreException | IOException e) { + } catch (KeyStoreException | KeyException | IOException e) { // Depending on what is presented, JSSE may also throw // KeyStoreException or IOException if it doesn't understand the // provided file. if (certificate.getCertificateFile() != null) { - String msg = sm.getString("openssl.nonJsseCertificate", - certificate.getCertificateFile(), certificate.getCertificateKeyFile()); + String msg = sm.getString("openssl.nonJsseCertificate", certificate.getCertificateFile(), + certificate.getCertificateKeyFile()); if (log.isDebugEnabled()) { - log.info(msg, e); + log.debug(msg, e); } else { log.info(msg); } diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/net/openssl/OpenSSLX509Certificate.java tomcat10-10.1.52/java/org/apache/tomcat/util/net/openssl/OpenSSLX509Certificate.java --- tomcat10-10.1.40/java/org/apache/tomcat/util/net/openssl/OpenSSLX509Certificate.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/net/openssl/OpenSSLX509Certificate.java 2026-01-23 19:33:36.000000000 +0000 @@ -134,16 +134,14 @@ } @Override - public void verify(PublicKey key) - throws CertificateException, NoSuchAlgorithmException, - InvalidKeyException, NoSuchProviderException, SignatureException { + public void verify(PublicKey key) throws CertificateException, NoSuchAlgorithmException, InvalidKeyException, + NoSuchProviderException, SignatureException { unwrap().verify(key); } @Override - public void verify(PublicKey key, String sigProvider) - throws CertificateException, NoSuchAlgorithmException, InvalidKeyException, - NoSuchProviderException, SignatureException { + public void verify(PublicKey key, String sigProvider) throws CertificateException, NoSuchAlgorithmException, + InvalidKeyException, NoSuchProviderException, SignatureException { unwrap().verify(key, sigProvider); } @@ -181,8 +179,8 @@ X509Certificate wrapped = this.wrapped; if (wrapped == null) { try { - wrapped = this.wrapped = (X509Certificate) OpenSSLContext.X509_CERT_FACTORY.generateCertificate( - new ByteArrayInputStream(bytes)); + wrapped = this.wrapped = (X509Certificate) OpenSSLContext.X509_CERT_FACTORY + .generateCertificate(new ByteArrayInputStream(bytes)); } catch (CertificateException e) { throw new IllegalStateException(e); } diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/net/openssl/ciphers/Authentication.java tomcat10-10.1.52/java/org/apache/tomcat/util/net/openssl/ciphers/Authentication.java --- tomcat10-10.1.40/java/org/apache/tomcat/util/net/openssl/ciphers/Authentication.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/net/openssl/ciphers/Authentication.java 2026-01-23 19:33:36.000000000 +0000 @@ -17,17 +17,19 @@ package org.apache.tomcat.util.net.openssl.ciphers; public enum Authentication { - RSA /* RSA auth */, - DSS /* DSS auth */, - aNULL /* no auth (i.e. use ADH or AECDH) */, - DH /* Fixed DH auth (kDHd or kDHr) */, - ECDH /* Fixed ECDH auth (kECDHe or kECDHr) */, - KRB5 /* KRB5 auth */, - ECDSA /* ECDSA auth*/, - PSK /* PSK auth */, + RSA /* RSA auth */, + DSS /* DSS auth */, + aNULL /* no auth (i.e. use ADH or AECDH) */, + DH /* Fixed DH auth (kDHd or kDHr) */, + ECDH /* Fixed ECDH auth (kECDHe or kECDHr) */, + KRB5 /* KRB5 auth */, + ECDSA /* ECDSA auth */, + PSK /* PSK auth */, GOST94 /* GOST R 34.10-94 signature auth */, GOST01 /* GOST R 34.10-2001 */, - FZA /* Fortezza */, - SRP /* Secure Remote Password */, - ANY /* TLS 1.3 */ + FZA /* Fortezza */, + SRP /* Secure Remote Password */, + EdDSA /* EdDSA */, + MLDSA /* ML-DSA */, + ANY /* TLS 1.3 */ } diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/net/openssl/ciphers/Cipher.java tomcat10-10.1.52/java/org/apache/tomcat/util/net/openssl/ciphers/Cipher.java --- tomcat10-10.1.40/java/org/apache/tomcat/util/net/openssl/ciphers/Cipher.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/net/openssl/ciphers/Cipher.java 2026-01-23 19:33:36.000000000 +0000 @@ -27,23 +27,23 @@ /** * All the standard cipher suites for SSL/TSL. * - * @see OpenSSL cipher definitions - * @see The cipher suite registry - * @see Another list of cipher suites with some non-standard IDs - * @see Oracle standard names for cipher suites - * @see Mapping of OpenSSL cipher suites names to registry names - * @see SSL Labs tool - list of ciphers - * @see OpenJDK source code + * @see OpenSSL cipher definitions + * @see The cipher suite + * registry + * @see Another list of cipher suites with some + * non-standard IDs + * @see Oracle + * standard names for cipher suites + * @see Mapping of OpenSSL cipher suites names to registry + * names + * @see SSL Labs tool - list of ciphers + * @see OpenJDK source code */ public enum Cipher { + // @formatter:off /* Cipher 0 * TLS_NULL_WITH_NULL_NULL * Must never be negotiated. Used internally to represent the initial @@ -4988,7 +4988,7 @@ 256, 256 },*/ - + // @formatter:on private final int id; private final String openSSLAlias; @@ -5011,10 +5011,9 @@ */ private final int alg_bits; - Cipher(int id, String openSSLAlias, KeyExchange kx, Authentication au, Encryption enc, - MessageDigest mac, Protocol protocol, boolean export, EncryptionLevel level, - boolean fipsCompatible, int strength_bits, int alg_bits, String[] jsseAltNames, - String[] openSSlAltNames) { + Cipher(int id, String openSSLAlias, KeyExchange kx, Authentication au, Encryption enc, MessageDigest mac, + Protocol protocol, boolean export, EncryptionLevel level, boolean fipsCompatible, int strength_bits, + int alg_bits, String[] jsseAltNames, String[] openSSlAltNames) { this.id = id; this.openSSLAlias = openSSLAlias; if (openSSlAltNames != null && openSSlAltNames.length != 0) { diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/net/openssl/ciphers/Group.java tomcat10-10.1.52/java/org/apache/tomcat/util/net/openssl/ciphers/Group.java --- tomcat10-10.1.40/java/org/apache/tomcat/util/net/openssl/ciphers/Group.java 1970-01-01 00:00:00.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/net/openssl/ciphers/Group.java 2026-01-23 19:33:36.000000000 +0000 @@ -0,0 +1,82 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.tomcat.util.net.openssl.ciphers; + +import java.util.HashMap; +import java.util.Map; + +/** + * All the supported named groups for TLS 1.3. + * @see The supported groups + * registry + */ +public enum Group { + + // Elliptic Curve Groups (ECDHE) + secp256r1(0x0017), + secp384r1(0x0018), + secp521r1(0x0019), + x25519(0x001D), + x448(0x001E), + + // Finite Field Groups (DHE) + ffdhe2048(0x0100), + ffdhe3072(0x0101), + ffdhe4096(0x0102), + ffdhe6144(0x0103), + ffdhe8192(0x0104), + + // Post-Quantum Key Exchange + MLKEM512(0x0200), + MLKEM768(0x0201), + MLKEM1024(0x0202), + + // Hybrid Key Exchange + SecP256r1MLKEM768(0x11EB), + X25519MLKEM768(0x11EC), + SecP384r1MLKEM1024(0x11ED); + + private final int id; + + Group(int id) { + this.id = id; + } + + /** + * @return the id + */ + public int getId() { + return this.id; + } + + private static final Map idMap = new HashMap<>(); + + static { + for (Group group : values()) { + int id = group.getId(); + + if (id > 0 && id < 0xFFFF) { + idMap.put(Integer.valueOf(id), group); + } + } + } + + + public static Group valueOf(int groupId) { + return idMap.get(Integer.valueOf(groupId)); + } +} diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/net/openssl/ciphers/KeyExchange.java tomcat10-10.1.52/java/org/apache/tomcat/util/net/openssl/ciphers/KeyExchange.java --- tomcat10-10.1.40/java/org/apache/tomcat/util/net/openssl/ciphers/KeyExchange.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/net/openssl/ciphers/KeyExchange.java 2026-01-23 19:33:36.000000000 +0000 @@ -18,19 +18,19 @@ public enum KeyExchange { EECDH /* SSL_kEECDH - ephemeral ECDH */, - RSA /* SSL_kRSA - RSA key exchange */, - DHr /* SSL_kDHr - DH cert, RSA CA cert */ /* no such cipher suites supported */, - DHd /* SSL_kDHd - DH cert, DSA CA cert */ /* no such cipher suite supported */, - EDH /* SSL_kDHE - tmp DH key no DH cert */, - PSK /* SSK_kPSK - PSK */, - FZA /* SSL_kFZA - Fortezza */ /* no such cipher suite supported */, - KRB5 /* SSL_kKRB5 - Kerberos 5 key exchange */, + RSA /* SSL_kRSA - RSA key exchange */, + DHr /* SSL_kDHr - DH cert, RSA CA cert */ /* no such cipher suites supported */, + DHd /* SSL_kDHd - DH cert, DSA CA cert */ /* no such cipher suite supported */, + EDH /* SSL_kDHE - tmp DH key no DH cert */, + PSK /* SSK_kPSK - PSK */, + FZA /* SSL_kFZA - Fortezza */ /* no such cipher suite supported */, + KRB5 /* SSL_kKRB5 - Kerberos 5 key exchange */, ECDHr /* SSL_kECDHr - ECDH cert, RSA CA cert */, ECDHe /* SSL_kECDHe - ECDH cert, ECDSA CA cert */, - GOST /* SSL_kGOST - GOST key exchange */, - SRP /* SSL_kSRP - SRP */, + GOST /* SSL_kGOST - GOST key exchange */, + SRP /* SSL_kSRP - SRP */, RSAPSK, ECDHEPSK, DHEPSK, - ANY /* TLS 1.3 */ + ANY /* TLS 1.3 */ } diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/net/openssl/ciphers/OpenSSLCipherConfigurationParser.java tomcat10-10.1.52/java/org/apache/tomcat/util/net/openssl/ciphers/OpenSSLCipherConfigurationParser.java --- tomcat10-10.1.40/java/org/apache/tomcat/util/net/openssl/ciphers/OpenSSLCipherConfigurationParser.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/net/openssl/ciphers/OpenSSLCipherConfigurationParser.java 2026-01-23 19:33:36.000000000 +0000 @@ -48,45 +48,46 @@ private static final String SEPARATOR = ":|,| "; /** - * If ! is used then the ciphers are permanently deleted from the list. The ciphers deleted can never reappear in the list - * even if they are explicitly stated. + * If ! is used then the ciphers are permanently deleted from the list. The ciphers deleted can never reappear in + * the list even if they are explicitly stated. */ private static final String EXCLUDE = "!"; /** - * If - is used then the ciphers are deleted from the list, but some or all of the ciphers can be added again by later - * options. + * If - is used then the ciphers are deleted from the list, but some or all of the ciphers can be added again by + * later options. */ private static final String DELETE = "-"; /** - * If + is used then the ciphers are moved to the end of the list. This option doesn't add any new ciphers it just moves - * matching existing ones. + * If + is used then the ciphers are moved to the end of the list. This option doesn't add any new ciphers it just + * moves matching existing ones. */ private static final String TO_END = "+"; - /** - * Lists of cipher suites can be combined in a single cipher string using the + character. - * This is used as a logical and operation. - * For example SHA1+DES represents all cipher suites containing the SHA1 and the DES algorithms. + /** + * Lists of cipher suites can be combined in a single cipher string using the + character. This is used as a logical + * and operation. For example SHA1+DES represents all cipher suites containing the SHA1 and the DES algorithms. */ private static final String AND = "+"; /** * All ciphers by their openssl alias name. */ - private static final Map> aliases = new LinkedHashMap<>(); + private static final Map> aliases = new LinkedHashMap<>(); + + private static final Set tls13CipherSuiteNames = new HashSet<>(); /** - * the 'NULL' ciphers that is those offering no encryption. Because these offer no encryption at all and are a security risk - * they are disabled unless explicitly included. + * the 'NULL' ciphers that is those offering no encryption. Because these offer no encryption at all and are a + * security risk they are disabled unless explicitly included. */ private static final String eNULL = "eNULL"; /** - * The cipher suites offering no authentication. This is currently the anonymous DH algorithms. T These cipher suites are - * vulnerable to a 'man in the middle' attack and so their use is normally discouraged. + * The cipher suites offering no authentication. This is currently the anonymous DH algorithms. T These cipher + * suites are vulnerable to a 'man in the middle' attack and so their use is normally discouraged. */ private static final String aNULL = "aNULL"; /** - * 'high' encryption cipher suites. This currently means those with key lengths larger than 128 bits, and some cipher suites - * with 128-bit keys. + * 'high' encryption cipher suites. This currently means those with key lengths larger than 128 bits, and some + * cipher suites with 128-bit keys. */ private static final String HIGH = "HIGH"; /** @@ -94,8 +95,8 @@ */ private static final String MEDIUM = "MEDIUM"; /** - * 'low' encryption cipher suites, currently those using 64 or 56 bit encryption algorithms but excluding export cipher - * suites. + * 'low' encryption cipher suites, currently those using 64 or 56 bit encryption algorithms but excluding export + * cipher suites. */ private static final String LOW = "LOW"; /** @@ -119,8 +120,7 @@ */ private static final String aRSA = "aRSA"; /** - * Cipher suites using RSA for key exchange - * Despite what the docs say, RSA is equivalent to kRSA. + * Cipher suites using RSA for key exchange Despite what the docs say, RSA is equivalent to kRSA. */ private static final String RSA = "RSA"; /** @@ -168,8 +168,7 @@ */ private static final String kEECDH = "kEECDH"; /** - * Cipher suites using ephemeral ECDH key agreement, excluding anonymous cipher suites. - * Same as "kEECDH:-AECDH" + * Cipher suites using ephemeral ECDH key agreement, excluding anonymous cipher suites. Same as "kEECDH:-AECDH" */ private static final String EECDH = "EECDH"; /** @@ -426,6 +425,16 @@ for (String jsseName : jsseNames) { jsseToOpenSSL.put(jsseName, cipher.getOpenSSLAlias()); } + + if (cipher.getProtocol().equals(Protocol.TLSv1_3)) { + tls13CipherSuiteNames.add(cipher.getOpenSSLAlias()); + /* + * The TLS 1.3 cipher suites do not, currently (January 2026), have any alternative names defined so the + * following two calls are NO-OPs but are implemented in case alternative names are used in the future. + */ + tls13CipherSuiteNames.addAll(cipher.getOpenSSLAltNames()); + tls13CipherSuiteNames.addAll(cipher.getJsseNames()); + } } List allCiphersList = Arrays.asList(Cipher.values()); Collections.reverse(allCiphersList); @@ -437,7 +446,8 @@ addListAlias(HIGH, filterByEncryptionLevel(allCiphers, Collections.singleton(EncryptionLevel.HIGH))); addListAlias(MEDIUM, filterByEncryptionLevel(allCiphers, Collections.singleton(EncryptionLevel.MEDIUM))); addListAlias(LOW, filterByEncryptionLevel(allCiphers, Collections.singleton(EncryptionLevel.LOW))); - addListAlias(EXPORT, filterByEncryptionLevel(allCiphers, new HashSet<>(Arrays.asList(EncryptionLevel.EXP40, EncryptionLevel.EXP56)))); + addListAlias(EXPORT, filterByEncryptionLevel(allCiphers, + new HashSet<>(Arrays.asList(EncryptionLevel.EXP40, EncryptionLevel.EXP56)))); aliases.put("EXP", aliases.get(EXPORT)); addListAlias(EXPORT40, filterByEncryptionLevel(allCiphers, Collections.singleton(EncryptionLevel.EXP40))); addListAlias(EXPORT56, filterByEncryptionLevel(allCiphers, Collections.singleton(EncryptionLevel.EXP56))); @@ -456,12 +466,15 @@ addListAlias(DHE, edh); addListAlias(kDHr, filterByKeyExchange(allCiphers, Collections.singleton(KeyExchange.DHr))); addListAlias(kDHd, filterByKeyExchange(allCiphers, Collections.singleton(KeyExchange.DHd))); - addListAlias(kDH, filterByKeyExchange(allCiphers, new HashSet<>(Arrays.asList(KeyExchange.DHr, KeyExchange.DHd)))); + addListAlias(kDH, + filterByKeyExchange(allCiphers, new HashSet<>(Arrays.asList(KeyExchange.DHr, KeyExchange.DHd)))); addListAlias(kECDHr, filterByKeyExchange(allCiphers, Collections.singleton(KeyExchange.ECDHr))); addListAlias(kECDHe, filterByKeyExchange(allCiphers, Collections.singleton(KeyExchange.ECDHe))); - addListAlias(kECDH, filterByKeyExchange(allCiphers, new HashSet<>(Arrays.asList(KeyExchange.ECDHe, KeyExchange.ECDHr)))); - addListAlias(ECDH, filterByKeyExchange(allCiphers, new HashSet<>(Arrays.asList(KeyExchange.ECDHe, KeyExchange.ECDHr, KeyExchange.EECDH)))); + addListAlias(kECDH, + filterByKeyExchange(allCiphers, new HashSet<>(Arrays.asList(KeyExchange.ECDHe, KeyExchange.ECDHr)))); + addListAlias(ECDH, filterByKeyExchange(allCiphers, + new HashSet<>(Arrays.asList(KeyExchange.ECDHe, KeyExchange.ECDHr, KeyExchange.EECDH)))); addListAlias(kECDHE, filterByKeyExchange(allCiphers, Collections.singleton(KeyExchange.EECDH))); Set ecdhe = filterByKeyExchange(allCiphers, Collections.singleton(KeyExchange.EECDH)); @@ -483,26 +496,40 @@ addListAlias(kFZA, filterByKeyExchange(allCiphers, Collections.singleton(KeyExchange.FZA))); addListAlias(aFZA, filterByAuthentication(allCiphers, Collections.singleton(Authentication.FZA))); addListAlias(eFZA, filterByEncryption(allCiphers, Collections.singleton(Encryption.FZA))); - addListAlias(FZA, filter(allCiphers, null, Collections.singleton(KeyExchange.FZA), Collections.singleton(Authentication.FZA), Collections.singleton(Encryption.FZA), null, null)); - addListAlias(Constants.SSL_PROTO_TLSv1_2, filterByProtocol(allCiphers, Collections.singleton(Protocol.TLSv1_2))); + addListAlias(FZA, filter(allCiphers, null, Collections.singleton(KeyExchange.FZA), + Collections.singleton(Authentication.FZA), Collections.singleton(Encryption.FZA), null, null)); + addListAlias(Constants.SSL_PROTO_TLSv1_2, + filterByProtocol(allCiphers, Collections.singleton(Protocol.TLSv1_2))); addListAlias(Constants.SSL_PROTO_TLSv1_0, filterByProtocol(allCiphers, Collections.singleton(Protocol.TLSv1))); addListAlias(Constants.SSL_PROTO_SSLv3, filterByProtocol(allCiphers, Collections.singleton(Protocol.SSLv3))); aliases.put(Constants.SSL_PROTO_TLSv1, aliases.get(Constants.SSL_PROTO_TLSv1_0)); addListAlias(Constants.SSL_PROTO_SSLv2, filterByProtocol(allCiphers, Collections.singleton(Protocol.SSLv2))); - addListAlias(DH, filterByKeyExchange(allCiphers, new HashSet<>(Arrays.asList(KeyExchange.DHr, KeyExchange.DHd, KeyExchange.EDH)))); + addListAlias(DH, filterByKeyExchange(allCiphers, + new HashSet<>(Arrays.asList(KeyExchange.DHr, KeyExchange.DHd, KeyExchange.EDH)))); Set adh = filterByKeyExchange(allCiphers, Collections.singleton(KeyExchange.EDH)); adh.retainAll(filterByAuthentication(allCiphers, Collections.singleton(Authentication.aNULL))); addListAlias(ADH, adh); - addListAlias(AES128, filterByEncryption(allCiphers, new HashSet<>(Arrays.asList(Encryption.AES128, Encryption.AES128CCM, Encryption.AES128CCM8, Encryption.AES128GCM)))); - addListAlias(AES256, filterByEncryption(allCiphers, new HashSet<>(Arrays.asList(Encryption.AES256, Encryption.AES256CCM, Encryption.AES256CCM8, Encryption.AES256GCM)))); - addListAlias(AES, filterByEncryption(allCiphers, new HashSet<>(Arrays.asList(Encryption.AES128, Encryption.AES128CCM, Encryption.AES128CCM8, Encryption.AES128GCM, Encryption.AES256, Encryption.AES256CCM, Encryption.AES256CCM8, Encryption.AES256GCM)))); + addListAlias(AES128, filterByEncryption(allCiphers, new HashSet<>( + Arrays.asList(Encryption.AES128, Encryption.AES128CCM, Encryption.AES128CCM8, Encryption.AES128GCM)))); + addListAlias(AES256, filterByEncryption(allCiphers, new HashSet<>( + Arrays.asList(Encryption.AES256, Encryption.AES256CCM, Encryption.AES256CCM8, Encryption.AES256GCM)))); + addListAlias(AES, + filterByEncryption(allCiphers, + new HashSet<>(Arrays.asList(Encryption.AES128, Encryption.AES128CCM, Encryption.AES128CCM8, + Encryption.AES128GCM, Encryption.AES256, Encryption.AES256CCM, Encryption.AES256CCM8, + Encryption.AES256GCM)))); addListAlias(ARIA128, filterByEncryption(allCiphers, Collections.singleton(Encryption.ARIA128GCM))); addListAlias(ARIA256, filterByEncryption(allCiphers, Collections.singleton(Encryption.ARIA256GCM))); - addListAlias(ARIA, filterByEncryption(allCiphers, new HashSet<>(Arrays.asList(Encryption.ARIA128GCM, Encryption.ARIA256GCM)))); - addListAlias(AESGCM, filterByEncryption(allCiphers, new HashSet<>(Arrays.asList(Encryption.AES128GCM, Encryption.AES256GCM)))); - addListAlias(AESCCM, filterByEncryption(allCiphers, new HashSet<>(Arrays.asList(Encryption.AES128CCM, Encryption.AES128CCM8, Encryption.AES256CCM, Encryption.AES256CCM8)))); - addListAlias(AESCCM8, filterByEncryption(allCiphers, new HashSet<>(Arrays.asList(Encryption.AES128CCM8, Encryption.AES256CCM8)))); - addListAlias(CAMELLIA, filterByEncryption(allCiphers, new HashSet<>(Arrays.asList(Encryption.CAMELLIA128, Encryption.CAMELLIA256)))); + addListAlias(ARIA, filterByEncryption(allCiphers, + new HashSet<>(Arrays.asList(Encryption.ARIA128GCM, Encryption.ARIA256GCM)))); + addListAlias(AESGCM, filterByEncryption(allCiphers, + new HashSet<>(Arrays.asList(Encryption.AES128GCM, Encryption.AES256GCM)))); + addListAlias(AESCCM, filterByEncryption(allCiphers, new HashSet<>(Arrays.asList(Encryption.AES128CCM, + Encryption.AES128CCM8, Encryption.AES256CCM, Encryption.AES256CCM8)))); + addListAlias(AESCCM8, filterByEncryption(allCiphers, + new HashSet<>(Arrays.asList(Encryption.AES128CCM8, Encryption.AES256CCM8)))); + addListAlias(CAMELLIA, filterByEncryption(allCiphers, + new HashSet<>(Arrays.asList(Encryption.CAMELLIA128, Encryption.CAMELLIA256)))); addListAlias(CAMELLIA128, filterByEncryption(allCiphers, Collections.singleton(Encryption.CAMELLIA128))); addListAlias(CAMELLIA256, filterByEncryption(allCiphers, Collections.singleton(Encryption.CAMELLIA256))); addListAlias(CHACHA20, filterByEncryption(allCiphers, Collections.singleton(Encryption.CHACHA20POLY1305))); @@ -517,27 +544,34 @@ aliases.put(SHA, aliases.get(SHA1)); addListAlias(SHA256, filterByMessageDigest(allCiphers, Collections.singleton(MessageDigest.SHA256))); addListAlias(SHA384, filterByMessageDigest(allCiphers, Collections.singleton(MessageDigest.SHA384))); - addListAlias(aGOST, filterByAuthentication(allCiphers, new HashSet<>(Arrays.asList(Authentication.GOST01, Authentication.GOST94)))); + addListAlias(aGOST, filterByAuthentication(allCiphers, + new HashSet<>(Arrays.asList(Authentication.GOST01, Authentication.GOST94)))); addListAlias(aGOST01, filterByAuthentication(allCiphers, Collections.singleton(Authentication.GOST01))); addListAlias(aGOST94, filterByAuthentication(allCiphers, Collections.singleton(Authentication.GOST94))); addListAlias(kGOST, filterByKeyExchange(allCiphers, Collections.singleton(KeyExchange.GOST))); addListAlias(GOST94, filterByMessageDigest(allCiphers, Collections.singleton(MessageDigest.GOST94))); addListAlias(GOST89MAC, filterByMessageDigest(allCiphers, Collections.singleton(MessageDigest.GOST89MAC))); - addListAlias(PSK, filter(allCiphers, null, new HashSet<>(Arrays.asList(KeyExchange.PSK, KeyExchange.RSAPSK, KeyExchange.DHEPSK, KeyExchange.ECDHEPSK)), Collections.singleton(Authentication.PSK), null, null, null)); + addListAlias(PSK, + filter(allCiphers, null, new HashSet<>( + Arrays.asList(KeyExchange.PSK, KeyExchange.RSAPSK, KeyExchange.DHEPSK, KeyExchange.ECDHEPSK)), + Collections.singleton(Authentication.PSK), null, null, null)); addListAlias(aPSK, filterByAuthentication(allCiphers, Collections.singleton(Authentication.PSK))); addListAlias(kPSK, filterByKeyExchange(allCiphers, Collections.singleton(KeyExchange.PSK))); addListAlias(kRSAPSK, filterByKeyExchange(allCiphers, Collections.singleton(KeyExchange.RSAPSK))); addListAlias(kECDHEPSK, filterByKeyExchange(allCiphers, Collections.singleton(KeyExchange.ECDHEPSK))); addListAlias(kDHEPSK, filterByKeyExchange(allCiphers, Collections.singleton(KeyExchange.DHEPSK))); - addListAlias(KRB5, filter(allCiphers, null, Collections.singleton(KeyExchange.KRB5), Collections.singleton(Authentication.KRB5), null, null, null)); + addListAlias(KRB5, filter(allCiphers, null, Collections.singleton(KeyExchange.KRB5), + Collections.singleton(Authentication.KRB5), null, null, null)); addListAlias(aSRP, filterByAuthentication(allCiphers, Collections.singleton(Authentication.SRP))); addListAlias(kSRP, filterByKeyExchange(allCiphers, Collections.singleton(KeyExchange.SRP))); addListAlias(SRP, filterByKeyExchange(allCiphers, Collections.singleton(KeyExchange.SRP))); initialized = true; // Despite what the OpenSSL docs say, DEFAULT also excludes SSLv2 - addListAlias(DEFAULT, parse("ALL:!EXPORT:!eNULL:!aNULL:!SSLv2:!DES:!RC2:!RC4:!DSS:!SEED:!IDEA:!CAMELLIA:!AESCCM:!3DES:!ARIA")); + addListAlias(DEFAULT, parse( + "ALL:!EXPORT:!eNULL:!aNULL:!SSLv2:!DES:!RC2:!RC4:!DSS:!SEED:!IDEA:!CAMELLIA:!AESCCM:!3DES:!ARIA")); // COMPLEMENTOFDEFAULT is also not exactly as defined by the docs - LinkedHashSet complementOfDefault = filterByKeyExchange(all, new HashSet<>(Arrays.asList(KeyExchange.EDH,KeyExchange.EECDH))); + LinkedHashSet complementOfDefault = + filterByKeyExchange(all, new HashSet<>(Arrays.asList(KeyExchange.EDH, KeyExchange.EECDH))); complementOfDefault = filterByAuthentication(complementOfDefault, Collections.singleton(Authentication.aNULL)); aliases.get(eNULL).forEach(complementOfDefault::remove); complementOfDefault.addAll(aliases.get(Constants.SSL_PROTO_SSLv2)); @@ -590,9 +624,8 @@ static LinkedHashSet strengthSort(final LinkedHashSet ciphers) { /* - * This routine sorts the ciphers with descending strength. The sorting - * must keep the pre-sorted sequence, so we apply the normal sorting - * routine as '+' movement to the end of the list. + * This routine sorts the ciphers with descending strength. The sorting must keep the pre-sorted sequence, so we + * apply the normal sorting routine as '+' movement to the end of the list. */ Set keySizes = new HashSet<>(); for (Cipher cipher : ciphers) { @@ -609,8 +642,7 @@ } /* - * See - * https://github.com/openssl/openssl/blob/7c96dbcdab959fef74c4caae63cdebaa354ab252/ssl/ssl_ciph.c#L1371 + * See https://github.com/openssl/openssl/blob/7c96dbcdab959fef74c4caae63cdebaa354ab252/ssl/ssl_ciph.c#L1371 */ static LinkedHashSet defaultSort(final LinkedHashSet ciphers) { final LinkedHashSet result = new LinkedHashSet<>(ciphers.size()); @@ -620,9 +652,9 @@ ecdh.addAll(filterByKeyExchange(ciphers, Collections.singleton(KeyExchange.EECDH))); /* AES is our preferred symmetric cipher */ - Set aes = new HashSet<>(Arrays.asList(Encryption.AES128, Encryption.AES128CCM, - Encryption.AES128CCM8, Encryption.AES128GCM, Encryption.AES256, - Encryption.AES256CCM, Encryption.AES256CCM8, Encryption.AES256GCM)); + Set aes = new HashSet<>( + Arrays.asList(Encryption.AES128, Encryption.AES128CCM, Encryption.AES128CCM8, Encryption.AES128GCM, + Encryption.AES256, Encryption.AES256CCM, Encryption.AES256CCM8, Encryption.AES256GCM)); /* Now arrange all ciphers by preference: */ result.addAll(filterByEncryption(ecdh, aes)); @@ -635,9 +667,10 @@ /* Low priority for MD5 */ moveToEnd(result, filterByMessageDigest(result, Collections.singleton(MessageDigest.MD5))); - /* Move anonymous ciphers to the end. Usually, these will remain disabled. - * (For applications that allow them, they aren't too bad, but we prefer - * authenticated ciphers.) */ + /* + * Move anonymous ciphers to the end. Usually, these will remain disabled. (For applications that allow them, + * they aren't too bad, but we prefer authenticated ciphers.) + */ moveToEnd(result, filterByAuthentication(result, Collections.singleton(Authentication.aNULL))); /* Move ciphers without forward secrecy to the end */ @@ -721,15 +754,18 @@ if (JreCompat.isJre22Available()) { if (OpenSSLStatus.isLibraryInitialized()) { try { - Class openSSLLibraryClass = Class.forName("org.apache.tomcat.util.net.openssl.panama.OpenSSLLibrary"); + Class openSSLLibraryClass = + Class.forName("org.apache.tomcat.util.net.openssl.panama.OpenSSLLibrary"); @SuppressWarnings("unchecked") - List cipherList = (List) openSSLLibraryClass.getMethod("findCiphers", String.class).invoke(null, elements[0]); + List cipherList = (List) openSSLLibraryClass + .getMethod("findCiphers", String.class).invoke(null, elements[0]); // Replace the original list with the profile contents elements = cipherList.toArray(new String[0]); } catch (Throwable t) { Throwable throwable = ExceptionUtils.unwrapInvocationTargetException(t); ExceptionUtils.handleThrowable(throwable); - log.error(sm.getString("opensslCipherConfigurationParser.unknownProfile", elements[0]), throwable); + log.error(sm.getString("opensslCipherConfigurationParser.unknownProfile", elements[0]), + throwable); } } else { // OpenSSL is not available @@ -768,14 +804,14 @@ add(ciphers, element); } else if (element.contains(AND)) { String[] intersections = element.split("\\" + AND); - if(intersections.length > 0 && aliases.containsKey(intersections[0])) { + if (intersections.length > 0 && aliases.containsKey(intersections[0])) { List result = new ArrayList<>(aliases.get(intersections[0])); - for(int i = 1; i < intersections.length; i++) { - if(aliases.containsKey(intersections[i])) { + for (int i = 1; i < intersections.length; i++) { + if (aliases.containsKey(intersections[i])) { result.retainAll(aliases.get(intersections[i])); } } - ciphers.addAll(result); + ciphers.addAll(result); } } } @@ -789,16 +825,31 @@ result.addAll(cipher.getJsseNames()); } if (log.isDebugEnabled()) { - log.debug(sm.getString("opensslCipherConfigurationParser.effectiveCiphers", displayResult(ciphers, true, ","))); + log.debug(sm.getString("opensslCipherConfigurationParser.effectiveCiphers", + displayResult(ciphers, true, ","))); } return result; } /** - * Parse the specified expression according to the OpenSSL syntax and - * returns a list of standard JSSE cipher names. + * Determines if the provided name is the name of a TLS 1.3 cipher suite. + * + * @param cipherSuiteName The name to test + * + * @return {@code true} if the provided String is recognised as the name of a TLS 1.3 cipherSuite. + */ + public static boolean isTls13Cipher(String cipherSuiteName) { + if (!initialized) { + init(); + } + return tls13CipherSuiteNames.contains(cipherSuiteName); + } + + /** + * Parse the specified expression according to the OpenSSL syntax and returns a list of standard JSSE cipher names. * * @param expression the openssl expression to define a list of cipher. + * * @return the corresponding list of ciphers. */ public static List parseExpression(String expression) { @@ -826,8 +877,8 @@ * * @param opensslCipherName The OpenSSL name for a cipher * - * @return The JSSE name for the specified OpenSSL cipher. If none is known, - * the IANA standard name will be returned instead + * @return The JSSE name for the specified OpenSSL cipher. If none is known, the IANA standard name will be returned + * instead */ public static String openSSLToJsse(String opensslCipherName) { if (!initialized) { @@ -864,7 +915,8 @@ } public static void usage() { - System.out.println("Usage: java " + OpenSSLCipherConfigurationParser.class.getName() + " [options] cipher spec"); + System.out + .println("Usage: java " + OpenSSLCipherConfigurationParser.class.getName() + " [options] cipher spec"); System.out.println(); System.out.println("Displays the TLS cipher suites matching the cipher spec."); System.out.println(); @@ -875,26 +927,23 @@ System.out.println(" -v Provide detailed cipher listing"); } - public static void main(String[] args) throws Exception - { + public static void main(String[] args) throws Exception { boolean verbose = false; boolean useOpenSSLNames = false; int argindex; - for(argindex = 0; argindex < args.length; ++argindex) - { + for (argindex = 0; argindex < args.length; ++argindex) { String arg = args[argindex]; - if("--verbose".equals(arg) || "-v".equals(arg)) { + if ("--verbose".equals(arg) || "-v".equals(arg)) { verbose = true; - } else if("--openssl".equals(arg)) { + } else if ("--openssl".equals(arg)) { useOpenSSLNames = true; - } else if("--help".equals(arg) || "-h".equals(arg)) { + } else if ("--help".equals(arg) || "-h".equals(arg)) { usage(); System.exit(0); - } - else if("--".equals(arg)) { + } else if ("--".equals(arg)) { ++argindex; break; - } else if(arg.startsWith("-")) { + } else if (arg.startsWith("-")) { System.out.println("Unknown option: " + arg); usage(); System.exit(1); @@ -905,30 +954,30 @@ } String cipherSpec; - if(argindex < args.length) { + if (argindex < args.length) { cipherSpec = args[argindex]; } else { cipherSpec = "DEFAULT"; } Set ciphers = parse(cipherSpec); boolean first = true; - if(!ciphers.isEmpty()) { - for(Cipher cipher : ciphers) - { - if(first) { + if (!ciphers.isEmpty()) { + for (Cipher cipher : ciphers) { + if (first) { first = false; } else { - if(!verbose) { + if (!verbose) { System.out.print(','); } } - if(useOpenSSLNames) { + if (useOpenSSLNames) { System.out.print(cipher.getOpenSSLAlias()); } else { System.out.print(cipher.name()); } - if(verbose) { - System.out.println("\t" + cipher.getProtocol() + "\tKx=" + cipher.getKx() + "\tAu=" + cipher.getAu() + "\tEnc=" + cipher.getEnc() + "\tMac=" + cipher.getMac()); + if (verbose) { + System.out.println("\t" + cipher.getProtocol() + "\tKx=" + cipher.getKx() + "\tAu=" + + cipher.getAu() + "\tEnc=" + cipher.getEnc() + "\tMac=" + cipher.getMac()); } } System.out.println(); diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/net/openssl/ciphers/Protocol.java tomcat10-10.1.52/java/org/apache/tomcat/util/net/openssl/ciphers/Protocol.java --- tomcat10-10.1.40/java/org/apache/tomcat/util/net/openssl/ciphers/Protocol.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/net/openssl/ciphers/Protocol.java 2026-01-23 19:33:36.000000000 +0000 @@ -33,9 +33,8 @@ } /** - * The name returned by OpenSSL in the protocol column when using - * openssl ciphers -v. This is currently only used by the unit - * tests hence it is package private. + * The name returned by OpenSSL in the protocol column when using openssl ciphers -v. This is currently + * only used by the unit tests hence it is package private. */ String getOpenSSLName() { return openSSLName; diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/net/openssl/ciphers/SignatureScheme.java tomcat10-10.1.52/java/org/apache/tomcat/util/net/openssl/ciphers/SignatureScheme.java --- tomcat10-10.1.40/java/org/apache/tomcat/util/net/openssl/ciphers/SignatureScheme.java 1970-01-01 00:00:00.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/net/openssl/ciphers/SignatureScheme.java 2026-01-23 19:33:36.000000000 +0000 @@ -0,0 +1,100 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.tomcat.util.net.openssl.ciphers; + +import java.util.HashMap; +import java.util.Map; + +/** + * All the signature schemes for TLS 1.3. + * @see The signature schemes + * registry + */ +public enum SignatureScheme { + + // RSASSA-PKCS1-v1_5 algorithms + rsa_pkcs1_sha256(0x0401, Authentication.RSA), + rsa_pkcs1_sha384(0x0501, Authentication.RSA), + rsa_pkcs1_sha512(0x0601, Authentication.RSA), + + // ECDSA algorithms + ecdsa_secp256r1_sha256(0x0403, Authentication.ECDSA), + ecdsa_secp384r1_sha384(0x0503, Authentication.ECDSA), + ecdsa_secp521r1_sha512(0x0603, Authentication.ECDSA), + + // RSASSA-PSS algorithms with public key OID rsaEncryption + rsa_pss_rsae_sha256(0x0804, Authentication.RSA), + rsa_pss_rsae_sha384(0x0805, Authentication.RSA), + rsa_pss_rsae_sha512(0x0806, Authentication.RSA), + + // EdDSA algorithms + ed25519(0x0807, Authentication.EdDSA), + ed448(0x0808, Authentication.EdDSA), + + // RSASSA-PSS algorithms with public key OID RSASSA-PSS + rsa_pss_pss_sha256(0x0809, Authentication.RSA), + rsa_pss_pss_sha384(0x080a, Authentication.RSA), + rsa_pss_pss_sha512(0x080b, Authentication.RSA), + + // Legacy algorithms + rsa_pkcs1_sha1(0x0201, Authentication.RSA), + ecdsa_sha1(0x0203, Authentication.ECDSA), + + // ML-DSA algorithms + mldsa44(0x0904, Authentication.MLDSA), + mldsa65(0x0905, Authentication.MLDSA), + mldsa87(0x0906, Authentication.MLDSA); + + private final int id; + private final Authentication auth; + + SignatureScheme(int id, Authentication auth) { + this.id = id; + this.auth = auth; + } + + /** + * @return the id + */ + public int getId() { + return this.id; + } + + /** + * @return the auth + */ + public Authentication getAuth() { + return this.auth; + } + + private static final Map idMap = new HashMap<>(); + + static { + for (SignatureScheme scheme : values()) { + int id = scheme.getId(); + + if (id > 0 && id < 0xFFFF) { + idMap.put(Integer.valueOf(id), scheme); + } + } + } + + + public static SignatureScheme valueOf(int schemeId) { + return idMap.get(Integer.valueOf(schemeId)); + } +} diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/net/openssl/panama/LocalStrings.properties tomcat10-10.1.52/java/org/apache/tomcat/util/net/openssl/panama/LocalStrings.properties --- tomcat10-10.1.40/java/org/apache/tomcat/util/net/openssl/panama/LocalStrings.properties 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/net/openssl/panama/LocalStrings.properties 2026-01-23 19:33:36.000000000 +0000 @@ -63,6 +63,7 @@ openssl.errorPrivateKeyCheck=Private key does not match the certificate public key: [{0}] openssl.errorReadingPEMParameters=Failed reading PEM parameters [{0}] for certificate [{1}] openssl.errorSSLCtxInit=Error initializing SSL context +openssl.errorSettingGroups=Error setting group list: [{0}] openssl.invalidSslProtocol=An invalid value [{0}] was provided for the SSLProtocol attribute openssl.keyManagerMissing=No key manager found openssl.makeConf=Creating OpenSSLConf context diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/net/openssl/panama/LocalStrings_fr.properties tomcat10-10.1.52/java/org/apache/tomcat/util/net/openssl/panama/LocalStrings_fr.properties --- tomcat10-10.1.40/java/org/apache/tomcat/util/net/openssl/panama/LocalStrings_fr.properties 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/net/openssl/panama/LocalStrings_fr.properties 2026-01-23 19:33:36.000000000 +0000 @@ -63,6 +63,7 @@ openssl.errorPrivateKeyCheck=La clé privée ne correspond pas à la clé publique du certificat: [{0}] openssl.errorReadingPEMParameters=Erreur de lecture des paramètres PEM [{0}] pour le certificat [{1}] openssl.errorSSLCtxInit=Erreur d'initialisation du contexte SSL +openssl.errorSettingGroups=Erreur en définissant la liste de groupes: [{0}] openssl.invalidSslProtocol=La valeur invalide [{0}] a été fournie pour l''attribut SSLProtocol openssl.keyManagerMissing=Aucun gestionnaire de clés trouvé openssl.makeConf=Création du contexte de OpenSSLConf diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/net/openssl/panama/LocalStrings_ja.properties tomcat10-10.1.52/java/org/apache/tomcat/util/net/openssl/panama/LocalStrings_ja.properties --- tomcat10-10.1.40/java/org/apache/tomcat/util/net/openssl/panama/LocalStrings_ja.properties 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/net/openssl/panama/LocalStrings_ja.properties 2026-01-23 19:33:36.000000000 +0000 @@ -63,6 +63,7 @@ openssl.errorPrivateKeyCheck=秘密鍵が証明書の公開鍵と一致しません: [{0}] openssl.errorReadingPEMParameters=証明書 [{1}] の PEM パラメータ [{0}] の読み取りに失敗しました openssl.errorSSLCtxInit=SSLコンテキストの初期化エラー +openssl.errorSettingGroups=グループリストの設定中にエラーが発生しました: [{0}] openssl.invalidSslProtocol=無効な値 [{0}] が SSLProtocol 属性に指定されました openssl.keyManagerMissing=キーマネージャが見つかりません openssl.makeConf=OpenSSLConf コンテキストの作成 diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/net/openssl/panama/OpenSSLContext.java tomcat10-10.1.52/java/org/apache/tomcat/util/net/openssl/panama/OpenSSLContext.java --- tomcat10-10.1.40/java/org/apache/tomcat/util/net/openssl/panama/OpenSSLContext.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/net/openssl/panama/OpenSSLContext.java 2026-01-23 19:33:36.000000000 +0000 @@ -59,10 +59,12 @@ import org.apache.tomcat.util.net.SSLHostConfig.CertificateVerification; import org.apache.tomcat.util.net.SSLHostConfigCertificate; import org.apache.tomcat.util.net.SSLHostConfigCertificate.Type; +import org.apache.tomcat.util.net.SSLUtilBase; import org.apache.tomcat.util.net.openssl.OpenSSLConf; import org.apache.tomcat.util.net.openssl.OpenSSLConfCmd; import org.apache.tomcat.util.net.openssl.OpenSSLStatus; import org.apache.tomcat.util.net.openssl.OpenSSLUtil; +import org.apache.tomcat.util.net.openssl.ciphers.Group; import org.apache.tomcat.util.openssl.SSL_CTX_set_alpn_select_cb$cb; import org.apache.tomcat.util.openssl.SSL_CTX_set_cert_verify_callback$cb; import org.apache.tomcat.util.openssl.SSL_CTX_set_tmp_dh_callback$dh; @@ -81,31 +83,24 @@ private static final String defaultProtocol = "TLS"; - private static final int SSL_AIDX_RSA = 0; - private static final int SSL_AIDX_DSA = 1; - private static final int SSL_AIDX_ECC = 3; - private static final int SSL_AIDX_MAX = 4; - - public static final int SSL_PROTOCOL_NONE = 0; + public static final int SSL_PROTOCOL_NONE = 0; public static final int SSL_PROTOCOL_SSLV2 = 1; - public static final int SSL_PROTOCOL_SSLV3 = (1<<1); - public static final int SSL_PROTOCOL_TLSV1 = (1<<2); - public static final int SSL_PROTOCOL_TLSV1_1 = (1<<3); - public static final int SSL_PROTOCOL_TLSV1_2 = (1<<4); - public static final int SSL_PROTOCOL_TLSV1_3 = (1<<5); - public static final int SSL_PROTOCOL_ALL = (SSL_PROTOCOL_TLSV1 | SSL_PROTOCOL_TLSV1_1 | SSL_PROTOCOL_TLSV1_2 | - SSL_PROTOCOL_TLSV1_3); + public static final int SSL_PROTOCOL_SSLV3 = (1 << 1); + public static final int SSL_PROTOCOL_TLSV1 = (1 << 2); + public static final int SSL_PROTOCOL_TLSV1_1 = (1 << 3); + public static final int SSL_PROTOCOL_TLSV1_2 = (1 << 4); + public static final int SSL_PROTOCOL_TLSV1_3 = (1 << 5); + public static final int SSL_PROTOCOL_ALL = + (SSL_PROTOCOL_TLSV1 | SSL_PROTOCOL_TLSV1_1 | SSL_PROTOCOL_TLSV1_2 | SSL_PROTOCOL_TLSV1_3); static final int OPTIONAL_NO_CA = 3; private static final String BEGIN_KEY = "-----BEGIN PRIVATE KEY-----\n"; private static final Object END_KEY = "\n-----END PRIVATE KEY-----"; - private static final byte[] HTTP_11_PROTOCOL = - new byte[] { 'h', 't', 't', 'p', '/', '1', '.', '1' }; + private static final byte[] HTTP_11_PROTOCOL = new byte[] { 'h', 't', 't', 'p', '/', '1', '.', '1' }; - private static final byte[] DEFAULT_SESSION_ID_CONTEXT = - new byte[] { 'd', 'e', 'f', 'a', 'u', 'l', 't' }; + private static final byte[] DEFAULT_SESSION_ID_CONTEXT = new byte[] { 'd', 'e', 'f', 'a', 'u', 'l', 't' }; static final CertificateFactory X509_CERT_FACTORY; static { @@ -128,6 +123,10 @@ private boolean initialized = false; private boolean noOcspCheck = false; + private boolean ocspSoftFail = true; + // 15s default - same as JSSE + private int ocspTimeout = 15000; + private int ocspVerifyFlags = 0; private X509TrustManager x509TrustManager; private final ContextState state; @@ -149,8 +148,7 @@ return ciphers.toArray(new String[0]); } - public OpenSSLContext(SSLHostConfigCertificate certificate, List negotiableProtocols) - throws SSLException { + public OpenSSLContext(SSLHostConfigCertificate certificate, List negotiableProtocols) throws SSLException { // Check that OpenSSL was initialized if (!OpenSSLStatus.isInitialized()) { @@ -181,10 +179,8 @@ if (MemorySegment.NULL.equals(confCtx)) { throw new SSLException(sm.getString("openssl.errMakeConf", OpenSSLLibrary.getLastError())); } - SSL_CONF_CTX_set_flags(confCtx, SSL_CONF_FLAG_FILE() | - SSL_CONF_FLAG_SERVER() | - SSL_CONF_FLAG_CERTIFICATE() | - SSL_CONF_FLAG_SHOW_ERRORS()); + SSL_CONF_CTX_set_flags(confCtx, SSL_CONF_FLAG_FILE() | SSL_CONF_FLAG_SERVER() | + SSL_CONF_FLAG_CERTIFICATE() | SSL_CONF_FLAG_SHOW_ERRORS()); } else { log.error(sm.getString("opensslconf.unsupported")); } @@ -267,8 +263,30 @@ SSL_CTX_set_timeout(sslCtx, 14400); // Set int pem_password_cb(char *buf, int size, int rwflag, void *u) callback - SSL_CTX_set_default_passwd_cb(sslCtx, - pem_password_cb.allocate(new PasswordCallback(null), contextArena)); + SSL_CTX_set_default_passwd_cb(sslCtx, pem_password_cb.allocate(new PasswordCallback(null), contextArena)); + + // Set server groups + // Note: It is also possible to override setSSLParameters in OpenSSLEngine to set the final + // list of groups per connection, but this is less efficient than setting the configured + // group list on the SSL context and letting OpenSSL figure it out. + if (sslHostConfig.getGroupList() != null) { + StringBuilder sb = new StringBuilder(); + boolean first = true; + for (Group group : sslHostConfig.getGroupList()) { + if (first) { + first = false; + } else { + sb.append(':'); + } + sb.append(group.toString()); + } + try (var localArena = Arena.ofConfined()) { + if (SSL_CTX_set1_groups_list(sslCtx, localArena.allocateFrom(sb.toString())) <= 0) { + logLastError("openssl.errorSettingGroups"); + // Consider this is not fatal + } + } + } if (negotiableProtocols != null && !negotiableProtocols.isEmpty()) { alpn = true; @@ -282,21 +300,18 @@ } success = true; - } catch(Exception e) { + } catch (Exception e) { throw new SSLException(sm.getString("openssl.errorSSLCtxInit"), e); } finally { this.negotiableProtocols = negotiableProtocolsBytes; state = new ContextState(sslCtx, confCtx); /* - * When an SSLHostConfig is replaced at runtime, it is not possible to - * call destroy() on the associated OpenSSLContext since it is likely - * that there will be in-progress connections using the OpenSSLContext. - * A reference chain has been deliberately established (see - * OpenSSLSessionContext) to ensure that the OpenSSLContext remains - * ineligible for GC while those connections are alive. Once those - * connections complete, the OpenSSLContext will become eligible for GC - * and the memory session will ensure that the associated native - * resources are cleaned up. + * When an SSLHostConfig is replaced at runtime, it is not possible to call destroy() on the associated + * OpenSSLContext since it is likely that there will be in-progress connections using the OpenSSLContext. A + * reference chain has been deliberately established (see OpenSSLSessionContext) to ensure that the + * OpenSSLContext remains ineligible for GC while those connections are alive. Once those connections + * complete, the OpenSSLContext will become eligible for GC and the memory session will ensure that the + * associated native resources are cleaned up. */ cleanable = cleaner.register(this, state); @@ -342,7 +357,13 @@ log.trace(sm.getString("opensslconf.checkCommand", name, value)); } try (var localArena = Arena.ofConfined()) { - if (name.equals("NO_OCSP_CHECK")) { + if (name.equals(OpenSSLConfCmd.NO_OCSP_CHECK)) { + ok = true; + } else if (name.equals(OpenSSLConfCmd.OCSP_SOFT_FAIL)) { + ok = true; + } else if (name.equals(OpenSSLConfCmd.OCSP_TIMEOUT)) { + ok = true; + } else if (name.equals(OpenSSLConfCmd.OCSP_VERIFY_FLAGS)) { ok = true; } else { int code = SSL_CONF_cmd_value_type(state.confCtx, localArena.allocateFrom(name)); @@ -374,7 +395,7 @@ } } } catch (Exception e) { - log.error(sm.getString("opensslconf.checkFailed", e.getLocalizedMessage())); + log.error(sm.getString("opensslconf.checkFailed", e.getLocalizedMessage()), e); return false; } if (!ok) { @@ -411,12 +432,20 @@ log.trace(sm.getString("opensslconf.applyCommand", name, value)); } try (var localArena = Arena.ofConfined()) { - if (name.equals("NO_OCSP_CHECK")) { - noOcspCheck = Boolean.parseBoolean(value); + if (name.equals(OpenSSLConfCmd.NO_OCSP_CHECK)) { + // Ignore - Tomcat internal - set directly + rc = 1; + } else if (name.equals(OpenSSLConfCmd.OCSP_SOFT_FAIL)) { + // Ignore - Tomcat internal - set directly + rc = 1; + } else if (name.equals(OpenSSLConfCmd.OCSP_TIMEOUT)) { + // Ignore - Tomcat internal - set directly + rc = 1; + } else if (name.equals(OpenSSLConfCmd.OCSP_VERIFY_FLAGS)) { + // Ignore - Tomcat internal - set directly rc = 1; } else { - rc = SSL_CONF_cmd(state.confCtx, localArena.allocateFrom(name), - localArena.allocateFrom(value)); + rc = SSL_CONF_cmd(state.confCtx, localArena.allocateFrom(name), localArena.allocateFrom(value)); String errorMessage = OpenSSLLibrary.getLastError(); if (rc <= 0 || errorMessage != null) { log.error(sm.getString("opensslconf.commandError", name, value, errorMessage)); @@ -424,16 +453,14 @@ } } } catch (Exception e) { - log.error(sm.getString("opensslconf.applyFailed")); + log.error(sm.getString("opensslconf.applyFailed"), e); return false; } if (rc <= 0) { - log.error(sm.getString("opensslconf.failedCommand", name, value, - Integer.toString(rc))); + log.error(sm.getString("opensslconf.failedCommand", name, value, Integer.toString(rc))); result = false; } else if (log.isTraceEnabled()) { - log.trace(sm.getString("opensslconf.resultCommand", name, value, - Integer.toString(rc))); + log.trace(sm.getString("opensslconf.resultCommand", name, value, Integer.toString(rc))); } } // rc = SSLConf.finish(confCtx); @@ -451,11 +478,10 @@ /** * Set up the SSL_CTX. * - * @param kms Must contain a KeyManager of the type - * {@code OpenSSLKeyManager} - * @param tms Must contain a TrustManager of the type - * {@code X509TrustManager} - * @param sr Is not used for this implementation. + * @param kms Must contain a KeyManager of the type {@code OpenSSLKeyManager} + * @param tms Must contain a TrustManager of the type {@code X509TrustManager} + * @param sr Is not used for this implementation. + * * @throws KeyManagementException if an error occurs */ @Override @@ -495,18 +521,35 @@ openssl_h_Compatibility.SSL_CTX_clear_options(state.sslCtx, SSL_OP_NO_TICKET()); } + boolean ciphersSet = false; + String tls12Warning = null; + String tls13Warning = null; // List the ciphers that the client is permitted to negotiate if (minTlsVersion <= TLS1_2_VERSION()) { - if (SSL_CTX_set_cipher_list(state.sslCtx, - localArena.allocateFrom(sslHostConfig.getCiphers())) <= 0) { - log.warn(sm.getString("engine.failedCipherList", sslHostConfig.getCiphers())); + if (SSL_CTX_set_cipher_list(state.sslCtx, localArena.allocateFrom(sslHostConfig.getCiphers())) <= 0) { + tls12Warning = sm.getString("engine.failedCipherList", sslHostConfig.getCiphers()); + } else { + ciphersSet = true; + } + } + if (maxTlsVersion >= TLS1_3_VERSION()) { + try { + if (SSL_CTX_set_ciphersuites(state.sslCtx, localArena.allocateFrom(sslHostConfig.getCipherSuites())) <= 0) { + tls13Warning = sm.getString("engine.failedCipherSuite", sslHostConfig.getCipherSuites()); + } else { + ciphersSet = true; + } + } catch (NoClassDefFoundError | UnsatisfiedLinkError e) { + // Ignore unavailable TLS 1.3 call, which might be compiled out sometimes on LibreSSL + tls13Warning = sm.getString("engine.failedCipherSuite", sslHostConfig.getCipherSuites()); } } - // Check if the ciphers have been changed from the defaults - if (maxTlsVersion >= TLS1_3_VERSION() && (sslHostConfig.getCiphers() != SSLHostConfig.DEFAULT_TLS_CIPHERS)) { - if (SSL_CTX_set_ciphersuites(state.sslCtx, - localArena.allocateFrom(sslHostConfig.getCiphers())) <= 0) { - log.warn(sm.getString("engine.failedCipherSuite", sslHostConfig.getCiphers())); + if (!ciphersSet) { + if (tls12Warning != null) { + log.warn(tls12Warning); + } + if (tls13Warning != null) { + log.warn(tls13Warning); } } @@ -525,16 +568,23 @@ case REQUIRED -> SSL_VERIFY_FAIL_IF_NO_PEER_CERT(); }; + if (value == OPTIONAL_NO_CA || !sslHostConfig.getOcspEnabled()) { + noOcspCheck = true; + } + ocspSoftFail = sslHostConfig.getOcspSoftFail(); + ocspTimeout = sslHostConfig.getOcspTimeout(); + ocspVerifyFlags = sslHostConfig.getOcspVerifyFlags(); + // Set int verify_callback(int preverify_ok, X509_STORE_CTX *x509_ctx) callback SSL_CTX_set_verify(state.sslCtx, value, SSL_CTX_set_verify$callback.allocate(new OpenSSLEngine.VerifyCallback(), contextArena)); - // Trust and certificate verification + // Trust and certificate verification (optional - may not be configured) if (tms != null) { // Client certificate verification based on custom trust managers x509TrustManager = chooseTrustManager(tms); - SSL_CTX_set_cert_verify_callback(state.sslCtx, - SSL_CTX_set_cert_verify_callback$cb.allocate(new CertVerifyCallback(x509TrustManager), contextArena), state.sslCtx); + SSL_CTX_set_cert_verify_callback(state.sslCtx, SSL_CTX_set_cert_verify_callback$cb + .allocate(new CertVerifyCallback(x509TrustManager), contextArena), state.sslCtx); // Pass along the DER encoded certificates of the accepted client // certificate issuers, so that their subjects can be presented @@ -552,15 +602,17 @@ log.debug(sm.getString("openssl.addedClientCaCert", caCert.toString())); } } - } else { + } else if (sslHostConfig.getCaCertificateFile() != null || sslHostConfig.getCaCertificatePath() != null) { // Client certificate verification based on trusted CA files and dirs - MemorySegment caCertificateFileNative = sslHostConfig.getCaCertificateFile() != null - ? localArena.allocateFrom(SSLHostConfig.adjustRelativePath(sslHostConfig.getCaCertificateFile())) : MemorySegment.NULL; - MemorySegment caCertificatePathNative = sslHostConfig.getCaCertificatePath() != null - ? localArena.allocateFrom(SSLHostConfig.adjustRelativePath(sslHostConfig.getCaCertificatePath())) : MemorySegment.NULL; - if ((sslHostConfig.getCaCertificateFile() != null || sslHostConfig.getCaCertificatePath() != null) - && SSL_CTX_load_verify_locations(state.sslCtx, - caCertificateFileNative, caCertificatePathNative) <= 0) { + MemorySegment caCertificateFileNative = sslHostConfig.getCaCertificateFile() != null ? + localArena + .allocateFrom(SSLHostConfig.adjustRelativePath(sslHostConfig.getCaCertificateFile())) : + MemorySegment.NULL; + MemorySegment caCertificatePathNative = sslHostConfig.getCaCertificatePath() != null ? + localArena + .allocateFrom(SSLHostConfig.adjustRelativePath(sslHostConfig.getCaCertificatePath())) : + MemorySegment.NULL; + if (SSL_CTX_load_verify_locations(state.sslCtx, caCertificateFileNative, caCertificatePathNative) <= 0) { logLastError("openssl.errorConfiguringLocations"); } else { var caCerts = SSL_CTX_get_client_CA_list(state.sslCtx); @@ -571,8 +623,8 @@ } } else { // OpenSSL might crash here when passing null on some platforms - if (MemorySegment.NULL.equals(caCertificateFileNative) - || (SSL_add_file_cert_subjects_to_stack(caCerts, caCertificateFileNative) <= 0)) { + if (MemorySegment.NULL.equals(caCertificateFileNative) || + (SSL_add_file_cert_subjects_to_stack(caCerts, caCertificateFileNative) <= 0)) { caCerts = MemorySegment.NULL; } } @@ -583,8 +635,8 @@ } if (negotiableProtocols != null && !negotiableProtocols.isEmpty()) { - SSL_CTX_set_alpn_select_cb(state.sslCtx, - SSL_CTX_set_alpn_select_cb$cb.allocate(new ALPNSelectCallback(negotiableProtocols), contextArena), state.sslCtx); + SSL_CTX_set_alpn_select_cb(state.sslCtx, SSL_CTX_set_alpn_select_cb$cb + .allocate(new ALPNSelectCallback(negotiableProtocols), contextArena), state.sslCtx); } // Log any non fatal init errors @@ -642,8 +694,7 @@ if ((opts & SSL_OP_NO_SSLv3()) == 0) { enabled.add(Constants.SSL_PROTO_SSLv3); } - sslHostConfig.setEnabledProtocols( - enabled.toArray(new String[0])); + sslHostConfig.setEnabledProtocols(enabled.toArray(new String[0])); // Reconfigure the enabled ciphers sslHostConfig.setEnabledCiphers(getCiphers(state.sslCtx)); } @@ -677,16 +728,12 @@ var pkey = SSL_get_privatekey(ssl); int type = (MemorySegment.NULL.equals(pkey)) ? EVP_PKEY_NONE() : EVP_PKEY_base_id(pkey); /* - * OpenSSL will call us with either keylen == 512 or keylen == 1024 - * (see the definition of SSL_EXPORT_PKEYLENGTH in ssl_locl.h). - * Adjust the DH parameter length according to the size of the - * RSA/DSA private key used for the current connection, and always - * use at least 1024-bit parameters. - * Note: This may cause interoperability issues with implementations - * which limit their DH support to 1024 bit - e.g. Java 7 and earlier. - * In this case, SSLCertificateFile can be used to specify fixed - * 1024-bit DH parameters (with the effect that OpenSSL skips this - * callback). + * OpenSSL will call us with either keylen == 512 or keylen == 1024 (see the definition of + * SSL_EXPORT_PKEYLENGTH in ssl_locl.h). Adjust the DH parameter length according to the size of the RSA/DSA + * private key used for the current connection, and always use at least 1024-bit parameters. Note: This may + * cause interoperability issues with implementations which limit their DH support to 1024 bit - e.g. Java 7 + * and earlier. In this case, SSLCertificateFile can be used to specify fixed 1024-bit DH parameters (with + * the effect that OpenSSL skips this callback). */ int keylen = 0; if (type == EVP_PKEY_RSA() || type == EVP_PKEY_DSA()) { @@ -702,15 +749,17 @@ } // int SSL_callback_alpn_select_proto(SSL* ssl, const unsigned char **out, unsigned char *outlen, - // const unsigned char *in, unsigned int inlen, void *arg) + // const unsigned char *in, unsigned int inlen, void *arg) private static class ALPNSelectCallback implements SSL_CTX_set_alpn_select_cb$cb.Function { private final List negotiableProtocols; + ALPNSelectCallback(List negotiableProtocols) { this.negotiableProtocols = negotiableProtocols; } + @Override - public int apply(MemorySegment ssl, MemorySegment out, - MemorySegment outlen, MemorySegment in, int inlen, MemorySegment arg) { + public int apply(MemorySegment ssl, MemorySegment out, MemorySegment outlen, MemorySegment in, int inlen, + MemorySegment arg) { try (var localArena = Arena.ofConfined()) { MemorySegment inSeg = in.reinterpret(inlen, localArena, null); byte[] advertisedBytes = inSeg.toArray(ValueLayout.JAVA_BYTE); @@ -721,9 +770,11 @@ if (advertisedBytes[i + j] == negotiableProtocolBytes[j]) { if (j == negotiableProtocolBytes.length - 1) { // Match - MemorySegment outSeg = out.reinterpret(ValueLayout.ADDRESS.byteSize(), localArena, null); + MemorySegment outSeg = + out.reinterpret(ValueLayout.ADDRESS.byteSize(), localArena, null); outSeg.set(ValueLayout.ADDRESS, 0, inSeg.asSlice(i)); - MemorySegment outlenSeg = outlen.reinterpret(ValueLayout.JAVA_BYTE.byteSize(), localArena, null); + MemorySegment outlenSeg = + outlen.reinterpret(ValueLayout.JAVA_BYTE.byteSize(), localArena, null); outlenSeg.set(ValueLayout.JAVA_BYTE, 0, (byte) negotiableProtocolBytes.length); return SSL_TLSEXT_ERR_OK(); } @@ -742,11 +793,13 @@ private static class CertVerifyCallback implements SSL_CTX_set_cert_verify_callback$cb.Function { private final X509TrustManager x509TrustManager; + CertVerifyCallback(X509TrustManager x509TrustManager) { this.x509TrustManager = x509TrustManager; } + @Override - public int apply(MemorySegment /*X509_STORE_CTX*/ x509_ctx, MemorySegment param) { + public int apply(MemorySegment /* X509_STORE_CTX */ x509_ctx, MemorySegment param) { if (log.isTraceEnabled()) { log.trace("Certificate verification"); } @@ -754,12 +807,12 @@ return 0; } MemorySegment ssl = X509_STORE_CTX_get_ex_data(x509_ctx, SSL_get_ex_data_X509_STORE_CTX_idx()); - MemorySegment /*STACK_OF(X509)*/ sk = X509_STORE_CTX_get0_untrusted(x509_ctx); + MemorySegment /* STACK_OF(X509) */ sk = X509_STORE_CTX_get0_untrusted(x509_ctx); int len = openssl_h_Compatibility.OPENSSL_sk_num(sk); byte[][] certificateChain = new byte[len][]; try (var localArena = Arena.ofConfined()) { for (int i = 0; i < len; i++) { - MemorySegment/*(X509*)*/ x509 = openssl_h_Compatibility.OPENSSL_sk_value(sk, i); + MemorySegment/* (X509*) */ x509 = openssl_h_Compatibility.OPENSSL_sk_value(sk, i); MemorySegment bufPointer = localArena.allocateFrom(ValueLayout.ADDRESS, MemorySegment.NULL); int length = i2d_X509(x509, bufPointer); if (length < 0) { @@ -771,30 +824,32 @@ OPENSSL_free(buf); } MemorySegment cipher = SSL_get_current_cipher(ssl); - String authMethod = (MemorySegment.NULL.equals(cipher)) ? "UNKNOWN" - : getCipherAuthenticationMethod(SSL_CIPHER_get_auth_nid(cipher), SSL_CIPHER_get_kx_nid(cipher)); + String authMethod = (MemorySegment.NULL.equals(cipher)) ? "UNKNOWN" : + getCipherAuthenticationMethod(SSL_CIPHER_get_auth_nid(cipher), SSL_CIPHER_get_kx_nid(cipher)); X509Certificate[] peerCerts = certificates(certificateChain); try { x509TrustManager.checkClientTrusted(peerCerts, authMethod); return 1; } catch (Exception e) { - log.debug(sm.getString("openssl.certificateVerificationFailed"), e); + if (log.isDebugEnabled()) { + log.debug(sm.getString("openssl.certificateVerificationFailed"), e); + } } } return 0; } } - private static final int NID_kx_rsa = 1037/*NID_kx_rsa()*/; - //private static final int NID_kx_dhe = NID_kx_dhe(); - //private static final int NID_kx_ecdhe = NID_kx_ecdhe(); - - //private static final int NID_auth_rsa = NID_auth_rsa(); - //private static final int NID_auth_dss = NID_auth_dss(); - //private static final int NID_auth_null = NID_auth_null(); - //private static final int NID_auth_ecdsa = NID_auth_ecdsa(); + private static final int NID_kx_rsa = 1037/* NID_kx_rsa() */; + // private static final int NID_kx_dhe = NID_kx_dhe(); + // private static final int NID_kx_ecdhe = NID_kx_ecdhe(); + + // private static final int NID_auth_rsa = NID_auth_rsa(); + // private static final int NID_auth_dss = NID_auth_dss(); + // private static final int NID_auth_null = NID_auth_null(); + // private static final int NID_auth_ecdsa = NID_auth_ecdsa(); - //private static final int SSL_kRSA = 1; + // private static final int SSL_kRSA = 1; private static final int SSL_kDHr = 2; private static final int SSL_kDHd = 4; private static final int SSL_kEDH = 8; @@ -804,21 +859,21 @@ private static final int SSL_kECDHe = 40; private static final int SSL_kEECDH = 80; private static final int SSL_kECDHE = SSL_kEECDH; - //private static final int SSL_kPSK = 100; - //private static final int SSL_kGOST = 200; - //private static final int SSL_kSRP = 400; + // private static final int SSL_kPSK = 100; + // private static final int SSL_kGOST = 200; + // private static final int SSL_kSRP = 400; private static final int SSL_aRSA = 1; private static final int SSL_aDSS = 2; private static final int SSL_aNULL = 4; - //private static final int SSL_aDH = 8; - //private static final int SSL_aECDH = 10; - //private static final int SSL_aKRB5 = 20; + // private static final int SSL_aDH = 8; + // private static final int SSL_aECDH = 10; + // private static final int SSL_aKRB5 = 20; private static final int SSL_aECDSA = 40; - //private static final int SSL_aPSK = 80; - //private static final int SSL_aGOST94 = 100; - //private static final int SSL_aGOST01 = 200; - //private static final int SSL_aSRP = 400; + // private static final int SSL_aPSK = 80; + // private static final int SSL_aGOST94 = 100; + // private static final int SSL_aGOST01 = 200; + // private static final int SSL_aSRP = 400; private static final String SSL_TXT_RSA = "RSA"; private static final String SSL_TXT_DH = "DH"; @@ -853,9 +908,11 @@ private static class PasswordCallback implements pem_password_cb.Function { private final String callbackPassword; + PasswordCallback(String callbackPassword) { this.callbackPassword = callbackPassword; } + @Override public int apply(MemorySegment /* char **/ buf, int bufsiz, int verify, MemorySegment /* void **/ cb) { if (log.isTraceEnabled()) { @@ -879,8 +936,7 @@ } - private boolean addCertificate(SSLHostConfigCertificate certificate, Arena localArena) throws Exception { - int index = getCertificateIndex(certificate); + public boolean addCertificate(SSLHostConfigCertificate certificate, Arena localArena) throws Exception { // Load Server key and certificate if (certificate.getCertificateFile() != null) { // Pick right key password @@ -894,13 +950,12 @@ keyPassFile = certificate.getCertificateKeystorePasswordFile(); } if (keyPassFile != null) { - try (BufferedReader reader = - new BufferedReader(new InputStreamReader( - ConfigFileLoader.getSource().getResource(keyPassFile).getInputStream(), + try (BufferedReader reader = new BufferedReader( + new InputStreamReader(ConfigFileLoader.getSource().getResource(keyPassFile).getInputStream(), StandardCharsets.UTF_8))) { keyPassToUse = reader.readLine(); - } catch (IOException e) { - log.error(sm.getString("openssl.errorLoadingPassword", keyPassFile), e); + } catch (IOException ioe) { + log.error(sm.getString("openssl.errorLoadingPassword", keyPassFile), ioe); return false; } } else { @@ -910,16 +965,17 @@ byte[] certificateFileBytes; try (Resource resource = ConfigFileLoader.getSource().getResource(certificate.getCertificateFile())) { certificateFileBytes = resource.getInputStream().readAllBytes(); - } catch (IOException e) { - log.error(sm.getString("openssl.errorLoadingCertificate", certificate.getCertificateFile()), e); + } catch (IOException ioe) { + log.error(sm.getString("openssl.errorLoadingCertificate", certificate.getCertificateFile()), ioe); return false; } - MemorySegment certificateFileBytesNative = localArena.allocateFrom(ValueLayout.JAVA_BYTE, certificateFileBytes); + MemorySegment certificateFileBytesNative = + localArena.allocateFrom(ValueLayout.JAVA_BYTE, certificateFileBytes); MemorySegment certificateBIO = BIO_new(BIO_s_mem()); try { if (BIO_write(certificateBIO, certificateFileBytesNative, certificateFileBytes.length) <= 0) { - log.error(sm.getString("openssl.errorLoadingCertificateWithError", - certificate.getCertificateFile(), OpenSSLLibrary.getLastError())); + log.error(sm.getString("openssl.errorLoadingCertificateWithError", certificate.getCertificateFile(), + OpenSSLLibrary.getLastError())); return false; } MemorySegment cert; @@ -957,22 +1013,24 @@ cert = certPointer.get(ValueLayout.ADDRESS, 0); key = keyPointer.get(ValueLayout.ADDRESS, 0); } else { - String certificateKeyFileName = (certificate.getCertificateKeyFile() == null) - ? certificate.getCertificateFile() : certificate.getCertificateKeyFile(); + String certificateKeyFileName = + (certificate.getCertificateKeyFile() == null) ? certificate.getCertificateFile() : + certificate.getCertificateKeyFile(); // Load key byte[] certificateKeyFileBytes; try (Resource resource = ConfigFileLoader.getSource().getResource(certificateKeyFileName)) { certificateKeyFileBytes = resource.getInputStream().readAllBytes(); - } catch (IOException e) { - log.error(sm.getString("openssl.errorLoadingCertificate", certificateKeyFileName), e); + } catch (IOException ioe) { + log.error(sm.getString("openssl.errorLoadingCertificate", certificateKeyFileName), ioe); return false; } - MemorySegment certificateKeyFileBytesNative = localArena.allocateFrom(ValueLayout.JAVA_BYTE, certificateKeyFileBytes); + MemorySegment certificateKeyFileBytesNative = + localArena.allocateFrom(ValueLayout.JAVA_BYTE, certificateKeyFileBytes); MemorySegment keyBIO = BIO_new(BIO_s_mem()); try { if (BIO_write(keyBIO, certificateKeyFileBytesNative, certificateKeyFileBytes.length) <= 0) { - log.error(sm.getString("openssl.errorLoadingCertificateWithError", - certificateKeyFileName, OpenSSLLibrary.getLastError())); + log.error(sm.getString("openssl.errorLoadingCertificateWithError", certificateKeyFileName, + OpenSSLLibrary.getLastError())); return false; } key = MemorySegment.NULL; @@ -997,8 +1055,8 @@ } } if (MemorySegment.NULL.equals(key)) { - log.error(sm.getString("openssl.errorLoadingCertificateWithError", - certificateKeyFileName, OpenSSLLibrary.getLastError())); + log.error(sm.getString("openssl.errorLoadingCertificateWithError", certificateKeyFileName, + OpenSSLLibrary.getLastError())); return false; } // Load certificate @@ -1030,12 +1088,13 @@ logLastError("openssl.errorPrivateKeyCheck"); return false; } - // Try to read DH parameters from the (first) SSLCertificateFile - if (index == SSL_AIDX_RSA) { + // Try to read DH parameters from the SSLCertificateFile + if (certificate.getType() == Type.RSA) { BIO_reset(certificateBIO); if (!openssl_h_Compatibility.BORINGSSL) { if (!openssl_h_Compatibility.OPENSSL3) { - var dh = PEM_read_bio_DHparams(certificateBIO, MemorySegment.NULL, MemorySegment.NULL, MemorySegment.NULL); + var dh = PEM_read_bio_DHparams(certificateBIO, MemorySegment.NULL, MemorySegment.NULL, + MemorySegment.NULL); if (!MemorySegment.NULL.equals(dh)) { SSL_CTX_set_tmp_dh(state.sslCtx, dh); DH_free(dh); @@ -1047,14 +1106,16 @@ if (SSL_CTX_set0_tmp_dh_pkey(state.sslCtx, pkey) <= 0) { EVP_PKEY_free(pkey); } else { - log.debug(sm.getString("openssl.setCustomDHParameters", Integer.valueOf(numBits), certificate.getCertificateFile())); + log.debug(sm.getString("openssl.setCustomDHParameters", Integer.valueOf(numBits), + certificate.getCertificateFile())); } } else { String errMessage = OpenSSLLibrary.getLastError(); if (errMessage != null) { - log.debug(sm.getString("openssl.errorReadingPEMParameters", errMessage, certificate.getCertificateFile())); + log.debug(sm.getString("openssl.errorReadingPEMParameters", errMessage, + certificate.getCertificateFile())); } - SSL_CTX_ctrl(state.sslCtx, SSL_CTRL_SET_DH_AUTO(), 1, MemorySegment.NULL); + SSL_CTX_set_dh_auto(state.sslCtx, 1); } } } @@ -1063,7 +1124,8 @@ BIO_reset(certificateBIO); if (!openssl_h_Compatibility.BORINGSSL) { if (!openssl_h_Compatibility.OPENSSL3) { - var ecparams = PEM_read_bio_ECPKParameters(certificateBIO, MemorySegment.NULL, MemorySegment.NULL, MemorySegment.NULL); + var ecparams = PEM_read_bio_ECPKParameters(certificateBIO, MemorySegment.NULL, + MemorySegment.NULL, MemorySegment.NULL); if (!MemorySegment.NULL.equals(ecparams)) { int nid = EC_GROUP_get_curve_name(ecparams); var eckey = EC_KEY_new_by_curve_name(nid); @@ -1072,10 +1134,11 @@ EC_GROUP_free(ecparams); } // Set callback for DH parameters - SSL_CTX_set_tmp_dh_callback(state.sslCtx, SSL_CTX_set_tmp_dh_callback$dh.allocate(new TmpDHCallback(), contextArena)); + SSL_CTX_set_tmp_dh_callback(state.sslCtx, + SSL_CTX_set_tmp_dh_callback$dh.allocate(new TmpDHCallback(), contextArena)); } else { - var ecparams = PEM_ASN1_read_bio(d2i_ECPKParameters$SYMBOL(), - PEM_STRING_ECPARAMETERS(), certificateBIO, MemorySegment.NULL, MemorySegment.NULL, MemorySegment.NULL); + var ecparams = PEM_ASN1_read_bio(d2i_ECPKParameters$SYMBOL(), PEM_STRING_ECPARAMETERS(), + certificateBIO, MemorySegment.NULL, MemorySegment.NULL, MemorySegment.NULL); if (!MemorySegment.NULL.equals(ecparams)) { int curveNid = EC_GROUP_get_curve_name(ecparams); var curveNidAddress = localArena.allocateFrom(ValueLayout.JAVA_INT, curveNid); @@ -1093,29 +1156,34 @@ // Set certificate chain file if (certificate.getCertificateChainFile() != null) { byte[] certificateChainBytes; - try (Resource resource = ConfigFileLoader.getSource().getResource(certificate.getCertificateChainFile())) { + try (Resource resource = + ConfigFileLoader.getSource().getResource(certificate.getCertificateChainFile())) { certificateChainBytes = resource.getInputStream().readAllBytes(); - } catch (IOException e) { - log.error(sm.getString("openssl.errorLoadingCertificate", certificate.getCertificateChainFile()), e); + } catch (IOException ioe) { + log.error( + sm.getString("openssl.errorLoadingCertificate", certificate.getCertificateChainFile()), + ioe); return false; } - MemorySegment certificateChainBytesNative = localArena.allocateFrom(ValueLayout.JAVA_BYTE, certificateChainBytes); + MemorySegment certificateChainBytesNative = + localArena.allocateFrom(ValueLayout.JAVA_BYTE, certificateChainBytes); MemorySegment certificateChainBIO = BIO_new(BIO_s_mem()); try { - if (BIO_write(certificateChainBIO, certificateChainBytesNative, certificateChainBytes.length) <= 0) { + if (BIO_write(certificateChainBIO, certificateChainBytesNative, + certificateChainBytes.length) <= 0) { log.error(sm.getString("openssl.errorLoadingCertificateWithError", certificate.getCertificateChainFile(), OpenSSLLibrary.getLastError())); return false; } - MemorySegment certChainEntry = - PEM_read_bio_X509_AUX(certificateChainBIO, MemorySegment.NULL, MemorySegment.NULL, MemorySegment.NULL); + MemorySegment certChainEntry = PEM_read_bio_X509_AUX(certificateChainBIO, MemorySegment.NULL, + MemorySegment.NULL, MemorySegment.NULL); while (!MemorySegment.NULL.equals(certChainEntry)) { if (SSL_CTX_add0_chain_cert(state.sslCtx, certChainEntry) <= 0) { log.error(sm.getString("openssl.errorLoadingCertificateWithError", certificate.getCertificateChainFile(), OpenSSLLibrary.getLastError())); } - certChainEntry = - PEM_read_bio_X509_AUX(certificateChainBIO, MemorySegment.NULL, MemorySegment.NULL, MemorySegment.NULL); + certChainEntry = PEM_read_bio_X509_AUX(certificateChainBIO, MemorySegment.NULL, + MemorySegment.NULL, MemorySegment.NULL); } // EOF is accepted, otherwise log an error if ((ERR_peek_last_error() & ERR_REASON_MASK()) == PEM_R_NO_START_LINE()) { @@ -1132,8 +1200,8 @@ MemorySegment certificateStore = SSL_CTX_get_cert_store(state.sslCtx); if (sslHostConfig.getCertificateRevocationListFile() != null) { MemorySegment x509Lookup = X509_STORE_add_lookup(certificateStore, X509_LOOKUP_file()); - var certificateRevocationListFileNative = - localArena.allocateFrom(SSLHostConfig.adjustRelativePath(sslHostConfig.getCertificateRevocationListFile())); + var certificateRevocationListFileNative = localArena.allocateFrom( + SSLHostConfig.adjustRelativePath(sslHostConfig.getCertificateRevocationListFile())); if (X509_LOOKUP_load_file(x509Lookup, certificateRevocationListFileNative, X509_FILETYPE_PEM()) <= 0) { log.error(sm.getString("openssl.errorLoadingCertificateRevocationListWithError", @@ -1142,8 +1210,8 @@ } if (sslHostConfig.getCertificateRevocationListPath() != null) { MemorySegment x509Lookup = X509_STORE_add_lookup(certificateStore, X509_LOOKUP_hash_dir()); - var certificateRevocationListPathNative = - localArena.allocateFrom(SSLHostConfig.adjustRelativePath(sslHostConfig.getCertificateRevocationListPath())); + var certificateRevocationListPathNative = localArena.allocateFrom( + SSLHostConfig.adjustRelativePath(sslHostConfig.getCertificateRevocationListPath())); if (X509_LOOKUP_add_dir(x509Lookup, certificateRevocationListPathNative, X509_FILETYPE_PEM()) <= 0) { log.error(sm.getString("openssl.errorLoadingCertificateRevocationListWithError", @@ -1158,17 +1226,15 @@ String alias = certificate.getCertificateKeyAlias(); X509KeyManager x509KeyManager = certificate.getCertificateKeyManager(); if (alias == null) { - alias = "tomcat"; + alias = SSLUtilBase.DEFAULT_KEY_ALIAS; } X509Certificate[] chain = x509KeyManager.getCertificateChain(alias); if (chain == null) { alias = findAlias(x509KeyManager, certificate); chain = x509KeyManager.getCertificateChain(alias); } - String encodedKey = - BEGIN_KEY + - Base64.getMimeEncoder(64, new byte[]{'\n'}).encodeToString(x509KeyManager.getPrivateKey(alias).getEncoded()) + - END_KEY; + String encodedKey = BEGIN_KEY + Base64.getMimeEncoder(64, new byte[] { '\n' }) + .encodeToString(x509KeyManager.getPrivateKey(alias).getEncoded()) + END_KEY; var rawCertificate = localArena.allocateFrom(ValueLayout.JAVA_BYTE, chain[0].getEncoded()); var rawCertificatePointer = localArena.allocateFrom(ValueLayout.ADDRESS, rawCertificate); var rawKey = localArena.allocateFrom(ValueLayout.JAVA_BYTE, encodedKey.getBytes(StandardCharsets.US_ASCII)); @@ -1180,7 +1246,8 @@ MemorySegment keyBIO = BIO_new(BIO_s_mem()); try { BIO_write(keyBIO, rawKey, (int) rawKey.byteSize()); - MemorySegment privateKeyAddress = PEM_read_bio_PrivateKey(keyBIO, MemorySegment.NULL, MemorySegment.NULL, MemorySegment.NULL); + MemorySegment privateKeyAddress = + PEM_read_bio_PrivateKey(keyBIO, MemorySegment.NULL, MemorySegment.NULL, MemorySegment.NULL); if (MemorySegment.NULL.equals(privateKeyAddress)) { logLastError("openssl.errorLoadingPrivateKey"); return false; @@ -1218,13 +1285,14 @@ log.debug(sm.getString("openssl.errorReadingPEMParameters", errMessage, x509KeyManager.toString())); } - SSL_CTX_ctrl(state.sslCtx, SSL_CTRL_SET_DH_AUTO(), 1, MemorySegment.NULL); + SSL_CTX_set_dh_auto(state.sslCtx, 1); } } for (int i = 1; i < chain.length; i++) { var rawCertificateChain = localArena.allocateFrom(ValueLayout.JAVA_BYTE, chain[i].getEncoded()); var rawCertificateChainPointer = localArena.allocateFrom(ValueLayout.ADDRESS, rawCertificateChain); - var x509certChain = d2i_X509(MemorySegment.NULL, rawCertificateChainPointer, rawCertificateChain.byteSize()); + var x509certChain = + d2i_X509(MemorySegment.NULL, rawCertificateChainPointer, rawCertificateChain.byteSize()); if (MemorySegment.NULL.equals(x509certChain)) { logLastError("openssl.errorLoadingCertificate"); return false; @@ -1242,28 +1310,10 @@ } - private static int getCertificateIndex(SSLHostConfigCertificate certificate) { - int result; - // If the type is undefined there will only be one certificate (enforced - // in SSLHostConfig) so use the RSA slot. - if (certificate.getType() == Type.RSA || certificate.getType() == Type.UNDEFINED) { - result = SSL_AIDX_RSA; - } else if (certificate.getType() == Type.EC) { - result = SSL_AIDX_ECC; - } else if (certificate.getType() == Type.DSA) { - result = SSL_AIDX_DSA; - } else { - result = SSL_AIDX_MAX; - } - return result; - } - - /* * Find a valid alias when none was specified in the config. */ - private static String findAlias(X509KeyManager keyManager, - SSLHostConfigCertificate certificate) { + private static String findAlias(X509KeyManager keyManager, SSLHostConfigCertificate certificate) { Type type = certificate.getType(); String result = null; @@ -1280,7 +1330,7 @@ Iterator iter = candidateTypes.iterator(); while (result == null && iter.hasNext()) { - result = keyManager.chooseServerAlias(iter.next().toString(), null, null); + result = keyManager.chooseServerAlias(iter.next().getKeyType(), null, null); } return result; @@ -1319,11 +1369,10 @@ @Override public SSLEngine createSSLEngine() { - return new OpenSSLEngine(cleaner, state.sslCtx, defaultProtocol, false, sessionContext, - alpn, initialized, + return new OpenSSLEngine(cleaner, state.sslCtx, defaultProtocol, false, sessionContext, alpn, initialized, sslHostConfig.getCertificateVerificationDepth(), sslHostConfig.getCertificateVerification() == CertificateVerification.OPTIONAL_NO_CA, - noOcspCheck); + noOcspCheck, ocspSoftFail, ocspTimeout, ocspVerifyFlags); } @Override @@ -1342,7 +1391,7 @@ X509KeyManager x509KeyManager = certificate.getCertificateKeyManager(); if (x509KeyManager != null) { if (alias == null) { - alias = "tomcat"; + alias = SSLUtilBase.DEFAULT_KEY_ALIAS; } chain = x509KeyManager.getCertificateChain(alias); if (chain == null) { @@ -1373,11 +1422,10 @@ private ContextState(MemorySegment sslCtx, MemorySegment confCtx) { // Use another arena to avoid keeping a reference through segments // This also allows making further accesses to the main pointers safer - this.sslCtx = sslCtx.reinterpret(ValueLayout.ADDRESS.byteSize(), stateArena, - openssl_h::SSL_CTX_free); + this.sslCtx = sslCtx.reinterpret(ValueLayout.ADDRESS.byteSize(), stateArena, openssl_h::SSL_CTX_free); if (!MemorySegment.NULL.equals(confCtx)) { - this.confCtx = confCtx.reinterpret(ValueLayout.ADDRESS.byteSize(), stateArena, - openssl_h::SSL_CONF_CTX_free); + this.confCtx = + confCtx.reinterpret(ValueLayout.ADDRESS.byteSize(), stateArena, openssl_h::SSL_CONF_CTX_free); } else { this.confCtx = MemorySegment.NULL; } diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/net/openssl/panama/OpenSSLEngine.java tomcat10-10.1.52/java/org/apache/tomcat/util/net/openssl/panama/OpenSSLEngine.java --- tomcat10-10.1.40/java/org/apache/tomcat/util/net/openssl/panama/OpenSSLEngine.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/net/openssl/panama/OpenSSLEngine.java 2026-01-23 19:33:36.000000000 +0000 @@ -17,6 +17,7 @@ package org.apache.tomcat.util.net.openssl.panama; import java.io.ByteArrayOutputStream; +import java.io.IOException; import java.io.InputStream; import java.lang.foreign.Arena; import java.lang.foreign.MemorySegment; @@ -56,6 +57,7 @@ import org.apache.juli.logging.Log; import org.apache.juli.logging.LogFactory; import org.apache.tomcat.util.buf.Asn1Parser; +import org.apache.tomcat.util.http.Method; import org.apache.tomcat.util.net.Constants; import org.apache.tomcat.util.net.SSLUtil; import org.apache.tomcat.util.net.openssl.ciphers.OpenSSLCipherConfigurationParser; @@ -67,9 +69,8 @@ import org.apache.tomcat.util.res.StringManager; /** - * Implements a {@link SSLEngine} using - * OpenSSL - * BIO abstractions. + * Implements a {@link SSLEngine} using OpenSSL BIO + * abstractions. */ public final class OpenSSLEngine extends SSLEngine implements SSLUtil.ProtocolInfo { @@ -87,13 +88,15 @@ availableCipherSuites.addAll(OpenSSLLibrary.findCiphers("ALL")); AVAILABLE_CIPHER_SUITES = Collections.unmodifiableSet(availableCipherSuites); IMPLEMENTED_PROTOCOLS_SET = Set.of(Constants.SSL_PROTO_SSLv2Hello, Constants.SSL_PROTO_SSLv2, - Constants.SSL_PROTO_SSLv3, Constants.SSL_PROTO_TLSv1, Constants.SSL_PROTO_TLSv1_1, - Constants.SSL_PROTO_TLSv1_2, Constants.SSL_PROTO_TLSv1_3); + Constants.SSL_PROTO_SSLv3, Constants.SSL_PROTO_TLSv1, Constants.SSL_PROTO_TLSv1_1, + Constants.SSL_PROTO_TLSv1_2, Constants.SSL_PROTO_TLSv1_3); } private static final int MAX_PLAINTEXT_LENGTH = 16 * 1024; // 2^14 private static final int MAX_COMPRESSED_LENGTH = MAX_PLAINTEXT_LENGTH + 1024; private static final int MAX_CIPHERTEXT_LENGTH = MAX_COMPRESSED_LENGTH + 1024; + // 15 minutes aligns with JSSE + private static final int OCSP_MAX_SKEW = 60 * 15; // Header (5) + Data (2^14) + Compression (1024) + Encryption (1024) + MAC (20) + Padding (256) private static final int MAX_ENCRYPTED_PACKET_LENGTH = MAX_CIPHERTEXT_LENGTH + 5 + 20 + 256; @@ -106,7 +109,8 @@ private static final String INVALID_CIPHER = "SSL_NULL_WITH_NULL_NULL"; - private static final ConcurrentHashMap states = new ConcurrentHashMap<>(); + private static final ConcurrentHashMap states = new ConcurrentHashMap<>(); + private static EngineState getState(MemorySegment ssl) { return states.get(Long.valueOf(ssl.address())); } @@ -116,9 +120,20 @@ private final Cleanable cleanable; private MemorySegment bufSegment; - private enum Accepted { NOT, IMPLICIT, EXPLICIT } + private enum Accepted { + NOT, + IMPLICIT, + EXPLICIT + } + private Accepted accepted = Accepted.NOT; - private enum PHAState { NONE, START, COMPLETE } + + private enum PHAState { + NONE, + START, + COMPLETE + } + private boolean handshakeFinished; private int currentHandshake; private boolean receivedShutdown; @@ -153,24 +168,24 @@ /** * Creates a new instance * - * @param sslCtx an OpenSSL {@code SSL_CTX} object - * @param fallbackApplicationProtocol the fallback application protocol - * @param clientMode {@code true} if this is used for clients, {@code false} - * otherwise - * @param sessionContext the {@link OpenSSLSessionContext} this - * {@link SSLEngine} belongs to. - * @param alpn {@code true} if alpn should be used, {@code false} - * otherwise - * @param initialized {@code true} if this instance gets its protocol, - * cipher and client verification from the {@code SSL_CTX} {@code sslCtx} - * @param certificateVerificationDepth Certificate verification depth - * @param certificateVerificationOptionalNoCA Skip CA verification in - * optional mode + * @param sslCtx an OpenSSL {@code SSL_CTX} object + * @param fallbackApplicationProtocol the fallback application protocol + * @param clientMode {@code true} if this is used for clients, {@code false} otherwise + * @param sessionContext the {@link OpenSSLSessionContext} this {@link SSLEngine} belongs to. + * @param alpn {@code true} if alpn should be used, {@code false} otherwise + * @param initialized {@code true} if this instance gets its protocol, cipher and client + * verification from the {@code SSL_CTX} {@code sslCtx} + * @param certificateVerificationDepth Certificate verification depth + * @param certificateVerificationOptionalNoCA Skip CA verification in optional mode + * @param noOcspCheck Enable OCSP if true + * @param ocspSoftFail Allow OCSP checks to pass if the responder can't be contacted + * @param ocspTimeout Timout in ms to use for OCSP requests + * @param ocspVerifyFlags Verification flags for OCSP */ - OpenSSLEngine(Cleaner cleaner, MemorySegment sslCtx, String fallbackApplicationProtocol, - boolean clientMode, OpenSSLSessionContext sessionContext, boolean alpn, - boolean initialized, int certificateVerificationDepth, - boolean certificateVerificationOptionalNoCA, boolean noOcspCheck) { + OpenSSLEngine(Cleaner cleaner, MemorySegment sslCtx, String fallbackApplicationProtocol, boolean clientMode, + OpenSSLSessionContext sessionContext, boolean alpn, boolean initialized, int certificateVerificationDepth, + boolean certificateVerificationOptionalNoCA, boolean noOcspCheck, boolean ocspSoftFail, + int ocspTimeout, int ocspVerifyFlags) { if (sslCtx == null) { throw new IllegalArgumentException(sm.getString("engine.noSSLContext")); } @@ -193,7 +208,8 @@ var internalBIO = internalBIOPointer.get(ValueLayout.ADDRESS, 0); var networkBIO = networkBIOPointer.get(ValueLayout.ADDRESS, 0); SSL_set_bio(ssl, internalBIO, internalBIO); - state = new EngineState(ssl, networkBIO, certificateVerificationDepth, noOcspCheck); + state = new EngineState(ssl, networkBIO, certificateVerificationDepth, noOcspCheck, ocspSoftFail, + ocspTimeout, ocspVerifyFlags); } this.fallbackApplicationProtocol = fallbackApplicationProtocol; this.clientMode = clientMode; @@ -223,8 +239,8 @@ } /** - * Write plain text data to the OpenSSL internal BIO - * Calling this function with src.remaining == 0 is undefined. + * Write plain text data to the OpenSSL internal BIO Calling this function with src.remaining == 0 is undefined. + * * @throws SSLException if the OpenSSL error check fails */ private int writePlaintextData(final MemorySegment ssl, final ByteBuffer src) throws SSLException { @@ -247,6 +263,7 @@ /** * Write encrypted data to the OpenSSL network BIO. + * * @throws SSLException if the OpenSSL error check fails */ private int writeEncryptedData(final MemorySegment networkBIO, final ByteBuffer src) throws SSLException { @@ -269,6 +286,7 @@ /** * Read plain text data from the OpenSSL internal BIO + * * @throws SSLException if the OpenSSL error check fails */ private int readPlaintextData(final MemorySegment ssl, final ByteBuffer dst) throws SSLException { @@ -291,9 +309,11 @@ /** * Read encrypted data from the OpenSSL network BIO + * * @throws SSLException if the OpenSSL error check fails */ - private int readEncryptedData(final MemorySegment networkBIO, final ByteBuffer dst, final int pending) throws SSLException { + private int readEncryptedData(final MemorySegment networkBIO, final ByteBuffer dst, final int pending) + throws SSLException { clearLastError(); final int pos = dst.position(); MemorySegment dstSegment = dst.isDirect() ? MemorySegment.ofBuffer(dst) : bufSegment; @@ -311,10 +331,12 @@ } @Override - public synchronized SSLEngineResult wrap(final ByteBuffer[] srcs, final int offset, final int length, final ByteBuffer dst) throws SSLException { + public synchronized SSLEngineResult wrap(final ByteBuffer[] srcs, final int offset, final int length, + final ByteBuffer dst) throws SSLException { // Check to make sure the engine has not been closed if (destroyed) { - return new SSLEngineResult(SSLEngineResult.Status.CLOSED, SSLEngineResult.HandshakeStatus.NOT_HANDSHAKING, 0, 0); + return new SSLEngineResult(SSLEngineResult.Status.CLOSED, SSLEngineResult.HandshakeStatus.NOT_HANDSHAKING, + 0, 0); } // Throw required runtime exceptions @@ -322,9 +344,8 @@ throw new IllegalArgumentException(sm.getString("engine.nullBuffer")); } if (offset >= srcs.length || offset + length > srcs.length) { - throw new IndexOutOfBoundsException(sm.getString("engine.invalidBufferArray", - Integer.toString(offset), Integer.toString(length), - Integer.toString(srcs.length))); + throw new IndexOutOfBoundsException(sm.getString("engine.invalidBufferArray", Integer.toString(offset), + Integer.toString(length), Integer.toString(srcs.length))); } if (dst.isReadOnly()) { throw new ReadOnlyBufferException(); @@ -400,8 +421,8 @@ // Do we have enough room in dst to write encrypted data? int capacity = dst.remaining(); if (capacity < pendingNet) { - return new SSLEngineResult( - SSLEngineResult.Status.BUFFER_OVERFLOW, getHandshakeStatus(), bytesConsumed, bytesProduced); + return new SSLEngineResult(SSLEngineResult.Status.BUFFER_OVERFLOW, getHandshakeStatus(), + bytesConsumed, bytesProduced); } // Write the pending data from the network BIO into the dst buffer @@ -420,10 +441,12 @@ } @Override - public synchronized SSLEngineResult unwrap(final ByteBuffer src, final ByteBuffer[] dsts, final int offset, final int length) throws SSLException { + public synchronized SSLEngineResult unwrap(final ByteBuffer src, final ByteBuffer[] dsts, final int offset, + final int length) throws SSLException { // Check to make sure the engine has not been closed if (destroyed) { - return new SSLEngineResult(SSLEngineResult.Status.CLOSED, SSLEngineResult.HandshakeStatus.NOT_HANDSHAKING, 0, 0); + return new SSLEngineResult(SSLEngineResult.Status.CLOSED, SSLEngineResult.HandshakeStatus.NOT_HANDSHAKING, + 0, 0); } // Throw required runtime exceptions @@ -431,9 +454,8 @@ throw new IllegalArgumentException(sm.getString("engine.nullBuffer")); } if (offset >= dsts.length || offset + length > dsts.length) { - throw new IndexOutOfBoundsException(sm.getString("engine.invalidBufferArray", - Integer.toString(offset), Integer.toString(length), - Integer.toString(dsts.length))); + throw new IndexOutOfBoundsException(sm.getString("engine.invalidBufferArray", Integer.toString(offset), + Integer.toString(length), Integer.toString(dsts.length))); } int capacity = 0; final int endOffset = offset + length; @@ -549,8 +571,7 @@ } } - private int pendingReadableBytesInSSL() - throws SSLException { + private int pendingReadableBytesInSSL() throws SSLException { // NOTE: Calling a fake read is necessary before calling pendingReadableBytesInSSL because // SSL_pending will return 0 if OpenSSL has not started the current TLS record // See https://www.openssl.org/docs/manmaster/man3/SSL_pending.html @@ -564,8 +585,7 @@ int pendingReadableBytesInSSL = SSL_pending(state.ssl); // TLS 1.0 needs additional handling - if (Constants.SSL_PROTO_TLSv1.equals(version) && lastPrimingReadResult == 0 && - pendingReadableBytesInSSL == 0) { + if (Constants.SSL_PROTO_TLSv1.equals(version) && lastPrimingReadResult == 0 && pendingReadableBytesInSSL == 0) { // Perform another priming read lastPrimingReadResult = SSL_read(state.ssl, MemorySegment.NULL, 0); if (lastPrimingReadResult <= 0) { @@ -794,28 +814,29 @@ throw new SSLException(sm.getString("engine.engineClosed")); } switch (accepted) { - case NOT: - handshake(); - accepted = Accepted.EXPLICIT; - break; - case IMPLICIT: - // A user did not start handshake by calling this method by themselves, - // but handshake has been started already by wrap() or unwrap() implicitly. - // Because it's the user's first time to call this method, it is unfair to - // raise an exception. From the user's standpoint, they never asked for - // renegotiation. - - accepted = Accepted.EXPLICIT; // Next time this method is invoked by the user, we should raise an exception. - break; - case EXPLICIT: - renegotiate(); - break; + case NOT: + handshake(); + accepted = Accepted.EXPLICIT; + break; + case IMPLICIT: + // A user did not start handshake by calling this method by themselves, + // but handshake has been started already by wrap() or unwrap() implicitly. + // Because it's the user's first time to call this method, it is unfair to + // raise an exception. From the user's standpoint, they never asked for + // renegotiation. + + accepted = Accepted.EXPLICIT; // Next time this method is invoked by the user, we should raise an + // exception. + break; + case EXPLICIT: + renegotiate(); + break; } } private byte[] getPeerCertificate() { try (var localArena = Arena.ofConfined()) { - MemorySegment/*(X509*)*/ x509 = openssl_h_Compatibility.SSL_get_peer_certificate(state.ssl); + MemorySegment/* (X509*) */ x509 = openssl_h_Compatibility.SSL_get_peer_certificate(state.ssl); MemorySegment bufPointer = localArena.allocateFrom(ValueLayout.ADDRESS, MemorySegment.NULL); int length = i2d_X509(x509, bufPointer); if (length <= 0) { @@ -830,7 +851,7 @@ } private byte[][] getPeerCertChain() { - MemorySegment/*STACK_OF(X509)*/ sk = SSL_get_peer_cert_chain(state.ssl); + MemorySegment/* STACK_OF(X509) */ sk = SSL_get_peer_cert_chain(state.ssl); int len = openssl_h_Compatibility.OPENSSL_sk_num(sk); if (len <= 0) { return null; @@ -838,7 +859,7 @@ byte[][] certificateChain = new byte[len][]; try (var localArena = Arena.ofConfined()) { for (int i = 0; i < len; i++) { - MemorySegment/*(X509*)*/ x509 = openssl_h_Compatibility.OPENSSL_sk_value(sk, i); + MemorySegment/* (X509*) */ x509 = openssl_h_Compatibility.OPENSSL_sk_value(sk, i); MemorySegment bufPointer = localArena.allocateFrom(ValueLayout.ADDRESS, MemorySegment.NULL); int length = i2d_X509(x509, bufPointer); if (length < 0) { @@ -965,34 +986,24 @@ } /* - * Tomcat Native stores a count of the completed handshakes in the - * SSL instance and increments it every time a handshake is - * completed. Comparing the handshake count when the handshake - * started to the current handshake count enables this code to - * detect when the handshake has completed. + * Tomcat Native stores a count of the completed handshakes in the SSL instance and increments it every time + * a handshake is completed. Comparing the handshake count when the handshake started to the current + * handshake count enables this code to detect when the handshake has completed. * - * Obtaining client certificates after the connection has been - * established requires additional checks. We need to trigger - * additional reads until the certificates have been read, but we - * don't know how many reads we will need as it depends on both - * client and network behaviour. + * Obtaining client certificates after the connection has been established requires additional checks. We + * need to trigger additional reads until the certificates have been read, but we don't know how many reads + * we will need as it depends on both client and network behaviour. * - * The additional reads are triggered by returning NEED_UNWRAP - * rather than FINISHED. This allows the standard I/O code to be - * used. + * The additional reads are triggered by returning NEED_UNWRAP rather than FINISHED. This allows the + * standard I/O code to be used. * - * For TLSv1.2 and below, the handshake completes before the - * renegotiation. We therefore use SSL.renegotiatePending() to - * check on the current status of the renegotiation and return - * NEED_UNWRAP until it completes which means the client - * certificates will have been read from the client. + * For TLSv1.2 and below, the handshake completes before the renegotiation. We therefore use + * SSL.renegotiatePending() to check on the current status of the renegotiation and return NEED_UNWRAP until + * it completes which means the client certificates will have been read from the client. * - * For TLSv1.3, Tomcat Native sets a flag when post handshake - * authentication is started and updates it once the client - * certificate has been received. We therefore use - * SSL.getPostHandshakeAuthInProgress() to check the current status - * and return NEED_UNWRAP until that methods indicates that PHA is - * no longer in progress. + * For TLSv1.3, Tomcat Native sets a flag when post handshake authentication is started and updates it once + * the client certificate has been received. We therefore use SSL.getPostHandshakeAuthInProgress() to check + * the current status and return NEED_UNWRAP until that methods indicates that PHA is no longer in progress. */ // No pending data to be sent to the peer @@ -1073,7 +1084,8 @@ state.certificateVerifyMode = switch (mode) { case NONE -> SSL_VERIFY_NONE(); case REQUIRE -> SSL_VERIFY_FAIL_IF_NO_PEER_CERT(); - case OPTIONAL -> certificateVerificationOptionalNoCA ? OpenSSLContext.OPTIONAL_NO_CA : SSL_VERIFY_PEER(); + case OPTIONAL -> + certificateVerificationOptionalNoCA ? OpenSSLContext.OPTIONAL_NO_CA : SSL_VERIFY_PEER(); }; // Set int verify_callback(int preverify_ok, X509_STORE_CTX *x509_ctx) callback int value = switch (mode) { @@ -1104,7 +1116,7 @@ static class VerifyCallback implements SSL_set_verify$callback.Function, SSL_CTX_set_verify$callback.Function { @Override - public int apply(int preverify_ok, MemorySegment /*X509_STORE_CTX*/ x509ctx) { + public int apply(int preverify_ok, MemorySegment /* X509_STORE_CTX */ x509ctx) { MemorySegment ssl = X509_STORE_CTX_get_ex_data(x509ctx, SSL_get_ex_data_X509_STORE_CTX_idx()); EngineState state = getState(ssl); if (state == null) { @@ -1118,34 +1130,34 @@ int errnum = X509_STORE_CTX_get_error(x509ctx); int errdepth = X509_STORE_CTX_get_error_depth(x509ctx); state.phaState = PHAState.COMPLETE; - if (state.certificateVerifyMode == -1 /*SSL_CVERIFY_UNSET*/ || state.certificateVerifyMode == SSL_VERIFY_NONE()) { + if (state.certificateVerifyMode == -1 /* SSL_CVERIFY_UNSET */ || + state.certificateVerifyMode == SSL_VERIFY_NONE()) { return 1; } - /*SSL_VERIFY_ERROR_IS_OPTIONAL(errnum) -> ((errnum == X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT) - || (errnum == X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN) - || (errnum == X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY) - || (errnum == X509_V_ERR_CERT_UNTRUSTED) - || (errnum == X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE))*/ - boolean verifyErrorIsOptional = (errnum == X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT()) - || (errnum == X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN()) - || (errnum == X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY()) - || (errnum == X509_V_ERR_CERT_UNTRUSTED()) - || (errnum == X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE()); - if (verifyErrorIsOptional && (state.certificateVerifyMode == OpenSSLContext.OPTIONAL_NO_CA)) { + /* + * SSL_VERIFY_ERROR_IS_OPTIONAL(errnum) -> ((errnum == X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT) || (errnum == + * X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN) || (errnum == X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY) || + * (errnum == X509_V_ERR_CERT_UNTRUSTED) || (errnum == X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE)) + */ + boolean verifyErrorIsOptional = (errnum == X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT()) || + (errnum == X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN()) || + (errnum == X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY()) || + (errnum == X509_V_ERR_CERT_UNTRUSTED()) || (errnum == X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE()); + if ((verifyErrorIsOptional || errnum == X509_V_OK()) && (state.certificateVerifyMode == OpenSSLContext.OPTIONAL_NO_CA)) { ok = 1; openssl_h_Compatibility.SSL_set_verify_result(state.ssl, X509_V_OK()); } + if (ok == 0 && errnum == X509_V_ERR_UNABLE_TO_GET_CRL()) { + ok = 1; + } /* - * Expired certificates vs. "expired" CRLs: by default, OpenSSL - * turns X509_V_ERR_CRL_HAS_EXPIRED into a "certificate_expired(45)" - * SSL alert, but that's not really the message we should convey to the - * peer (at the very least, it's confusing, and in many cases, it's also - * inaccurate, as the certificate itself may very well not have expired - * yet). We set the X509_STORE_CTX error to something which OpenSSL's - * s3_both.c:ssl_verify_alarm_type() maps to SSL_AD_CERTIFICATE_UNKNOWN, - * i.e. the peer will receive a "certificate_unknown(46)" alert. - * We do not touch errnum, though, so that later on we will still log - * the "real" error, as returned by OpenSSL. + * Expired certificates vs. "expired" CRLs: by default, OpenSSL turns X509_V_ERR_CRL_HAS_EXPIRED into a + * "certificate_expired(45)" SSL alert, but that's not really the message we should convey to the peer (at + * the very least, it's confusing, and in many cases, it's also inaccurate, as the certificate itself may + * very well not have expired yet). We set the X509_STORE_CTX error to something which OpenSSL's + * s3_both.c:ssl_verify_alarm_type() maps to SSL_AD_CERTIFICATE_UNKNOWN, i.e. the peer will receive a + * "certificate_unknown(46)" alert. We do not touch errnum, though, so that later on we will still log the + * "real" error, as returned by OpenSSL. */ if (ok == 0 && errnum == X509_V_ERR_CRL_HAS_EXPIRED()) { X509_STORE_CTX_set_error(x509ctx, -1); @@ -1153,24 +1165,23 @@ // OCSP if (!state.noOcspCheck && (ok > 0)) { - /* If there was an optional verification error, it's not - * possible to perform OCSP validation since the issuer may be - * missing/untrusted. Fail in that case. + /* + * If there was an optional verification error, it's not possible to perform OCSP validation since the + * issuer may be missing/untrusted. Fail in that case. */ if (verifyErrorIsOptional) { - if (state.certificateVerifyMode != OpenSSLContext.OPTIONAL_NO_CA) { - X509_STORE_CTX_set_error(x509ctx, X509_V_ERR_APPLICATION_VERIFICATION()); - errnum = X509_V_ERR_APPLICATION_VERIFICATION(); - ok = 0; - } + X509_STORE_CTX_set_error(x509ctx, X509_V_ERR_APPLICATION_VERIFICATION()); + errnum = X509_V_ERR_APPLICATION_VERIFICATION(); + ok = 0; } else { - int ocspResponse = processOCSP(x509ctx); + int ocspResponse = processOCSP(state, x509ctx); if (ocspResponse == V_OCSP_CERTSTATUS_REVOKED()) { ok = 0; errnum = X509_STORE_CTX_get_error(x509ctx); + X509_STORE_CTX_set_error(x509ctx, X509_V_ERR_CERT_REVOKED()); } else if (ocspResponse == V_OCSP_CERTSTATUS_UNKNOWN()) { errnum = X509_STORE_CTX_get_error(x509ctx); - if (errnum <= 0) { + if (errnum != 0 && !(state.ocspSoftFail && errnum == X509_V_ERR_UNABLE_TO_GET_CRL())) { ok = 0; } } @@ -1185,7 +1196,7 @@ } } - private static int processOCSP(MemorySegment /*X509_STORE_CTX*/ x509ctx) { + private static int processOCSP(EngineState state, MemorySegment /* X509_STORE_CTX */ x509ctx) { int ocspResponse = V_OCSP_CERTSTATUS_UNKNOWN(); MemorySegment x509 = X509_STORE_CTX_get_current_cert(x509ctx); if (!MemorySegment.NULL.equals(x509)) { @@ -1196,46 +1207,60 @@ // don't do OCSP checking for valid self-issued certs X509_STORE_CTX_set_error(x509ctx, X509_V_OK()); } else { - // If we can't get the issuer, we cannot perform OCSP verification - MemorySegment issuer = X509_STORE_CTX_get0_current_issuer(x509ctx); - if (!MemorySegment.NULL.equals(issuer)) { - // sslutils.c ssl_ocsp_request(x509, issuer, x509ctx); - int nid = X509_get_ext_by_NID(x509, NID_info_access(), -1); - if (nid >= 0) { - try (var localArenal = Arena.ofConfined()) { - MemorySegment ext = X509_get_ext(x509, nid); - MemorySegment os = X509_EXTENSION_get_data(ext); - int length = ASN1_STRING_length(os); - MemorySegment data = ASN1_STRING_get0_data(os); - // ocsp_urls = decode_OCSP_url(os); - byte[] asn1String = data.reinterpret(length, localArenal, null).toArray(ValueLayout.JAVA_BYTE); - Asn1Parser parser = new Asn1Parser(asn1String); - // Parse the byte sequence - ArrayList urls = new ArrayList<>(); - try { - parseOCSPURLs(parser, urls); - } catch (Exception e) { - log.error(sm.getString("engine.ocspParseError"), e); + try (var localArena = Arena.ofConfined()) { + // If we can't get the issuer, we cannot perform OCSP verification + MemorySegment issuer = MemorySegment.NULL; + try { + if (openssl_h_Compatibility.OPENSSL && !openssl_h_Compatibility.OPENSSL3) { + issuer = openssl_h_Compatibility.X509_STORE_CTX_get0_current_issuer(x509ctx); + } else { + MemorySegment x509IssuerPointer = localArena.allocateFrom(ValueLayout.ADDRESS, MemorySegment.NULL); + int res = X509_STORE_CTX_get1_issuer(x509IssuerPointer, x509ctx, x509); + if (res > 0) { + issuer = x509IssuerPointer.get(ValueLayout.ADDRESS, 0); } - if (!urls.isEmpty()) { - // Use OpenSSL to build OCSP request - for (String urlString : urls) { - try { - URL url = (new URI(urlString)).toURL(); - ocspResponse = processOCSPRequest(url, issuer, x509, x509ctx, localArenal); - if (log.isDebugEnabled()) { - log.debug(sm.getString("engine.ocspResponse", urlString, - Integer.toString(ocspResponse))); + } + if (!MemorySegment.NULL.equals(issuer)) { + // sslutils.c ssl_ocsp_request(x509, issuer, x509ctx); + int nid = X509_get_ext_by_NID(x509, NID_info_access(), -1); + if (nid >= 0) { + MemorySegment ext = X509_get_ext(x509, nid); + MemorySegment os = X509_EXTENSION_get_data(ext); + int length = ASN1_STRING_length(os); + MemorySegment data = ASN1_STRING_get0_data(os); + // ocsp_urls = decode_OCSP_url(os); + byte[] asn1String = + data.reinterpret(length, localArena, null).toArray(ValueLayout.JAVA_BYTE); + Asn1Parser parser = new Asn1Parser(asn1String); + // Parse the byte sequence + ArrayList urls = new ArrayList<>(); + try { + parseOCSPURLs(parser, urls); + } catch (Exception e) { + log.error(sm.getString("engine.ocspParseError"), e); + } + if (!urls.isEmpty()) { + // Use OpenSSL to build OCSP request + for (String urlString : urls) { + try { + URL url = (new URI(urlString)).toURL(); + ocspResponse = processOCSPRequest(state, url, issuer, x509, x509ctx, localArena); + if (log.isDebugEnabled()) { + log.debug(sm.getString("engine.ocspResponse", urlString, + Integer.toString(ocspResponse))); + } + } catch (MalformedURLException | URISyntaxException e) { + log.warn(sm.getString("engine.invalidOCSPURL", urlString)); + } + if (ocspResponse != V_OCSP_CERTSTATUS_UNKNOWN()) { + break; } - } catch (MalformedURLException | URISyntaxException e) { - log.warn(sm.getString("engine.invalidOCSPURL", urlString)); - } - if (ocspResponse != V_OCSP_CERTSTATUS_UNKNOWN()) { - break; } } } } + } finally { + X509_free(issuer); } } } @@ -1244,9 +1269,9 @@ } private static final int ASN1_SEQUENCE = 0x30; - private static final int ASN1_OID = 0x06; - private static final int ASN1_STRING = 0x86; - private static final byte[] OCSP_OID = {0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x30, 0x01}; + private static final int ASN1_OID = 0x06; + private static final int ASN1_STRING = 0x86; + private static final byte[] OCSP_OID = { 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x30, 0x01 }; private static void parseOCSPURLs(Asn1Parser parser, ArrayList urls) { while (!parser.eof()) { @@ -1272,8 +1297,11 @@ } } - private static int processOCSPRequest(URL url, MemorySegment issuer, MemorySegment x509, - MemorySegment /*X509_STORE_CTX*/ x509ctx, Arena localArena) { + private static int processOCSPRequest(EngineState state, URL url, MemorySegment issuer, MemorySegment x509, + MemorySegment /* X509_STORE_CTX */ x509ctx, Arena localArena) { + if (openssl_h_Compatibility.BORINGSSL || openssl_h_Compatibility.isLibreSSLPre35()) { + return V_OCSP_CERTSTATUS_UNKNOWN(); + } MemorySegment ocspRequest = MemorySegment.NULL; MemorySegment ocspResponse = MemorySegment.NULL; MemorySegment id; @@ -1294,6 +1322,7 @@ if (MemorySegment.NULL.equals(ocspOneReq)) { return V_OCSP_CERTSTATUS_UNKNOWN(); } + OCSP_request_add1_nonce(ocspRequest, (char) 0, -1); MemorySegment bufPointer = localArena.allocateFrom(ValueLayout.ADDRESS, MemorySegment.NULL); int requestLength = i2d_OCSP_REQUEST(ocspRequest, bufPointer); if (requestLength <= 0) { @@ -1307,7 +1336,9 @@ // Content-Length: ocspRequestData.length byte[] ocspRequestData = buf.reinterpret(requestLength, localArena, null).toArray(ValueLayout.JAVA_BYTE); connection = (HttpURLConnection) url.openConnection(); - connection.setRequestMethod("POST"); + connection.setConnectTimeout(state.ocspTimeout); + connection.setReadTimeout(state.ocspTimeout); + connection.setRequestMethod(Method.POST); connection.setDoInput(true); connection.setDoOutput(true); connection.setFixedLengthStreamingMode(requestLength); @@ -1328,26 +1359,54 @@ var nativeResponseData = localArena.allocateFrom(ValueLayout.JAVA_BYTE, responseData); var nativeResponseDataPointer = localArena.allocateFrom(ValueLayout.ADDRESS, nativeResponseData); ocspResponse = d2i_OCSP_RESPONSE(MemorySegment.NULL, nativeResponseDataPointer, responseData.length); - if (!MemorySegment.NULL.equals(ocspResponse)) { + if (MemorySegment.NULL.equals(ocspResponse)) { + // Failed to get a valid response + X509_STORE_CTX_set_error(x509ctx, X509_V_ERR_APPLICATION_VERIFICATION()); + } else { if (OCSP_response_status(ocspResponse) == OCSP_RESPONSE_STATUS_SUCCESSFUL()) { basicResponse = OCSP_response_get1_basic(ocspResponse); + if (OCSP_check_nonce(ocspRequest, basicResponse) == 0) { + X509_STORE_CTX_set_error(x509ctx, X509_V_ERR_OCSP_RESP_INVALID()); + return V_OCSP_CERTSTATUS_UNKNOWN(); + } + MemorySegment certStack = OCSP_resp_get0_certs(basicResponse); + if (OCSP_basic_verify(basicResponse, certStack, X509_STORE_CTX_get0_store(x509ctx), state.ocspVerifyFlags) <= 0) { + X509_STORE_CTX_set_error(x509ctx, X509_V_ERR_OCSP_SIGNATURE_FAILURE()); + return V_OCSP_CERTSTATUS_UNKNOWN(); + } certId = OCSP_cert_to_id(MemorySegment.NULL, x509, issuer); if (MemorySegment.NULL.equals(certId)) { + X509_STORE_CTX_set_error(x509ctx, X509_V_ERR_OCSP_RESP_INVALID()); return V_OCSP_CERTSTATUS_UNKNOWN(); } // Find by serial number and get the matching response - MemorySegment singleResponse = OCSP_resp_get0(basicResponse, OCSP_resp_find(basicResponse, certId, -1)); - return OCSP_single_get0_status(singleResponse, MemorySegment.NULL, - MemorySegment.NULL, MemorySegment.NULL, MemorySegment.NULL); + MemorySegment singleResponse = + OCSP_resp_get0(basicResponse, OCSP_resp_find(basicResponse, certId, -1)); + MemorySegment thisUpdatePointer = localArena.allocateFrom(ValueLayout.ADDRESS, MemorySegment.NULL); + MemorySegment nextUpdatePointer = localArena.allocateFrom(ValueLayout.ADDRESS, MemorySegment.NULL); + int status = OCSP_single_get0_status(singleResponse, MemorySegment.NULL, MemorySegment.NULL, + thisUpdatePointer, nextUpdatePointer); + if (OCSP_check_validity(thisUpdatePointer.get(ValueLayout.ADDRESS, 0), + nextUpdatePointer.get(ValueLayout.ADDRESS, 0), OCSP_MAX_SKEW, -1) <= 0) { + X509_STORE_CTX_set_error(x509ctx, X509_V_ERR_OCSP_NOT_YET_VALID()); + return V_OCSP_CERTSTATUS_UNKNOWN(); + } + if (OCSP_check_validity(thisUpdatePointer.get(ValueLayout.ADDRESS, 0), + nextUpdatePointer.get(ValueLayout.ADDRESS, 0), OCSP_MAX_SKEW, OCSP_MAX_SKEW) <= 0) { + X509_STORE_CTX_set_error(x509ctx, X509_V_ERR_OCSP_HAS_EXPIRED()); + return V_OCSP_CERTSTATUS_UNKNOWN(); + } + return status; } } + } catch (IOException ioe) { + // Timeout or network error. Responder is not available. + log.warn(sm.getString("engine.ocspRequestError", url.toString()), ioe); + X509_STORE_CTX_set_error(x509ctx, X509_V_ERR_UNABLE_TO_GET_CRL()); } catch (Exception e) { log.warn(sm.getString("engine.ocspRequestError", url.toString()), e); + X509_STORE_CTX_set_error(x509ctx, X509_V_ERR_APPLICATION_VERIFICATION()); } finally { - if (MemorySegment.NULL.equals(ocspResponse)) { - // Failed to get a valid response - X509_STORE_CTX_set_error(x509ctx, X509_V_ERR_APPLICATION_VERIFICATION()); - } OCSP_CERTID_free(certId); OCSP_BASICRESP_free(basicResponse); OCSP_RESPONSE_free(ocspResponse); @@ -1376,7 +1435,7 @@ private class OpenSSLSession implements SSLSession { // lazy init for memory reasons - private Map values; + private Map values; // Last accessed time private long lastAccessedTime = -1; @@ -1394,8 +1453,8 @@ } MemorySegment sessionId = SSL_SESSION_get_id(session, lenPointer); int len = lenPointer.get(ValueLayout.JAVA_INT, 0); - id = (len == 0) ? new byte[0] - : sessionId.reinterpret(len, localArena, null).toArray(ValueLayout.JAVA_BYTE); + id = (len == 0) ? new byte[0] : + sessionId.reinterpret(len, localArena, null).toArray(ValueLayout.JAVA_BYTE); } } } @@ -1446,7 +1505,7 @@ if (value == null) { throw new IllegalArgumentException(sm.getString("engine.nullValue")); } - Map values = this.values; + Map values = this.values; if (values == null) { // Use size of 2 to keep the memory overhead small values = this.values = new HashMap<>(2); @@ -1474,7 +1533,7 @@ if (name == null) { throw new IllegalArgumentException(sm.getString("engine.nullName")); } - Map values = this.values; + Map values = this.values; if (values == null) { return; } @@ -1484,7 +1543,7 @@ @Override public String[] getValueNames() { - Map values = this.values; + Map values = this.values; if (values == null || values.isEmpty()) { return new String[0]; } @@ -1510,7 +1569,8 @@ } chain = getPeerCertChain(); if (!clientMode) { - // if used on the server side SSL_get_peer_cert_chain(...) will not include the remote peer certificate. + // if used on the server side SSL_get_peer_cert_chain(...) will not include the remote peer + // certificate. // We use SSL_get_peer_certificate to get it in this case and add it to our array later. // See https://www.openssl.org/docs/ssl/SSL_get_peer_cert_chain.html clientCert = getPeerCertificate(); @@ -1571,7 +1631,7 @@ } private Principal principal(Certificate[] certs) { - return ((java.security.cert.X509Certificate) certs[0]).getIssuerX500Principal(); + return ((java.security.cert.X509Certificate) certs[0]).getSubjectX500Principal(); } @Override @@ -1650,22 +1710,26 @@ private final MemorySegment networkBIO; private final int certificateVerificationDepth; private final boolean noOcspCheck; + private final boolean ocspSoftFail; + private final int ocspTimeout; + private final int ocspVerifyFlags; private PHAState phaState = PHAState.NONE; private int certificateVerifyMode = 0; private int handshakeCount = 0; - private EngineState(MemorySegment ssl, MemorySegment networkBIO, - int certificateVerificationDepth, boolean noOcspCheck) { + private EngineState(MemorySegment ssl, MemorySegment networkBIO, int certificateVerificationDepth, + boolean noOcspCheck, boolean ocspSoftFail, int ocspTimeout, int ocspVerifyFlags) { states.put(Long.valueOf(ssl.address()), this); this.certificateVerificationDepth = certificateVerificationDepth; this.noOcspCheck = noOcspCheck; + this.ocspSoftFail = ocspSoftFail; + this.ocspTimeout = ocspTimeout; + this.ocspVerifyFlags = ocspVerifyFlags; // Use another arena to avoid keeping a reference through segments // This also allows making further accesses to the main pointers safer - this.ssl = ssl.reinterpret(ValueLayout.ADDRESS.byteSize(), stateArena, - openssl_h::SSL_free); - this.networkBIO = networkBIO.reinterpret(ValueLayout.ADDRESS.byteSize(), stateArena, - openssl_h::BIO_free); + this.ssl = ssl.reinterpret(ValueLayout.ADDRESS.byteSize(), stateArena, openssl_h::SSL_free); + this.networkBIO = networkBIO.reinterpret(ValueLayout.ADDRESS.byteSize(), stateArena, openssl_h::BIO_free); } @Override diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/net/openssl/panama/OpenSSLImplementation.java tomcat10-10.1.52/java/org/apache/tomcat/util/net/openssl/panama/OpenSSLImplementation.java --- tomcat10-10.1.40/java/org/apache/tomcat/util/net/openssl/panama/OpenSSLImplementation.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/net/openssl/panama/OpenSSLImplementation.java 2026-01-23 19:33:36.000000000 +0000 @@ -30,7 +30,7 @@ public class OpenSSLImplementation extends SSLImplementation { @Override - public SSLSupport getSSLSupport(SSLSession session, Map> additionalAttributes) { + public SSLSupport getSSLSupport(SSLSession session, Map> additionalAttributes) { return new JSSESupport(session, additionalAttributes); } diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/net/openssl/panama/OpenSSLLibrary.java tomcat10-10.1.52/java/org/apache/tomcat/util/net/openssl/panama/OpenSSLLibrary.java --- tomcat10-10.1.40/java/org/apache/tomcat/util/net/openssl/panama/OpenSSLLibrary.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/net/openssl/panama/OpenSSLLibrary.java 2026-01-23 19:33:36.000000000 +0000 @@ -34,12 +34,10 @@ import org.apache.tomcat.util.res.StringManager; - /** - * Implementation of a global initialization of OpenSSL according to specified - * configuration parameters. - * Using this from a listener is completely optional, but is needed for - * configuration and full cleanup of a few native memory allocations. + * Implementation of a global initialization of OpenSSL according to specified configuration parameters. Using this from + * a listener is completely optional, but is needed for configuration and full cleanup of a few native memory + * allocations. */ public class OpenSSLLibrary { @@ -52,20 +50,19 @@ // ---------------------------------------------- Properties - protected static String SSLEngine = "on"; //default on + protected static String SSLEngine = "on"; // default on protected static String FIPSMode = "off"; // default off, valid only when SSLEngine="on" protected static String SSLRandomSeed = "builtin"; protected static boolean fipsModeActive = false; /** - * The "FIPS mode" level that we use as the argument to OpenSSL method - * FIPS_mode_set() to enable FIPS mode and that we expect as - * the return value of FIPS_mode() when FIPS mode is enabled. + * The "FIPS mode" level that we use as the argument to OpenSSL method FIPS_mode_set() to enable FIPS + * mode and that we expect as the return value of FIPS_mode() when FIPS mode is enabled. *

      - * In the future the OpenSSL library might grow support for different - * non-zero "FIPS" modes that specify different allowed subsets of ciphers - * or whatever, but nowadays only "1" is the supported value. + * In the future the OpenSSL library might grow support for different non-zero "FIPS" modes that specify different + * allowed subsets of ciphers or whatever, but nowadays only "1" is the supported value. *

      + * * @see OpenSSL method FIPS_mode_set() * @see OpenSSL method FIPS_mode() */ @@ -92,21 +89,20 @@ } /* - { BN_get_rfc3526_prime_8192, NULL, 6145 }, - { BN_get_rfc3526_prime_6144, NULL, 4097 }, - { BN_get_rfc3526_prime_4096, NULL, 3073 }, - { BN_get_rfc3526_prime_3072, NULL, 2049 }, - { BN_get_rfc3526_prime_2048, NULL, 1025 }, - { BN_get_rfc2409_prime_1024, NULL, 0 } + * { BN_get_rfc3526_prime_8192, NULL, 6145 }, { BN_get_rfc3526_prime_6144, NULL, 4097 }, { + * BN_get_rfc3526_prime_4096, NULL, 3073 }, { BN_get_rfc3526_prime_3072, NULL, 2049 }, { BN_get_rfc3526_prime_2048, + * NULL, 1025 }, { BN_get_rfc2409_prime_1024, NULL, 0 } */ static final class DHParam { final MemorySegment dh; final int min; + private DHParam(MemorySegment dh, int min) { this.dh = dh; this.min = min; } } + static final DHParam[] dhParameters = new DHParam[6]; private static void initDHParameters() { @@ -182,6 +178,8 @@ initLibrary(); OpenSSLStatus.setVersion(OpenSSL_version_num()); + OpenSSLStatus.setMajorVersion(openssl_h_Compatibility.MAJOR); + OpenSSLStatus.setMinorVersion(openssl_h_Compatibility.MINOR); if (openssl_h_Compatibility.OPENSSL3) { OpenSSLStatus.setName(OpenSSLStatus.Name.OPENSSL3); } else if (openssl_h_Compatibility.OPENSSL) { @@ -205,8 +203,9 @@ if (MemorySegment.NULL.equals(enginePointer)) { enginePointer = ENGINE_by_id(memorySession.allocateFrom("dynamic")); if (enginePointer != null) { - if (ENGINE_ctrl_cmd_string(enginePointer, memorySession.allocateFrom("SO_PATH"), engine, 0) == 0 - || ENGINE_ctrl_cmd_string(enginePointer, memorySession.allocateFrom("LOAD"), + if (ENGINE_ctrl_cmd_string(enginePointer, memorySession.allocateFrom("SO_PATH"), engine, + 0) == 0 || + ENGINE_ctrl_cmd_string(enginePointer, memorySession.allocateFrom("LOAD"), MemorySegment.NULL, 0) == 0) { // Engine load error ENGINE_free(enginePointer); @@ -233,7 +232,8 @@ var randomSeed = memorySession.allocateFrom(SSLRandomSeed); seedDone = RAND_load_file(randomSeed, 128) > 0; if (!seedDone) { - log.warn(sm.getString("openssllibrary.errorSettingSSLRandomSeed", SSLRandomSeed, OpenSSLLibrary.getLastError())); + log.warn(sm.getString("openssllibrary.errorSettingSSLRandomSeed", SSLRandomSeed, + OpenSSLLibrary.getLastError())); } } if (!seedDone) { @@ -252,7 +252,8 @@ final boolean enterFipsMode; int fipsModeState = FIPS_OFF; if (openssl_h_Compatibility.OPENSSL3) { - var md = EVP_MD_fetch(MemorySegment.NULL, memorySession.allocateFrom("SHA-512"), MemorySegment.NULL); + var md = EVP_MD_fetch(MemorySegment.NULL, memorySession.allocateFrom("SHA-512"), + MemorySegment.NULL); var provider = EVP_MD_get0_provider(md); String name = OSSL_PROVIDER_get0_name(provider).getString(0); EVP_MD_free(md); @@ -263,7 +264,7 @@ fipsModeState = FIPS_mode(); } - if(log.isDebugEnabled()) { + if (log.isDebugEnabled()) { log.debug(sm.getString("openssllibrary.currentFIPSMode", Integer.valueOf(fipsModeState))); } @@ -281,7 +282,8 @@ enterFipsMode = false; } else { if (openssl_h_Compatibility.OPENSSL3) { - throw new IllegalStateException(sm.getString("openssllibrary.FIPSProviderNotDefault", FIPSMode)); + throw new IllegalStateException( + sm.getString("openssllibrary.FIPSProviderNotDefault", FIPSMode)); } else { enterFipsMode = true; } @@ -292,7 +294,8 @@ enterFipsMode = false; } else { if (openssl_h_Compatibility.OPENSSL3) { - throw new IllegalStateException(sm.getString("openssllibrary.FIPSProviderNotDefault", FIPSMode)); + throw new IllegalStateException( + sm.getString("openssllibrary.FIPSProviderNotDefault", FIPSMode)); } else { throw new IllegalStateException(sm.getString("openssllibrary.requireNotInFIPSMode")); } @@ -300,7 +303,8 @@ } else if ("enter".equalsIgnoreCase(FIPSMode)) { if (fipsModeState == FIPS_OFF) { if (openssl_h_Compatibility.OPENSSL3) { - throw new IllegalStateException(sm.getString("openssllibrary.FIPSProviderNotDefault", FIPSMode)); + throw new IllegalStateException( + sm.getString("openssllibrary.FIPSProviderNotDefault", FIPSMode)); } else { enterFipsMode = true; } @@ -309,13 +313,12 @@ fipsModeActive = true; enterFipsMode = false; } else { - throw new IllegalStateException(sm.getString( - "openssllibrary.enterAlreadyInFIPSMode", Integer.valueOf(fipsModeState))); + throw new IllegalStateException(sm.getString("openssllibrary.enterAlreadyInFIPSMode", + Integer.valueOf(fipsModeState))); } } } else { - throw new IllegalArgumentException(sm.getString( - "openssllibrary.wrongFIPSMode", FIPSMode)); + throw new IllegalArgumentException(sm.getString("openssllibrary.wrongFIPSMode", FIPSMode)); } if (enterFipsMode) { @@ -383,8 +386,7 @@ if (!SSLEngine.equals(OpenSSLLibrary.SSLEngine)) { // Ensure that the SSLEngine is consistent with that used for SSL init if (OpenSSLStatus.isInitialized()) { - throw new IllegalStateException( - sm.getString("openssllibrary.tooLateForSSLEngine")); + throw new IllegalStateException(sm.getString("openssllibrary.tooLateForSSLEngine")); } OpenSSLLibrary.SSLEngine = SSLEngine; @@ -399,8 +401,7 @@ if (!SSLRandomSeed.equals(OpenSSLLibrary.SSLRandomSeed)) { // Ensure that the random seed is consistent with that used for SSL init if (OpenSSLStatus.isInitialized()) { - throw new IllegalStateException( - sm.getString("openssllibrary.tooLateForSSLRandomSeed")); + throw new IllegalStateException(sm.getString("openssllibrary.tooLateForSSLRandomSeed")); } OpenSSLLibrary.SSLRandomSeed = SSLRandomSeed; @@ -415,8 +416,7 @@ if (!FIPSMode.equals(OpenSSLLibrary.FIPSMode)) { // Ensure that the FIPS mode is consistent with that used for SSL init if (OpenSSLStatus.isInitialized()) { - throw new IllegalStateException( - sm.getString("openssllibrary.tooLateForFIPSMode")); + throw new IllegalStateException(sm.getString("openssllibrary.tooLateForFIPSMode")); } OpenSSLLibrary.FIPSMode = FIPSMode; @@ -475,12 +475,11 @@ private static final int OPENSSL_ERROR_MESSAGE_BUFFER_SIZE = 256; /** - * Many calls to SSL methods do not check the last error. Those that do - * check the last error need to ensure that any previously ignored error is - * cleared prior to the method call else errors may be falsely reported. - * Ideally, before any SSL_read, SSL_write, clearLastError should always - * be called, and getLastError should be called after on any negative or - * zero result. + * Many calls to SSL methods do not check the last error. Those that do check the last error need to ensure that any + * previously ignored error is cleared prior to the method call else errors may be falsely reported. Ideally, before + * any SSL_read, SSL_write, clearLastError should always be called, and getLastError should be called after on any + * negative or zero result. + * * @return the first error in the stack */ static String getLastError() { diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/net/openssl/panama/OpenSSLSessionContext.java tomcat10-10.1.52/java/org/apache/tomcat/util/net/openssl/panama/OpenSSLSessionContext.java --- tomcat10-10.1.40/java/org/apache/tomcat/util/net/openssl/panama/OpenSSLSessionContext.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/net/openssl/panama/OpenSSLSessionContext.java 2026-01-23 19:33:36.000000000 +0000 @@ -65,8 +65,8 @@ throw new IllegalArgumentException(sm.getString("sessionContext.nullTicketKeys")); } if (keys.length != TICKET_KEYS_SIZE) { - throw new IllegalArgumentException(sm.getString("sessionContext.invalidTicketKeysLength", - Integer.valueOf(keys.length))); + throw new IllegalArgumentException( + sm.getString("sessionContext.invalidTicketKeysLength", Integer.valueOf(keys.length))); } try (var memorySession = Arena.ofConfined()) { var array = memorySession.allocateFrom(ValueLayout.JAVA_BYTE, keys); @@ -85,8 +85,7 @@ } /** - * @return {@code true} if caching of SSL sessions is enabled, {@code false} - * otherwise. + * @return {@code true} if caching of SSL sessions is enabled, {@code false} otherwise. */ public boolean isSessionCacheEnabled() { return SSL_CTX_get_session_cache_mode(context.getSSLContext()) == SSL_SESS_CACHE_SERVER(); @@ -126,12 +125,13 @@ } /** - * Set the context within which session be reused (server side only) - * See - * man SSL_CTX_set_session_id_context + * Set the context within which session be reused (server side only) See + * man + * SSL_CTX_set_session_id_context + * + * @param sidCtx can be any kind of binary data, it is therefore possible to use e.g. the name of the application + * and/or the hostname and/or service name * - * @param sidCtx can be any kind of binary data, it is therefore possible to use e.g. the name - * of the application and/or the hostname and/or service name * @return {@code true} if success, {@code false} otherwise. */ public boolean setSessionIdContext(byte[] sidCtx) { diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/net/openssl/panama/OpenSSLSessionStats.java tomcat10-10.1.52/java/org/apache/tomcat/util/net/openssl/panama/OpenSSLSessionStats.java --- tomcat10-10.1.40/java/org/apache/tomcat/util/net/openssl/panama/OpenSSLSessionStats.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/net/openssl/panama/OpenSSLSessionStats.java 2026-01-23 19:33:36.000000000 +0000 @@ -44,21 +44,21 @@ * @return The number of started SSL/TLS handshakes in client mode. */ public long connect() { - return SSL_CTX_ctrl(ctx, SSL_CTRL_SESS_CONNECT() ,0, null); + return SSL_CTX_ctrl(ctx, SSL_CTRL_SESS_CONNECT(), 0, null); } /** * @return The number of successfully established SSL/TLS sessions in client mode. */ public long connectGood() { - return SSL_CTX_ctrl(ctx, SSL_CTRL_SESS_CONNECT_GOOD() , 0, null); + return SSL_CTX_ctrl(ctx, SSL_CTRL_SESS_CONNECT_GOOD(), 0, null); } /** * @return The number of start renegotiations in client mode. */ public long connectRenegotiate() { - return SSL_CTX_ctrl(ctx, SSL_CTRL_SESS_CONNECT_RENEGOTIATE() , 0, null); + return SSL_CTX_ctrl(ctx, SSL_CTRL_SESS_CONNECT_RENEGOTIATE(), 0, null); } /** @@ -83,44 +83,40 @@ } /** - * @return The number of successfully reused sessions. In client mode, a - * session set with {@code SSL_set_session} successfully reused is - * counted as a hit. In server mode, a session successfully - * retrieved from internal or external cache is counted as a hit. + * @return The number of successfully reused sessions. In client mode, a session set with {@code SSL_set_session} + * successfully reused is counted as a hit. In server mode, a session successfully retrieved from + * internal or external cache is counted as a hit. */ public long hits() { return SSL_CTX_ctrl(ctx, SSL_CTRL_SESS_HIT(), 0, null); } /** - * @return The number of successfully retrieved sessions from the external - * session cache in server mode. + * @return The number of successfully retrieved sessions from the external session cache in server mode. */ public long cbHits() { return SSL_CTX_ctrl(ctx, SSL_CTRL_SESS_CB_HIT(), 0, null); } /** - * @return The number of sessions proposed by clients that were not found in - * the internal session cache in server mode. + * @return The number of sessions proposed by clients that were not found in the internal session cache in server + * mode. */ public long misses() { return SSL_CTX_ctrl(ctx, SSL_CTRL_SESS_MISSES(), 0, null); } /** - * @return The number of sessions proposed by clients and either found in - * the internal or external session cache in server mode, but that - * were invalid due to timeout. These sessions are not included in - * the {@link #hits()} count. + * @return The number of sessions proposed by clients and either found in the internal or external session cache in + * server mode, but that were invalid due to timeout. These sessions are not included in the + * {@link #hits()} count. */ public long timeouts() { return SSL_CTX_ctrl(ctx, SSL_CTRL_SESS_TIMEOUTS(), 0, null); } /** - * @return The number of sessions that were removed because the maximum - * session cache size was exceeded. + * @return The number of sessions that were removed because the maximum session cache size was exceeded. */ public long cacheFull() { return SSL_CTX_ctrl(ctx, SSL_CTRL_SESS_CACHE_FULL(), 0, null); diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/net/openssl/panama/OpenSSLUtil.java tomcat10-10.1.52/java/org/apache/tomcat/util/net/openssl/panama/OpenSSLUtil.java --- tomcat10-10.1.40/java/org/apache/tomcat/util/net/openssl/panama/OpenSSLUtil.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/net/openssl/panama/OpenSSLUtil.java 2026-01-23 19:33:36.000000000 +0000 @@ -17,6 +17,7 @@ package org.apache.tomcat.util.net.openssl.panama; import java.io.IOException; +import java.security.KeyException; import java.security.KeyStoreException; import java.util.List; import java.util.Set; @@ -80,20 +81,20 @@ // No (or invalid?) certificate chain was provided for the cert String msg = sm.getString("openssl.nonJsseChain", certificate.getCertificateChainFile()); if (log.isDebugEnabled()) { - log.info(msg, e); + log.debug(msg, e); } else { log.info(msg); } return null; - } catch (KeyStoreException | IOException e) { + } catch (KeyStoreException | KeyException | IOException e) { // Depending on what is presented, JSSE may also throw // KeyStoreException or IOException if it doesn't understand the // provided file. if (certificate.getCertificateFile() != null) { - String msg = sm.getString("openssl.nonJsseCertificate", - certificate.getCertificateFile(), certificate.getCertificateKeyFile()); + String msg = sm.getString("openssl.nonJsseCertificate", certificate.getCertificateFile(), + certificate.getCertificateKeyFile()); if (log.isDebugEnabled()) { - log.info(msg, e); + log.debug(msg, e); } else { log.info(msg); } diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/net/openssl/panama/OpenSSLX509Certificate.java tomcat10-10.1.52/java/org/apache/tomcat/util/net/openssl/panama/OpenSSLX509Certificate.java --- tomcat10-10.1.40/java/org/apache/tomcat/util/net/openssl/panama/OpenSSLX509Certificate.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/net/openssl/panama/OpenSSLX509Certificate.java 2026-01-23 19:33:36.000000000 +0000 @@ -134,16 +134,14 @@ } @Override - public void verify(PublicKey key) - throws CertificateException, NoSuchAlgorithmException, - InvalidKeyException, NoSuchProviderException, SignatureException { + public void verify(PublicKey key) throws CertificateException, NoSuchAlgorithmException, InvalidKeyException, + NoSuchProviderException, SignatureException { unwrap().verify(key); } @Override - public void verify(PublicKey key, String sigProvider) - throws CertificateException, NoSuchAlgorithmException, InvalidKeyException, - NoSuchProviderException, SignatureException { + public void verify(PublicKey key, String sigProvider) throws CertificateException, NoSuchAlgorithmException, + InvalidKeyException, NoSuchProviderException, SignatureException { unwrap().verify(key, sigProvider); } @@ -181,8 +179,8 @@ X509Certificate wrapped = this.wrapped; if (wrapped == null) { try { - wrapped = this.wrapped = (X509Certificate) OpenSSLContext.X509_CERT_FACTORY.generateCertificate( - new ByteArrayInputStream(bytes)); + wrapped = this.wrapped = (X509Certificate) OpenSSLContext.X509_CERT_FACTORY + .generateCertificate(new ByteArrayInputStream(bytes)); } catch (CertificateException e) { throw new IllegalStateException(e); } diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/openssl/SSL_CTX_set_alpn_select_cb$cb.java tomcat10-10.1.52/java/org/apache/tomcat/util/openssl/SSL_CTX_set_alpn_select_cb$cb.java --- tomcat10-10.1.40/java/org/apache/tomcat/util/openssl/SSL_CTX_set_alpn_select_cb$cb.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/openssl/SSL_CTX_set_alpn_select_cb$cb.java 2026-01-23 19:33:36.000000000 +0000 @@ -26,32 +26,26 @@ import java.lang.invoke.MethodHandle; /** - * {@snippet lang=c : - * SSL_CTX_alpn_select_cb_func cb + * {@snippet lang = c : * SSL_CTX_alpn_select_cb_func cb * } */ @SuppressWarnings("javadoc") public class SSL_CTX_set_alpn_select_cb$cb { public interface Function { - int apply(MemorySegment _x0, MemorySegment _x1, MemorySegment _x2, MemorySegment _x3, int _x4, MemorySegment _x5); + int apply(MemorySegment _x0, MemorySegment _x1, MemorySegment _x2, MemorySegment _x3, int _x4, + MemorySegment _x5); } - private static final FunctionDescriptor $DESC = FunctionDescriptor.of( - openssl_h.C_INT, - openssl_h.C_POINTER, - openssl_h.C_POINTER, - openssl_h.C_POINTER, - openssl_h.C_POINTER, - openssl_h.C_INT, - openssl_h.C_POINTER - ); + private static final FunctionDescriptor $DESC = FunctionDescriptor.of(openssl_h.C_INT, openssl_h.C_POINTER, + openssl_h.C_POINTER, openssl_h.C_POINTER, openssl_h.C_POINTER, openssl_h.C_INT, openssl_h.C_POINTER); public static FunctionDescriptor descriptor() { return $DESC; } - private static final MethodHandle UP$MH = openssl_h.upcallHandle(SSL_CTX_set_alpn_select_cb$cb.Function.class, "apply", $DESC); + private static final MethodHandle UP$MH = + openssl_h.upcallHandle(SSL_CTX_set_alpn_select_cb$cb.Function.class, "apply", $DESC); public static MemorySegment allocate(SSL_CTX_set_alpn_select_cb$cb.Function fi, Arena scope) { return Linker.nativeLinker().upcallStub(UP$MH.bindTo(fi), $DESC, scope); @@ -59,7 +53,8 @@ private static final MethodHandle DOWN$MH = Linker.nativeLinker().downcallHandle($DESC); - public static int invoke(MemorySegment funcPtr,MemorySegment _x0, MemorySegment _x1, MemorySegment _x2, MemorySegment _x3, int _x4, MemorySegment _x5) { + public static int invoke(MemorySegment funcPtr, MemorySegment _x0, MemorySegment _x1, MemorySegment _x2, + MemorySegment _x3, int _x4, MemorySegment _x5) { try { return (int) DOWN$MH.invokeExact(funcPtr, _x0, _x1, _x2, _x3, _x4, _x5); } catch (Throwable ex$) { diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/openssl/SSL_CTX_set_cert_verify_callback$cb.java tomcat10-10.1.52/java/org/apache/tomcat/util/openssl/SSL_CTX_set_cert_verify_callback$cb.java --- tomcat10-10.1.40/java/org/apache/tomcat/util/openssl/SSL_CTX_set_cert_verify_callback$cb.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/openssl/SSL_CTX_set_cert_verify_callback$cb.java 2026-01-23 19:33:36.000000000 +0000 @@ -26,8 +26,7 @@ import java.lang.invoke.MethodHandle; /** - * {@snippet lang=c : - * int (*cb)(X509_STORE_CTX *, void *) + * {@snippet lang = c : * int (*cb)(X509_STORE_CTX *, void *) * } */ @SuppressWarnings("javadoc") @@ -37,17 +36,15 @@ int apply(MemorySegment _x0, MemorySegment _x1); } - private static final FunctionDescriptor $DESC = FunctionDescriptor.of( - openssl_h.C_INT, - openssl_h.C_POINTER, - openssl_h.C_POINTER - ); + private static final FunctionDescriptor $DESC = + FunctionDescriptor.of(openssl_h.C_INT, openssl_h.C_POINTER, openssl_h.C_POINTER); public static FunctionDescriptor descriptor() { return $DESC; } - private static final MethodHandle UP$MH = openssl_h.upcallHandle(SSL_CTX_set_cert_verify_callback$cb.Function.class, "apply", $DESC); + private static final MethodHandle UP$MH = + openssl_h.upcallHandle(SSL_CTX_set_cert_verify_callback$cb.Function.class, "apply", $DESC); public static MemorySegment allocate(SSL_CTX_set_cert_verify_callback$cb.Function fi, Arena scope) { return Linker.nativeLinker().upcallStub(UP$MH.bindTo(fi), $DESC, scope); @@ -55,7 +52,7 @@ private static final MethodHandle DOWN$MH = Linker.nativeLinker().downcallHandle($DESC); - public static int invoke(MemorySegment funcPtr,MemorySegment _x0, MemorySegment _x1) { + public static int invoke(MemorySegment funcPtr, MemorySegment _x0, MemorySegment _x1) { try { return (int) DOWN$MH.invokeExact(funcPtr, _x0, _x1); } catch (Throwable ex$) { diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/openssl/SSL_CTX_set_tmp_dh_callback$dh.java tomcat10-10.1.52/java/org/apache/tomcat/util/openssl/SSL_CTX_set_tmp_dh_callback$dh.java --- tomcat10-10.1.40/java/org/apache/tomcat/util/openssl/SSL_CTX_set_tmp_dh_callback$dh.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/openssl/SSL_CTX_set_tmp_dh_callback$dh.java 2026-01-23 19:33:36.000000000 +0000 @@ -26,8 +26,7 @@ import java.lang.invoke.MethodHandle; /** - * {@snippet lang=c : - * DH *(*dh)(SSL *, int, int) + * {@snippet lang = c : * DH *(*dh)(SSL *, int, int) * } */ @SuppressWarnings("javadoc") @@ -37,18 +36,15 @@ MemorySegment apply(MemorySegment _x0, int _x1, int _x2); } - private static final FunctionDescriptor $DESC = FunctionDescriptor.of( - openssl_h.C_POINTER, - openssl_h.C_POINTER, - openssl_h.C_INT, - openssl_h.C_INT - ); + private static final FunctionDescriptor $DESC = + FunctionDescriptor.of(openssl_h.C_POINTER, openssl_h.C_POINTER, openssl_h.C_INT, openssl_h.C_INT); public static FunctionDescriptor descriptor() { return $DESC; } - private static final MethodHandle UP$MH = openssl_h.upcallHandle(SSL_CTX_set_tmp_dh_callback$dh.Function.class, "apply", $DESC); + private static final MethodHandle UP$MH = + openssl_h.upcallHandle(SSL_CTX_set_tmp_dh_callback$dh.Function.class, "apply", $DESC); public static MemorySegment allocate(SSL_CTX_set_tmp_dh_callback$dh.Function fi, Arena scope) { return Linker.nativeLinker().upcallStub(UP$MH.bindTo(fi), $DESC, scope); @@ -56,7 +52,7 @@ private static final MethodHandle DOWN$MH = Linker.nativeLinker().downcallHandle($DESC); - public static MemorySegment invoke(MemorySegment funcPtr,MemorySegment _x0, int _x1, int _x2) { + public static MemorySegment invoke(MemorySegment funcPtr, MemorySegment _x0, int _x1, int _x2) { try { return (MemorySegment) DOWN$MH.invokeExact(funcPtr, _x0, _x1, _x2); } catch (Throwable ex$) { diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/openssl/SSL_CTX_set_verify$callback.java tomcat10-10.1.52/java/org/apache/tomcat/util/openssl/SSL_CTX_set_verify$callback.java --- tomcat10-10.1.40/java/org/apache/tomcat/util/openssl/SSL_CTX_set_verify$callback.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/openssl/SSL_CTX_set_verify$callback.java 2026-01-23 19:33:36.000000000 +0000 @@ -26,8 +26,7 @@ import java.lang.invoke.MethodHandle; /** - * {@snippet lang=c : - * SSL_verify_cb callback + * {@snippet lang = c : * SSL_verify_cb callback * } */ @SuppressWarnings("javadoc") @@ -37,17 +36,15 @@ int apply(int _x0, MemorySegment _x1); } - private static final FunctionDescriptor $DESC = FunctionDescriptor.of( - openssl_h.C_INT, - openssl_h.C_INT, - openssl_h.C_POINTER - ); + private static final FunctionDescriptor $DESC = + FunctionDescriptor.of(openssl_h.C_INT, openssl_h.C_INT, openssl_h.C_POINTER); public static FunctionDescriptor descriptor() { return $DESC; } - private static final MethodHandle UP$MH = openssl_h.upcallHandle(SSL_CTX_set_verify$callback.Function.class, "apply", $DESC); + private static final MethodHandle UP$MH = + openssl_h.upcallHandle(SSL_CTX_set_verify$callback.Function.class, "apply", $DESC); public static MemorySegment allocate(SSL_CTX_set_verify$callback.Function fi, Arena scope) { return Linker.nativeLinker().upcallStub(UP$MH.bindTo(fi), $DESC, scope); @@ -55,7 +52,7 @@ private static final MethodHandle DOWN$MH = Linker.nativeLinker().downcallHandle($DESC); - public static int invoke(MemorySegment funcPtr,int _x0, MemorySegment _x1) { + public static int invoke(MemorySegment funcPtr, int _x0, MemorySegment _x1) { try { return (int) DOWN$MH.invokeExact(funcPtr, _x0, _x1); } catch (Throwable ex$) { diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/openssl/SSL_set_info_callback$cb.java tomcat10-10.1.52/java/org/apache/tomcat/util/openssl/SSL_set_info_callback$cb.java --- tomcat10-10.1.40/java/org/apache/tomcat/util/openssl/SSL_set_info_callback$cb.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/openssl/SSL_set_info_callback$cb.java 2026-01-23 19:33:36.000000000 +0000 @@ -26,8 +26,7 @@ import java.lang.invoke.MethodHandle; /** - * {@snippet lang=c : - * void (*cb)(const SSL *, int, int) + * {@snippet lang = c : * void (*cb)(const SSL *, int, int) * } */ @SuppressWarnings("javadoc") @@ -37,17 +36,15 @@ void apply(MemorySegment _x0, int _x1, int _x2); } - private static final FunctionDescriptor $DESC = FunctionDescriptor.ofVoid( - openssl_h.C_POINTER, - openssl_h.C_INT, - openssl_h.C_INT - ); + private static final FunctionDescriptor $DESC = + FunctionDescriptor.ofVoid(openssl_h.C_POINTER, openssl_h.C_INT, openssl_h.C_INT); public static FunctionDescriptor descriptor() { return $DESC; } - private static final MethodHandle UP$MH = openssl_h.upcallHandle(SSL_set_info_callback$cb.Function.class, "apply", $DESC); + private static final MethodHandle UP$MH = + openssl_h.upcallHandle(SSL_set_info_callback$cb.Function.class, "apply", $DESC); public static MemorySegment allocate(SSL_set_info_callback$cb.Function fi, Arena scope) { return Linker.nativeLinker().upcallStub(UP$MH.bindTo(fi), $DESC, scope); @@ -55,9 +52,9 @@ private static final MethodHandle DOWN$MH = Linker.nativeLinker().downcallHandle($DESC); - public static void invoke(MemorySegment funcPtr,MemorySegment _x0, int _x1, int _x2) { + public static void invoke(MemorySegment funcPtr, MemorySegment _x0, int _x1, int _x2) { try { - DOWN$MH.invokeExact(funcPtr, _x0, _x1, _x2); + DOWN$MH.invokeExact(funcPtr, _x0, _x1, _x2); } catch (Throwable ex$) { throw new AssertionError("should not reach here", ex$); } diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/openssl/SSL_set_verify$callback.java tomcat10-10.1.52/java/org/apache/tomcat/util/openssl/SSL_set_verify$callback.java --- tomcat10-10.1.40/java/org/apache/tomcat/util/openssl/SSL_set_verify$callback.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/openssl/SSL_set_verify$callback.java 2026-01-23 19:33:36.000000000 +0000 @@ -26,8 +26,7 @@ import java.lang.invoke.MethodHandle; /** - * {@snippet lang=c : - * SSL_verify_cb callback + * {@snippet lang = c : * SSL_verify_cb callback * } */ @SuppressWarnings("javadoc") @@ -37,17 +36,15 @@ int apply(int _x0, MemorySegment _x1); } - private static final FunctionDescriptor $DESC = FunctionDescriptor.of( - openssl_h.C_INT, - openssl_h.C_INT, - openssl_h.C_POINTER - ); + private static final FunctionDescriptor $DESC = + FunctionDescriptor.of(openssl_h.C_INT, openssl_h.C_INT, openssl_h.C_POINTER); public static FunctionDescriptor descriptor() { return $DESC; } - private static final MethodHandle UP$MH = openssl_h.upcallHandle(SSL_set_verify$callback.Function.class, "apply", $DESC); + private static final MethodHandle UP$MH = + openssl_h.upcallHandle(SSL_set_verify$callback.Function.class, "apply", $DESC); public static MemorySegment allocate(SSL_set_verify$callback.Function fi, Arena scope) { return Linker.nativeLinker().upcallStub(UP$MH.bindTo(fi), $DESC, scope); @@ -55,7 +52,7 @@ private static final MethodHandle DOWN$MH = Linker.nativeLinker().downcallHandle($DESC); - public static int invoke(MemorySegment funcPtr,int _x0, MemorySegment _x1) { + public static int invoke(MemorySegment funcPtr, int _x0, MemorySegment _x1) { try { return (int) DOWN$MH.invokeExact(funcPtr, _x0, _x1); } catch (Throwable ex$) { diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/openssl/openssl_h.java tomcat10-10.1.52/java/org/apache/tomcat/util/openssl/openssl_h.java --- tomcat10-10.1.40/java/org/apache/tomcat/util/openssl/openssl_h.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/openssl/openssl_h.java 2026-01-23 19:33:36.000000000 +0000 @@ -29,70 +29,23 @@ import java.lang.foreign.*; import static java.lang.foreign.ValueLayout.*; -@SuppressWarnings({"javadoc", "boxing"}) +@SuppressWarnings({ "javadoc", "boxing" }) public class openssl_h { - /* - * On macOS SymbolLookup.libraryLookup() appears to ignore java.library.path which means the LibreSSL - * library will be found which will then fail. Therefore, skip that lookup on macOS. - * On other platforms this can also be used to give more flexibility when testing. - */ - public static final boolean USE_SYSTEM_LOAD_LIBRARY = Boolean.getBoolean("org.apache.tomcat.util.openssl.USE_SYSTEM_LOAD_LIBRARY"); - public static final String CRYPTO_LIBRARY_NAME = System.getProperty("org.apache.tomcat.util.openssl.CRYPTO_LIBRARY_NAME"); - public static final String LIBRARY_NAME = System.getProperty("org.apache.tomcat.util.openssl.LIBRARY_NAME", - (JrePlatform.IS_MAC_OS) ? "ssl.48" : "ssl"); - openssl_h() { - // Suppresses public default constructor, ensuring non-instantiability, - // but allows generated subclasses in same package. + // Should not be called directly } - public static final ValueLayout.OfBoolean C_BOOL = ValueLayout.JAVA_BOOLEAN; - public static final ValueLayout.OfByte C_CHAR = ValueLayout.JAVA_BYTE; - public static final ValueLayout.OfShort C_SHORT = ValueLayout.JAVA_SHORT; - public static final ValueLayout.OfInt C_INT = ValueLayout.JAVA_INT; - public static final ValueLayout.OfLong C_LONG_LONG = ValueLayout.JAVA_LONG; - public static final ValueLayout.OfFloat C_FLOAT = ValueLayout.JAVA_FLOAT; - public static final ValueLayout.OfDouble C_DOUBLE = ValueLayout.JAVA_DOUBLE; - public static final AddressLayout C_POINTER = ValueLayout.ADDRESS - .withTargetLayout(MemoryLayout.sequenceLayout(java.lang.Long.MAX_VALUE, JAVA_BYTE)); - public static final ValueLayout.OfLong C_LONG = ValueLayout.JAVA_LONG; - static final Arena LIBRARY_ARENA = Arena.ofAuto(); static final boolean TRACE_DOWNCALLS = Boolean.getBoolean("jextract.trace.downcalls"); - static final SymbolLookup SYMBOL_LOOKUP; - static { - if (USE_SYSTEM_LOAD_LIBRARY) { - if (CRYPTO_LIBRARY_NAME != null) { - System.loadLibrary(CRYPTO_LIBRARY_NAME); - } - System.loadLibrary(LIBRARY_NAME); - SYMBOL_LOOKUP = SymbolLookup.loaderLookup().or(Linker.nativeLinker().defaultLookup()); - } else { - SYMBOL_LOOKUP = SymbolLookup.libraryLookup(System.mapLibraryName(LIBRARY_NAME), LIBRARY_ARENA) - .or(SymbolLookup.loaderLookup()) - .or(Linker.nativeLinker().defaultLookup()); - } - } static void traceDowncall(String name, Object... args) { - String traceArgs = Arrays.stream(args) - .map(Object::toString) - .collect(Collectors.joining(", ")); - System.out.printf("%s(%s)\n", name, traceArgs); + String traceArgs = Arrays.stream(args).map(Object::toString).collect(Collectors.joining(", ")); + System.out.printf("%s(%s)\n", name, traceArgs); } static MemorySegment findOrThrow(String symbol) { - return SYMBOL_LOOKUP.find(symbol) - .orElseThrow(() -> new UnsatisfiedLinkError("unresolved symbol: " + symbol)); - } - - static MemoryLayout[] inferVariadicLayouts(Object[] varargs) { - MemoryLayout[] result = new MemoryLayout[varargs.length]; - for (int i = 0; i < varargs.length; i++) { - result[i] = variadicLayout(varargs[i].getClass()); - } - return result; + return SYMBOL_LOOKUP.find(symbol).orElseThrow(() -> new UnsatisfiedLinkError("unresolved symbol: " + symbol)); } static MethodHandle upcallHandle(Class fi, String name, FunctionDescriptor fdesc) { @@ -103,6382 +56,10111 @@ } } - static MethodHandle downcallHandleVariadic(String name, FunctionDescriptor baseDesc, MemoryLayout[] variadicLayouts) { - FunctionDescriptor variadicDesc = baseDesc.appendArgumentLayouts(variadicLayouts); - Linker.Option fva = Linker.Option.firstVariadicArg(baseDesc.argumentLayouts().size()); - return SYMBOL_LOOKUP.find(name) - .map(addr -> Linker.nativeLinker().downcallHandle(addr, variadicDesc, fva) - .asSpreader(Object[].class, variadicLayouts.length)) - .orElse(null); - } - - // Internals only below this point - - private static MemoryLayout variadicLayout(Class c) { - // apply default argument promotions per C spec - // note that all primitives are boxed, since they are passed through an Object[] - if (c == Boolean.class || c == Byte.class || c == Character.class || c == Short.class || c == Integer.class) { - return JAVA_INT; - } else if (c == Long.class) { - return JAVA_LONG; - } else if (c == Float.class || c == Double.class) { - return JAVA_DOUBLE; - } else if (MemorySegment.class.isAssignableFrom(c)) { - return ADDRESS; + static MemoryLayout align(MemoryLayout layout, long align) { + return switch (layout) { + case PaddingLayout p -> p; + case ValueLayout v -> v.withByteAlignment(align); + case GroupLayout g -> { + MemoryLayout[] alignedMembers = + g.memberLayouts().stream().map(m -> align(m, align)).toArray(MemoryLayout[]::new); + yield g instanceof StructLayout ? MemoryLayout.structLayout(alignedMembers) : + MemoryLayout.unionLayout(alignedMembers); + } + case SequenceLayout s -> MemoryLayout.sequenceLayout(s.elementCount(), align(s.elementLayout(), align)); + }; + } + + /* + * On macOS SymbolLookup.libraryLookup() appears to ignore java.library.path which means the LibreSSL library will + * be found which will then fail. Therefore, skip that lookup on macOS. On other platforms this can also be used to + * give more flexibility when testing. + */ + public static final boolean USE_SYSTEM_LOAD_LIBRARY = + Boolean.getBoolean("org.apache.tomcat.util.openssl.USE_SYSTEM_LOAD_LIBRARY"); + public static final String CRYPTO_LIBRARY_NAME = + System.getProperty("org.apache.tomcat.util.openssl.CRYPTO_LIBRARY_NAME"); + public static final String LIBRARY_NAME = System.getProperty("org.apache.tomcat.util.openssl.LIBRARY_NAME", + (JrePlatform.IS_MAC_OS) ? "ssl.48" : "ssl"); + + static final SymbolLookup SYMBOL_LOOKUP; + static { + if (USE_SYSTEM_LOAD_LIBRARY) { + if (CRYPTO_LIBRARY_NAME != null) { + System.loadLibrary(CRYPTO_LIBRARY_NAME); + } + System.loadLibrary(LIBRARY_NAME); + SYMBOL_LOOKUP = SymbolLookup.loaderLookup().or(Linker.nativeLinker().defaultLookup()); + } else { + SYMBOL_LOOKUP = SymbolLookup.libraryLookup(System.mapLibraryName(LIBRARY_NAME), LIBRARY_ARENA) + .or(SymbolLookup.loaderLookup()).or(Linker.nativeLinker().defaultLookup()); } - throw new IllegalArgumentException("Invalid type for ABI: " + c.getTypeName()); } - private static final int BIO_CLOSE = (int)1L; + + public static final ValueLayout.OfBoolean C_BOOL = ValueLayout.JAVA_BOOLEAN; + public static final ValueLayout.OfByte C_CHAR = ValueLayout.JAVA_BYTE; + public static final ValueLayout.OfShort C_SHORT = ValueLayout.JAVA_SHORT; + public static final ValueLayout.OfInt C_INT = ValueLayout.JAVA_INT; + public static final ValueLayout.OfLong C_LONG_LONG = ValueLayout.JAVA_LONG; + public static final ValueLayout.OfFloat C_FLOAT = ValueLayout.JAVA_FLOAT; + public static final ValueLayout.OfDouble C_DOUBLE = ValueLayout.JAVA_DOUBLE; + public static final AddressLayout C_POINTER = + ValueLayout.ADDRESS.withTargetLayout(MemoryLayout.sequenceLayout(java.lang.Long.MAX_VALUE, JAVA_BYTE)); + public static final ValueLayout.OfLong C_LONG = ValueLayout.JAVA_LONG; + private static final int BIO_CLOSE = (int) 1L; + /** - * {@snippet lang=c : - * #define BIO_CLOSE 1 + * {@snippet lang = c : * #define BIO_CLOSE 1 * } */ public static int BIO_CLOSE() { return BIO_CLOSE; } - private static final int BIO_CTRL_RESET = (int)1L; + + private static final int BIO_CTRL_RESET = (int) 1L; + /** - * {@snippet lang=c : - * #define BIO_CTRL_RESET 1 + * {@snippet lang = c : * #define BIO_CTRL_RESET 1 * } */ public static int BIO_CTRL_RESET() { return BIO_CTRL_RESET; } - private static final int BIO_FP_READ = (int)2L; + + private static final int BIO_FP_READ = (int) 2L; + /** - * {@snippet lang=c : - * #define BIO_FP_READ 2 + * {@snippet lang = c : * #define BIO_FP_READ 2 * } */ public static int BIO_FP_READ() { return BIO_FP_READ; } - private static final int BIO_C_SET_FILENAME = (int)108L; + + private static final int BIO_C_SET_FILENAME = (int) 108L; + /** - * {@snippet lang=c : - * #define BIO_C_SET_FILENAME 108 + * {@snippet lang = c : * #define BIO_C_SET_FILENAME 108 * } */ public static int BIO_C_SET_FILENAME() { return BIO_C_SET_FILENAME; } - private static final int NID_info_access = (int)177L; + + private static final int NID_info_access = (int) 177L; + /** - * {@snippet lang=c : - * #define NID_info_access 177 + * {@snippet lang = c : * #define NID_info_access 177 * } */ public static int NID_info_access() { return NID_info_access; } - private static final int X509_FILETYPE_PEM = (int)1L; + + private static final int X509_FILETYPE_PEM = (int) 1L; + /** - * {@snippet lang=c : - * #define X509_FILETYPE_PEM 1 + * {@snippet lang = c : * #define X509_FILETYPE_PEM 1 * } */ public static int X509_FILETYPE_PEM() { return X509_FILETYPE_PEM; } - private static final int X509_L_FILE_LOAD = (int)1L; + + private static final int X509_L_FILE_LOAD = (int) 1L; + /** - * {@snippet lang=c : - * #define X509_L_FILE_LOAD 1 + * {@snippet lang = c : * #define X509_L_FILE_LOAD 1 * } */ public static int X509_L_FILE_LOAD() { return X509_L_FILE_LOAD; } - private static final int X509_L_ADD_DIR = (int)2L; + + private static final int X509_L_ADD_DIR = (int) 2L; + /** - * {@snippet lang=c : - * #define X509_L_ADD_DIR 2 + * {@snippet lang = c : * #define X509_L_ADD_DIR 2 * } */ public static int X509_L_ADD_DIR() { return X509_L_ADD_DIR; } - private static final int X509_V_OK = (int)0L; + + private static final int X509_V_OK = (int) 0L; + /** - * {@snippet lang=c : - * #define X509_V_OK 0 + * {@snippet lang = c : * #define X509_V_OK 0 * } */ public static int X509_V_OK() { return X509_V_OK; } - private static final int X509_V_ERR_CRL_HAS_EXPIRED = (int)12L; + + private static final int X509_V_ERR_UNABLE_TO_GET_CRL = (int) 3L; + /** - * {@snippet lang=c : - * #define X509_V_ERR_CRL_HAS_EXPIRED 12 + * {@snippet lang = c : * #define X509_V_ERR_UNABLE_TO_GET_CRL 3 + * } + */ + public static int X509_V_ERR_UNABLE_TO_GET_CRL() { + return X509_V_ERR_UNABLE_TO_GET_CRL; + } + + private static final int X509_V_ERR_CRL_HAS_EXPIRED = (int) 12L; + + /** + * {@snippet lang = c : * #define X509_V_ERR_CRL_HAS_EXPIRED 12 * } */ public static int X509_V_ERR_CRL_HAS_EXPIRED() { return X509_V_ERR_CRL_HAS_EXPIRED; } - private static final int X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT = (int)18L; + + private static final int X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT = (int) 18L; + /** - * {@snippet lang=c : - * #define X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT 18 + * {@snippet lang = c : * #define X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT 18 * } */ public static int X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT() { return X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT; } - private static final int X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN = (int)19L; + + private static final int X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN = (int) 19L; + /** - * {@snippet lang=c : - * #define X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN 19 + * {@snippet lang = c : * #define X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN 19 * } */ public static int X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN() { return X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN; } - private static final int X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY = (int)20L; + + private static final int X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY = (int) 20L; + /** - * {@snippet lang=c : - * #define X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY 20 + * {@snippet lang = c : * #define X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY 20 * } */ public static int X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY() { return X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY; } - private static final int X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE = (int)21L; + + private static final int X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE = (int) 21L; + /** - * {@snippet lang=c : - * #define X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE 21 + * {@snippet lang = c : * #define X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE 21 * } */ public static int X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE() { return X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE; } - private static final int X509_V_ERR_CERT_UNTRUSTED = (int)27L; + + private static final int X509_V_ERR_CERT_REVOKED = (int) 23L; + + /** + * {@snippet lang = c : * #define X509_V_ERR_CERT_REVOKED 23 + * } + */ + public static int X509_V_ERR_CERT_REVOKED() { + return X509_V_ERR_CERT_REVOKED; + } + + private static final int X509_V_ERR_CERT_UNTRUSTED = (int) 27L; + /** - * {@snippet lang=c : - * #define X509_V_ERR_CERT_UNTRUSTED 27 + * {@snippet lang = c : * #define X509_V_ERR_CERT_UNTRUSTED 27 * } */ public static int X509_V_ERR_CERT_UNTRUSTED() { return X509_V_ERR_CERT_UNTRUSTED; } - private static final int X509_V_ERR_APPLICATION_VERIFICATION = (int)50L; + + private static final int X509_V_ERR_APPLICATION_VERIFICATION = (int) 50L; + /** - * {@snippet lang=c : - * #define X509_V_ERR_APPLICATION_VERIFICATION 50 + * {@snippet lang = c : * #define X509_V_ERR_APPLICATION_VERIFICATION 50 * } */ public static int X509_V_ERR_APPLICATION_VERIFICATION() { return X509_V_ERR_APPLICATION_VERIFICATION; } - private static final int X509_V_FLAG_CRL_CHECK = (int)4L; + + private static final int X509_V_ERR_OCSP_RESP_INVALID = (int) 96L; + /** - * {@snippet lang=c : - * #define X509_V_FLAG_CRL_CHECK 4 + * {@snippet lang = c : * #define X509_V_ERR_OCSP_RESP_INVALID 96 + * } + */ + public static int X509_V_ERR_OCSP_RESP_INVALID() { + return X509_V_ERR_OCSP_RESP_INVALID; + } + + private static final int X509_V_ERR_OCSP_SIGNATURE_FAILURE = (int) 97L; + + /** + * {@snippet lang = c : * #define X509_V_ERR_OCSP_SIGNATURE_FAILURE 97 + * } + */ + public static int X509_V_ERR_OCSP_SIGNATURE_FAILURE() { + return X509_V_ERR_OCSP_SIGNATURE_FAILURE; + } + + private static final int X509_V_ERR_OCSP_NOT_YET_VALID = (int) 98L; + + /** + * {@snippet lang = c : * #define X509_V_ERR_OCSP_NOT_YET_VALID 98 + * } + */ + public static int X509_V_ERR_OCSP_NOT_YET_VALID() { + return X509_V_ERR_OCSP_NOT_YET_VALID; + } + + private static final int X509_V_ERR_OCSP_HAS_EXPIRED = (int) 99L; + + /** + * {@snippet lang = c : * #define X509_V_ERR_OCSP_HAS_EXPIRED 99 + * } + */ + public static int X509_V_ERR_OCSP_HAS_EXPIRED() { + return X509_V_ERR_OCSP_HAS_EXPIRED; + } + + private static final int X509_V_FLAG_CRL_CHECK = (int) 4L; + + /** + * {@snippet lang = c : * #define X509_V_FLAG_CRL_CHECK 4 * } */ public static int X509_V_FLAG_CRL_CHECK() { return X509_V_FLAG_CRL_CHECK; } - private static final int X509_V_FLAG_CRL_CHECK_ALL = (int)8L; + + private static final int X509_V_FLAG_CRL_CHECK_ALL = (int) 8L; + /** - * {@snippet lang=c : - * #define X509_V_FLAG_CRL_CHECK_ALL 8 + * {@snippet lang = c : * #define X509_V_FLAG_CRL_CHECK_ALL 8 * } */ public static int X509_V_FLAG_CRL_CHECK_ALL() { return X509_V_FLAG_CRL_CHECK_ALL; } - private static final int PEM_R_NO_START_LINE = (int)108L; + + private static final int PEM_R_NO_START_LINE = (int) 108L; + /** - * {@snippet lang=c : - * #define PEM_R_NO_START_LINE 108 + * {@snippet lang = c : * #define PEM_R_NO_START_LINE 108 * } */ public static int PEM_R_NO_START_LINE() { return PEM_R_NO_START_LINE; } - private static final int SSL3_VERSION = (int)768L; + + private static final int SSL3_VERSION = (int) 768L; + /** - * {@snippet lang=c : - * #define SSL3_VERSION 768 + * {@snippet lang = c : * #define SSL3_VERSION 768 * } */ public static int SSL3_VERSION() { return SSL3_VERSION; } - private static final int TLS1_VERSION = (int)769L; + + private static final int TLS1_VERSION = (int) 769L; + /** - * {@snippet lang=c : - * #define TLS1_VERSION 769 + * {@snippet lang = c : * #define TLS1_VERSION 769 * } */ public static int TLS1_VERSION() { return TLS1_VERSION; } - private static final int TLS1_1_VERSION = (int)770L; + + private static final int TLS1_1_VERSION = (int) 770L; + /** - * {@snippet lang=c : - * #define TLS1_1_VERSION 770 + * {@snippet lang = c : * #define TLS1_1_VERSION 770 * } */ public static int TLS1_1_VERSION() { return TLS1_1_VERSION; } - private static final int TLS1_2_VERSION = (int)771L; + + private static final int TLS1_2_VERSION = (int) 771L; + /** - * {@snippet lang=c : - * #define TLS1_2_VERSION 771 + * {@snippet lang = c : * #define TLS1_2_VERSION 771 * } */ public static int TLS1_2_VERSION() { return TLS1_2_VERSION; } - private static final int TLS1_3_VERSION = (int)772L; + + private static final int TLS1_3_VERSION = (int) 772L; + /** - * {@snippet lang=c : - * #define TLS1_3_VERSION 772 + * {@snippet lang = c : * #define TLS1_3_VERSION 772 * } */ public static int TLS1_3_VERSION() { return TLS1_3_VERSION; } - private static final int SSL_SENT_SHUTDOWN = (int)1L; + + private static final int SSL_SENT_SHUTDOWN = (int) 1L; + /** - * {@snippet lang=c : - * #define SSL_SENT_SHUTDOWN 1 + * {@snippet lang = c : * #define SSL_SENT_SHUTDOWN 1 * } */ public static int SSL_SENT_SHUTDOWN() { return SSL_SENT_SHUTDOWN; } - private static final int SSL_RECEIVED_SHUTDOWN = (int)2L; + + private static final int SSL_RECEIVED_SHUTDOWN = (int) 2L; + /** - * {@snippet lang=c : - * #define SSL_RECEIVED_SHUTDOWN 2 + * {@snippet lang = c : * #define SSL_RECEIVED_SHUTDOWN 2 * } */ public static int SSL_RECEIVED_SHUTDOWN() { return SSL_RECEIVED_SHUTDOWN; } - private static final int SSL_OP_SINGLE_ECDH_USE = (int)0L; + + private static final int SSL_OP_SINGLE_ECDH_USE = (int) 0L; + /** - * {@snippet lang=c : - * #define SSL_OP_SINGLE_ECDH_USE 0 + * {@snippet lang = c : * #define SSL_OP_SINGLE_ECDH_USE 0 * } */ public static int SSL_OP_SINGLE_ECDH_USE() { return SSL_OP_SINGLE_ECDH_USE; } - private static final int SSL_OP_SINGLE_DH_USE = (int)0L; + + private static final int SSL_OP_SINGLE_DH_USE = (int) 0L; + /** - * {@snippet lang=c : - * #define SSL_OP_SINGLE_DH_USE 0 + * {@snippet lang = c : * #define SSL_OP_SINGLE_DH_USE 0 * } */ public static int SSL_OP_SINGLE_DH_USE() { return SSL_OP_SINGLE_DH_USE; } - private static final int SSL_OP_NO_SSLv2 = (int)0L; + + private static final int SSL_OP_NO_SSLv2 = (int) 0L; + /** - * {@snippet lang=c : - * #define SSL_OP_NO_SSLv2 0 + * {@snippet lang = c : * #define SSL_OP_NO_SSLv2 0 * } */ public static int SSL_OP_NO_SSLv2() { return SSL_OP_NO_SSLv2; } - private static final int SSL_CONF_FLAG_FILE = (int)2L; + + private static final int SSL_CONF_FLAG_FILE = (int) 2L; + /** - * {@snippet lang=c : - * #define SSL_CONF_FLAG_FILE 2 + * {@snippet lang = c : * #define SSL_CONF_FLAG_FILE 2 * } */ public static int SSL_CONF_FLAG_FILE() { return SSL_CONF_FLAG_FILE; } - private static final int SSL_CONF_FLAG_SERVER = (int)8L; + + private static final int SSL_CONF_FLAG_SERVER = (int) 8L; + /** - * {@snippet lang=c : - * #define SSL_CONF_FLAG_SERVER 8 + * {@snippet lang = c : * #define SSL_CONF_FLAG_SERVER 8 * } */ public static int SSL_CONF_FLAG_SERVER() { return SSL_CONF_FLAG_SERVER; } - private static final int SSL_CONF_FLAG_SHOW_ERRORS = (int)16L; + + private static final int SSL_CONF_FLAG_SHOW_ERRORS = (int) 16L; + /** - * {@snippet lang=c : - * #define SSL_CONF_FLAG_SHOW_ERRORS 16 + * {@snippet lang = c : * #define SSL_CONF_FLAG_SHOW_ERRORS 16 * } */ public static int SSL_CONF_FLAG_SHOW_ERRORS() { return SSL_CONF_FLAG_SHOW_ERRORS; } - private static final int SSL_CONF_FLAG_CERTIFICATE = (int)32L; + + private static final int SSL_CONF_FLAG_CERTIFICATE = (int) 32L; + /** - * {@snippet lang=c : - * #define SSL_CONF_FLAG_CERTIFICATE 32 + * {@snippet lang = c : * #define SSL_CONF_FLAG_CERTIFICATE 32 * } */ public static int SSL_CONF_FLAG_CERTIFICATE() { return SSL_CONF_FLAG_CERTIFICATE; } - private static final int SSL_CONF_TYPE_UNKNOWN = (int)0L; + + private static final int SSL_CONF_TYPE_UNKNOWN = (int) 0L; + /** - * {@snippet lang=c : - * #define SSL_CONF_TYPE_UNKNOWN 0 + * {@snippet lang = c : * #define SSL_CONF_TYPE_UNKNOWN 0 * } */ public static int SSL_CONF_TYPE_UNKNOWN() { return SSL_CONF_TYPE_UNKNOWN; } - private static final int SSL_CONF_TYPE_FILE = (int)2L; + + private static final int SSL_CONF_TYPE_FILE = (int) 2L; + /** - * {@snippet lang=c : - * #define SSL_CONF_TYPE_FILE 2 + * {@snippet lang = c : * #define SSL_CONF_TYPE_FILE 2 * } */ public static int SSL_CONF_TYPE_FILE() { return SSL_CONF_TYPE_FILE; } - private static final int SSL_CONF_TYPE_DIR = (int)3L; + + private static final int SSL_CONF_TYPE_DIR = (int) 3L; + /** - * {@snippet lang=c : - * #define SSL_CONF_TYPE_DIR 3 + * {@snippet lang = c : * #define SSL_CONF_TYPE_DIR 3 * } */ public static int SSL_CONF_TYPE_DIR() { return SSL_CONF_TYPE_DIR; } - private static final int SSL_SESS_CACHE_OFF = (int)0L; + + private static final int SSL_SESS_CACHE_OFF = (int) 0L; + /** - * {@snippet lang=c : - * #define SSL_SESS_CACHE_OFF 0 + * {@snippet lang = c : * #define SSL_SESS_CACHE_OFF 0 * } */ public static int SSL_SESS_CACHE_OFF() { return SSL_SESS_CACHE_OFF; } - private static final int SSL_SESS_CACHE_SERVER = (int)2L; + + private static final int SSL_SESS_CACHE_SERVER = (int) 2L; + /** - * {@snippet lang=c : - * #define SSL_SESS_CACHE_SERVER 2 + * {@snippet lang = c : * #define SSL_SESS_CACHE_SERVER 2 * } */ public static int SSL_SESS_CACHE_SERVER() { return SSL_SESS_CACHE_SERVER; } - private static final int SSL2_VERSION = (int)2L; + + private static final int SSL2_VERSION = (int) 2L; + /** - * {@snippet lang=c : - * #define SSL2_VERSION 2 + * {@snippet lang = c : * #define SSL2_VERSION 2 * } */ public static int SSL2_VERSION() { return SSL2_VERSION; } - private static final int SSL_TLSEXT_ERR_OK = (int)0L; + + private static final int SSL_TLSEXT_ERR_OK = (int) 0L; + /** - * {@snippet lang=c : - * #define SSL_TLSEXT_ERR_OK 0 + * {@snippet lang = c : * #define SSL_TLSEXT_ERR_OK 0 * } */ public static int SSL_TLSEXT_ERR_OK() { return SSL_TLSEXT_ERR_OK; } - private static final int SSL_TLSEXT_ERR_NOACK = (int)3L; + + private static final int SSL_TLSEXT_ERR_NOACK = (int) 3L; + /** - * {@snippet lang=c : - * #define SSL_TLSEXT_ERR_NOACK 3 + * {@snippet lang = c : * #define SSL_TLSEXT_ERR_NOACK 3 * } */ public static int SSL_TLSEXT_ERR_NOACK() { return SSL_TLSEXT_ERR_NOACK; } - private static final int SSL_CB_HANDSHAKE_DONE = (int)32L; + + private static final int SSL_CB_HANDSHAKE_DONE = (int) 32L; + /** - * {@snippet lang=c : - * #define SSL_CB_HANDSHAKE_DONE 32 + * {@snippet lang = c : * #define SSL_CB_HANDSHAKE_DONE 32 * } */ public static int SSL_CB_HANDSHAKE_DONE() { return SSL_CB_HANDSHAKE_DONE; } - private static final int SSL_VERIFY_NONE = (int)0L; + + private static final int SSL_VERIFY_NONE = (int) 0L; + /** - * {@snippet lang=c : - * #define SSL_VERIFY_NONE 0 + * {@snippet lang = c : * #define SSL_VERIFY_NONE 0 * } */ public static int SSL_VERIFY_NONE() { return SSL_VERIFY_NONE; } - private static final int SSL_VERIFY_PEER = (int)1L; + + private static final int SSL_VERIFY_PEER = (int) 1L; + /** - * {@snippet lang=c : - * #define SSL_VERIFY_PEER 1 + * {@snippet lang = c : * #define SSL_VERIFY_PEER 1 * } */ public static int SSL_VERIFY_PEER() { return SSL_VERIFY_PEER; } - private static final int SSL_VERIFY_FAIL_IF_NO_PEER_CERT = (int)2L; + + private static final int SSL_VERIFY_FAIL_IF_NO_PEER_CERT = (int) 2L; + /** - * {@snippet lang=c : - * #define SSL_VERIFY_FAIL_IF_NO_PEER_CERT 2 + * {@snippet lang = c : * #define SSL_VERIFY_FAIL_IF_NO_PEER_CERT 2 * } */ public static int SSL_VERIFY_FAIL_IF_NO_PEER_CERT() { return SSL_VERIFY_FAIL_IF_NO_PEER_CERT; } - private static final int SSL_ERROR_NONE = (int)0L; + + private static final int SSL_ERROR_NONE = (int) 0L; + /** - * {@snippet lang=c : - * #define SSL_ERROR_NONE 0 + * {@snippet lang = c : * #define SSL_ERROR_NONE 0 * } */ public static int SSL_ERROR_NONE() { return SSL_ERROR_NONE; } - private static final int SSL_CTRL_SET_TMP_DH = (int)3L; + + private static final int SSL_CTRL_SET_TMP_DH = (int) 3L; + /** - * {@snippet lang=c : - * #define SSL_CTRL_SET_TMP_DH 3 + * {@snippet lang = c : * #define SSL_CTRL_SET_TMP_DH 3 * } */ public static int SSL_CTRL_SET_TMP_DH() { return SSL_CTRL_SET_TMP_DH; } - private static final int SSL_CTRL_SET_TMP_ECDH = (int)4L; + + private static final int SSL_CTRL_SET_TMP_ECDH = (int) 4L; + /** - * {@snippet lang=c : - * #define SSL_CTRL_SET_TMP_ECDH 4 + * {@snippet lang = c : * #define SSL_CTRL_SET_TMP_ECDH 4 * } */ public static int SSL_CTRL_SET_TMP_ECDH() { return SSL_CTRL_SET_TMP_ECDH; } - private static final int SSL_CTRL_SESS_NUMBER = (int)20L; + + private static final int SSL_CTRL_SESS_NUMBER = (int) 20L; + /** - * {@snippet lang=c : - * #define SSL_CTRL_SESS_NUMBER 20 + * {@snippet lang = c : * #define SSL_CTRL_SESS_NUMBER 20 * } */ public static int SSL_CTRL_SESS_NUMBER() { return SSL_CTRL_SESS_NUMBER; } - private static final int SSL_CTRL_SESS_CONNECT = (int)21L; + + private static final int SSL_CTRL_SESS_CONNECT = (int) 21L; + /** - * {@snippet lang=c : - * #define SSL_CTRL_SESS_CONNECT 21 + * {@snippet lang = c : * #define SSL_CTRL_SESS_CONNECT 21 * } */ public static int SSL_CTRL_SESS_CONNECT() { return SSL_CTRL_SESS_CONNECT; } - private static final int SSL_CTRL_SESS_CONNECT_GOOD = (int)22L; + + private static final int SSL_CTRL_SESS_CONNECT_GOOD = (int) 22L; + /** - * {@snippet lang=c : - * #define SSL_CTRL_SESS_CONNECT_GOOD 22 + * {@snippet lang = c : * #define SSL_CTRL_SESS_CONNECT_GOOD 22 * } */ public static int SSL_CTRL_SESS_CONNECT_GOOD() { return SSL_CTRL_SESS_CONNECT_GOOD; } - private static final int SSL_CTRL_SESS_CONNECT_RENEGOTIATE = (int)23L; + + private static final int SSL_CTRL_SESS_CONNECT_RENEGOTIATE = (int) 23L; + /** - * {@snippet lang=c : - * #define SSL_CTRL_SESS_CONNECT_RENEGOTIATE 23 + * {@snippet lang = c : * #define SSL_CTRL_SESS_CONNECT_RENEGOTIATE 23 * } */ public static int SSL_CTRL_SESS_CONNECT_RENEGOTIATE() { return SSL_CTRL_SESS_CONNECT_RENEGOTIATE; } - private static final int SSL_CTRL_SESS_ACCEPT = (int)24L; + + private static final int SSL_CTRL_SESS_ACCEPT = (int) 24L; + /** - * {@snippet lang=c : - * #define SSL_CTRL_SESS_ACCEPT 24 + * {@snippet lang = c : * #define SSL_CTRL_SESS_ACCEPT 24 * } */ public static int SSL_CTRL_SESS_ACCEPT() { return SSL_CTRL_SESS_ACCEPT; } - private static final int SSL_CTRL_SESS_ACCEPT_GOOD = (int)25L; + + private static final int SSL_CTRL_SESS_ACCEPT_GOOD = (int) 25L; + /** - * {@snippet lang=c : - * #define SSL_CTRL_SESS_ACCEPT_GOOD 25 + * {@snippet lang = c : * #define SSL_CTRL_SESS_ACCEPT_GOOD 25 * } */ public static int SSL_CTRL_SESS_ACCEPT_GOOD() { return SSL_CTRL_SESS_ACCEPT_GOOD; } - private static final int SSL_CTRL_SESS_ACCEPT_RENEGOTIATE = (int)26L; + + private static final int SSL_CTRL_SESS_ACCEPT_RENEGOTIATE = (int) 26L; + /** - * {@snippet lang=c : - * #define SSL_CTRL_SESS_ACCEPT_RENEGOTIATE 26 + * {@snippet lang = c : * #define SSL_CTRL_SESS_ACCEPT_RENEGOTIATE 26 * } */ public static int SSL_CTRL_SESS_ACCEPT_RENEGOTIATE() { return SSL_CTRL_SESS_ACCEPT_RENEGOTIATE; } - private static final int SSL_CTRL_SESS_HIT = (int)27L; + + private static final int SSL_CTRL_SESS_HIT = (int) 27L; + /** - * {@snippet lang=c : - * #define SSL_CTRL_SESS_HIT 27 + * {@snippet lang = c : * #define SSL_CTRL_SESS_HIT 27 * } */ public static int SSL_CTRL_SESS_HIT() { return SSL_CTRL_SESS_HIT; } - private static final int SSL_CTRL_SESS_CB_HIT = (int)28L; + + private static final int SSL_CTRL_SESS_CB_HIT = (int) 28L; + /** - * {@snippet lang=c : - * #define SSL_CTRL_SESS_CB_HIT 28 + * {@snippet lang = c : * #define SSL_CTRL_SESS_CB_HIT 28 * } */ public static int SSL_CTRL_SESS_CB_HIT() { return SSL_CTRL_SESS_CB_HIT; } - private static final int SSL_CTRL_SESS_MISSES = (int)29L; + + private static final int SSL_CTRL_SESS_MISSES = (int) 29L; + /** - * {@snippet lang=c : - * #define SSL_CTRL_SESS_MISSES 29 + * {@snippet lang = c : * #define SSL_CTRL_SESS_MISSES 29 * } */ public static int SSL_CTRL_SESS_MISSES() { return SSL_CTRL_SESS_MISSES; } - private static final int SSL_CTRL_SESS_TIMEOUTS = (int)30L; + + private static final int SSL_CTRL_SESS_TIMEOUTS = (int) 30L; + /** - * {@snippet lang=c : - * #define SSL_CTRL_SESS_TIMEOUTS 30 + * {@snippet lang = c : * #define SSL_CTRL_SESS_TIMEOUTS 30 * } */ public static int SSL_CTRL_SESS_TIMEOUTS() { return SSL_CTRL_SESS_TIMEOUTS; } - private static final int SSL_CTRL_SESS_CACHE_FULL = (int)31L; + + private static final int SSL_CTRL_SESS_CACHE_FULL = (int) 31L; + /** - * {@snippet lang=c : - * #define SSL_CTRL_SESS_CACHE_FULL 31 + * {@snippet lang = c : * #define SSL_CTRL_SESS_CACHE_FULL 31 * } */ public static int SSL_CTRL_SESS_CACHE_FULL() { return SSL_CTRL_SESS_CACHE_FULL; } - private static final int SSL_CTRL_SET_SESS_CACHE_SIZE = (int)42L; + + private static final int SSL_CTRL_SET_SESS_CACHE_SIZE = (int) 42L; + /** - * {@snippet lang=c : - * #define SSL_CTRL_SET_SESS_CACHE_SIZE 42 + * {@snippet lang = c : * #define SSL_CTRL_SET_SESS_CACHE_SIZE 42 * } */ public static int SSL_CTRL_SET_SESS_CACHE_SIZE() { return SSL_CTRL_SET_SESS_CACHE_SIZE; } - private static final int SSL_CTRL_GET_SESS_CACHE_SIZE = (int)43L; + + private static final int SSL_CTRL_GET_SESS_CACHE_SIZE = (int) 43L; + /** - * {@snippet lang=c : - * #define SSL_CTRL_GET_SESS_CACHE_SIZE 43 + * {@snippet lang = c : * #define SSL_CTRL_GET_SESS_CACHE_SIZE 43 * } */ public static int SSL_CTRL_GET_SESS_CACHE_SIZE() { return SSL_CTRL_GET_SESS_CACHE_SIZE; } - private static final int SSL_CTRL_SET_SESS_CACHE_MODE = (int)44L; + + private static final int SSL_CTRL_SET_SESS_CACHE_MODE = (int) 44L; + /** - * {@snippet lang=c : - * #define SSL_CTRL_SET_SESS_CACHE_MODE 44 + * {@snippet lang = c : * #define SSL_CTRL_SET_SESS_CACHE_MODE 44 * } */ public static int SSL_CTRL_SET_SESS_CACHE_MODE() { return SSL_CTRL_SET_SESS_CACHE_MODE; } - private static final int SSL_CTRL_GET_SESS_CACHE_MODE = (int)45L; + + private static final int SSL_CTRL_GET_SESS_CACHE_MODE = (int) 45L; + /** - * {@snippet lang=c : - * #define SSL_CTRL_GET_SESS_CACHE_MODE 45 + * {@snippet lang = c : * #define SSL_CTRL_GET_SESS_CACHE_MODE 45 * } */ public static int SSL_CTRL_GET_SESS_CACHE_MODE() { return SSL_CTRL_GET_SESS_CACHE_MODE; } - private static final int SSL_CTRL_SET_TLSEXT_TICKET_KEYS = (int)59L; + + private static final int SSL_CTRL_SET_TLSEXT_TICKET_KEYS = (int) 59L; + /** - * {@snippet lang=c : - * #define SSL_CTRL_SET_TLSEXT_TICKET_KEYS 59 + * {@snippet lang = c : * #define SSL_CTRL_SET_TLSEXT_TICKET_KEYS 59 * } */ public static int SSL_CTRL_SET_TLSEXT_TICKET_KEYS() { return SSL_CTRL_SET_TLSEXT_TICKET_KEYS; } - private static final int SSL_CTRL_CHAIN_CERT = (int)89L; + + private static final int SSL_CTRL_CHAIN_CERT = (int) 89L; + /** - * {@snippet lang=c : - * #define SSL_CTRL_CHAIN_CERT 89 + * {@snippet lang = c : * #define SSL_CTRL_CHAIN_CERT 89 * } */ public static int SSL_CTRL_CHAIN_CERT() { return SSL_CTRL_CHAIN_CERT; } - private static final int SSL_CTRL_SET_GROUPS = (int)91L; + + private static final int SSL_CTRL_SET_GROUPS = (int) 91L; + /** - * {@snippet lang=c : - * #define SSL_CTRL_SET_GROUPS 91 + * {@snippet lang = c : * #define SSL_CTRL_SET_GROUPS 91 * } */ public static int SSL_CTRL_SET_GROUPS() { return SSL_CTRL_SET_GROUPS; } - private static final int SSL_CTRL_SET_DH_AUTO = (int)118L; + + private static final int SSL_CTRL_SET_GROUPS_LIST = (int) 92L; + + /** + * {@snippet lang = c : * #define SSL_CTRL_SET_GROUPS_LIST 92 + * } + */ + public static int SSL_CTRL_SET_GROUPS_LIST() { + return SSL_CTRL_SET_GROUPS_LIST; + } + + private static final int SSL_CTRL_SET_DH_AUTO = (int) 118L; + /** - * {@snippet lang=c : - * #define SSL_CTRL_SET_DH_AUTO 118 + * {@snippet lang = c : * #define SSL_CTRL_SET_DH_AUTO 118 * } */ public static int SSL_CTRL_SET_DH_AUTO() { return SSL_CTRL_SET_DH_AUTO; } - private static final int SSL_CTRL_SET_MIN_PROTO_VERSION = (int)123L; + + private static final int SSL_CTRL_SET_MIN_PROTO_VERSION = (int) 123L; + /** - * {@snippet lang=c : - * #define SSL_CTRL_SET_MIN_PROTO_VERSION 123 + * {@snippet lang = c : * #define SSL_CTRL_SET_MIN_PROTO_VERSION 123 * } */ public static int SSL_CTRL_SET_MIN_PROTO_VERSION() { return SSL_CTRL_SET_MIN_PROTO_VERSION; } - private static final int SSL_CTRL_SET_MAX_PROTO_VERSION = (int)124L; + + private static final int SSL_CTRL_SET_MAX_PROTO_VERSION = (int) 124L; + /** - * {@snippet lang=c : - * #define SSL_CTRL_SET_MAX_PROTO_VERSION 124 + * {@snippet lang = c : * #define SSL_CTRL_SET_MAX_PROTO_VERSION 124 * } */ public static int SSL_CTRL_SET_MAX_PROTO_VERSION() { return SSL_CTRL_SET_MAX_PROTO_VERSION; } - private static final int ERR_REASON_MASK = (int)8388607L; + + private static final int ERR_REASON_MASK = (int) 8388607L; + /** - * {@snippet lang=c : - * #define ERR_REASON_MASK 8388607 + * {@snippet lang = c : * #define ERR_REASON_MASK 8388607 * } */ public static int ERR_REASON_MASK() { return ERR_REASON_MASK; } - private static final int OCSP_RESPONSE_STATUS_SUCCESSFUL = (int)0L; + + private static final int OCSP_RESPONSE_STATUS_SUCCESSFUL = (int) 0L; + /** - * {@snippet lang=c : - * #define OCSP_RESPONSE_STATUS_SUCCESSFUL 0 + * {@snippet lang = c : * #define OCSP_RESPONSE_STATUS_SUCCESSFUL 0 * } */ public static int OCSP_RESPONSE_STATUS_SUCCESSFUL() { return OCSP_RESPONSE_STATUS_SUCCESSFUL; } - private static final int V_OCSP_CERTSTATUS_GOOD = (int)0L; + + private static final int V_OCSP_CERTSTATUS_GOOD = (int) 0L; + /** - * {@snippet lang=c : - * #define V_OCSP_CERTSTATUS_GOOD 0 + * {@snippet lang = c : * #define V_OCSP_CERTSTATUS_GOOD 0 * } */ public static int V_OCSP_CERTSTATUS_GOOD() { return V_OCSP_CERTSTATUS_GOOD; } - private static final int V_OCSP_CERTSTATUS_REVOKED = (int)1L; + + private static final int V_OCSP_CERTSTATUS_REVOKED = (int) 1L; + /** - * {@snippet lang=c : - * #define V_OCSP_CERTSTATUS_REVOKED 1 + * {@snippet lang = c : * #define V_OCSP_CERTSTATUS_REVOKED 1 * } */ public static int V_OCSP_CERTSTATUS_REVOKED() { return V_OCSP_CERTSTATUS_REVOKED; } - private static final int V_OCSP_CERTSTATUS_UNKNOWN = (int)2L; + + private static final int V_OCSP_CERTSTATUS_UNKNOWN = (int) 2L; + /** - * {@snippet lang=c : - * #define V_OCSP_CERTSTATUS_UNKNOWN 2 + * {@snippet lang = c : * #define V_OCSP_CERTSTATUS_UNKNOWN 2 * } */ public static int V_OCSP_CERTSTATUS_UNKNOWN() { return V_OCSP_CERTSTATUS_UNKNOWN; } - private static MethodHandle OPENSSL_sk_num$MH() { - class Holder { - static final FunctionDescriptor DESC = FunctionDescriptor.of( - openssl_h.C_INT, - openssl_h.C_POINTER - ); - - static final MethodHandle MH = Linker.nativeLinker().downcallHandle( - openssl_h.findOrThrow("OPENSSL_sk_num"), - DESC); - } - return Holder.MH; + private static class OPENSSL_sk_num { + public static final FunctionDescriptor DESC = FunctionDescriptor.of(openssl_h.C_INT, openssl_h.C_POINTER); + + public static final MemorySegment ADDR = openssl_h.findOrThrow("OPENSSL_sk_num"); + + public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); } /** - * {@snippet lang=c : - * int OPENSSL_sk_num(const OPENSSL_STACK *) + * Function descriptor for: + * {@snippet lang = c : * int OPENSSL_sk_num(const OPENSSL_STACK *) + * } + */ + public static FunctionDescriptor OPENSSL_sk_num$descriptor() { + return OPENSSL_sk_num.DESC; + } + + /** + * Downcall method handle for: + * {@snippet lang = c : * int OPENSSL_sk_num(const OPENSSL_STACK *) + * } + */ + public static MethodHandle OPENSSL_sk_num$handle() { + return OPENSSL_sk_num.HANDLE; + } + + /** + * Address for: + * {@snippet lang = c : * int OPENSSL_sk_num(const OPENSSL_STACK *) + * } + */ + public static MemorySegment OPENSSL_sk_num$address() { + return OPENSSL_sk_num.ADDR; + } + + /** + * {@snippet lang = c : * int OPENSSL_sk_num(const OPENSSL_STACK *) * } */ public static int OPENSSL_sk_num(MemorySegment x0) { - var mh$ = OPENSSL_sk_num$MH(); + var mh$ = OPENSSL_sk_num.HANDLE; try { if (TRACE_DOWNCALLS) { traceDowncall("OPENSSL_sk_num", x0); } return (int) mh$.invokeExact(x0); } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); + throw new AssertionError("should not reach here", ex$); } } - private static MethodHandle OPENSSL_sk_value$MH() { - class Holder { - static final FunctionDescriptor DESC = FunctionDescriptor.of( - openssl_h.C_POINTER, - openssl_h.C_POINTER, - openssl_h.C_INT - ); - - static final MethodHandle MH = Linker.nativeLinker().downcallHandle( - openssl_h.findOrThrow("OPENSSL_sk_value"), - DESC); - } - return Holder.MH; + private static class OPENSSL_sk_value { + public static final FunctionDescriptor DESC = + FunctionDescriptor.of(openssl_h.C_POINTER, openssl_h.C_POINTER, openssl_h.C_INT); + + public static final MemorySegment ADDR = openssl_h.findOrThrow("OPENSSL_sk_value"); + + public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); } /** - * {@snippet lang=c : - * void *OPENSSL_sk_value(const OPENSSL_STACK *, int) + * Function descriptor for: + * {@snippet lang = c : * void *OPENSSL_sk_value(const OPENSSL_STACK *, int) + * } + */ + public static FunctionDescriptor OPENSSL_sk_value$descriptor() { + return OPENSSL_sk_value.DESC; + } + + /** + * Downcall method handle for: + * {@snippet lang = c : * void *OPENSSL_sk_value(const OPENSSL_STACK *, int) + * } + */ + public static MethodHandle OPENSSL_sk_value$handle() { + return OPENSSL_sk_value.HANDLE; + } + + /** + * Address for: + * {@snippet lang = c : * void *OPENSSL_sk_value(const OPENSSL_STACK *, int) + * } + */ + public static MemorySegment OPENSSL_sk_value$address() { + return OPENSSL_sk_value.ADDR; + } + + /** + * {@snippet lang = c : * void *OPENSSL_sk_value(const OPENSSL_STACK *, int) * } */ public static MemorySegment OPENSSL_sk_value(MemorySegment x0, int x1) { - var mh$ = OPENSSL_sk_value$MH(); + var mh$ = OPENSSL_sk_value.HANDLE; try { if (TRACE_DOWNCALLS) { traceDowncall("OPENSSL_sk_value", x0, x1); } return (MemorySegment) mh$.invokeExact(x0, x1); } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); + throw new AssertionError("should not reach here", ex$); } } - private static MethodHandle OpenSSL_version_num$MH() { - class Holder { - static final FunctionDescriptor DESC = FunctionDescriptor.of( - openssl_h.C_LONG ); + private static class OpenSSL_version_num { + public static final FunctionDescriptor DESC = FunctionDescriptor.of(openssl_h.C_LONG); - static final MethodHandle MH = Linker.nativeLinker().downcallHandle( - openssl_h.findOrThrow("OpenSSL_version_num"), - DESC); - } - return Holder.MH; + public static final MemorySegment ADDR = openssl_h.findOrThrow("OpenSSL_version_num"); + + public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); } /** - * {@snippet lang=c : - * unsigned long OpenSSL_version_num(void) + * Function descriptor for: + * {@snippet lang = c : * unsigned long OpenSSL_version_num() + * } + */ + public static FunctionDescriptor OpenSSL_version_num$descriptor() { + return OpenSSL_version_num.DESC; + } + + /** + * Downcall method handle for: + * {@snippet lang = c : * unsigned long OpenSSL_version_num() + * } + */ + public static MethodHandle OpenSSL_version_num$handle() { + return OpenSSL_version_num.HANDLE; + } + + /** + * Address for: + * {@snippet lang = c : * unsigned long OpenSSL_version_num() + * } + */ + public static MemorySegment OpenSSL_version_num$address() { + return OpenSSL_version_num.ADDR; + } + + /** + * {@snippet lang = c : * unsigned long OpenSSL_version_num() * } */ public static long OpenSSL_version_num() { - var mh$ = OpenSSL_version_num$MH(); + var mh$ = OpenSSL_version_num.HANDLE; try { if (TRACE_DOWNCALLS) { traceDowncall("OpenSSL_version_num"); } return (long) mh$.invokeExact(); } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); + throw new AssertionError("should not reach here", ex$); } } - private static MethodHandle OpenSSL_version$MH() { - class Holder { - static final FunctionDescriptor DESC = FunctionDescriptor.of( - openssl_h.C_POINTER, - openssl_h.C_INT - ); - - static final MethodHandle MH = Linker.nativeLinker().downcallHandle( - openssl_h.findOrThrow("OpenSSL_version"), - DESC); - } - return Holder.MH; + private static class OpenSSL_version { + public static final FunctionDescriptor DESC = FunctionDescriptor.of(openssl_h.C_POINTER, openssl_h.C_INT); + + public static final MemorySegment ADDR = openssl_h.findOrThrow("OpenSSL_version"); + + public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); } /** - * {@snippet lang=c : - * const char *OpenSSL_version(int type) + * Function descriptor for: + * {@snippet lang = c : * const char *OpenSSL_version(int type) + * } + */ + public static FunctionDescriptor OpenSSL_version$descriptor() { + return OpenSSL_version.DESC; + } + + /** + * Downcall method handle for: + * {@snippet lang = c : * const char *OpenSSL_version(int type) + * } + */ + public static MethodHandle OpenSSL_version$handle() { + return OpenSSL_version.HANDLE; + } + + /** + * Address for: + * {@snippet lang = c : * const char *OpenSSL_version(int type) + * } + */ + public static MemorySegment OpenSSL_version$address() { + return OpenSSL_version.ADDR; + } + + /** + * {@snippet lang = c : * const char *OpenSSL_version(int type) * } */ public static MemorySegment OpenSSL_version(int type) { - var mh$ = OpenSSL_version$MH(); + var mh$ = OpenSSL_version.HANDLE; try { if (TRACE_DOWNCALLS) { traceDowncall("OpenSSL_version", type); } return (MemorySegment) mh$.invokeExact(type); } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); + throw new AssertionError("should not reach here", ex$); } } - private static MethodHandle CRYPTO_free$MH() { - class Holder { - static final FunctionDescriptor DESC = FunctionDescriptor.ofVoid( - openssl_h.C_POINTER, - openssl_h.C_POINTER, - openssl_h.C_INT - ); - - static final MethodHandle MH = Linker.nativeLinker().downcallHandle( - openssl_h.findOrThrow("CRYPTO_free"), - DESC); - } - return Holder.MH; + private static class CRYPTO_free { + public static final FunctionDescriptor DESC = + FunctionDescriptor.ofVoid(openssl_h.C_POINTER, openssl_h.C_POINTER, openssl_h.C_INT); + + public static final MemorySegment ADDR = openssl_h.findOrThrow("CRYPTO_free"); + + public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); } /** - * {@snippet lang=c : - * void CRYPTO_free(void *ptr, const char *file, int line) + * Function descriptor for: + * {@snippet lang = c : * void CRYPTO_free(void *ptr, const char *file, int line) + * } + */ + public static FunctionDescriptor CRYPTO_free$descriptor() { + return CRYPTO_free.DESC; + } + + /** + * Downcall method handle for: + * {@snippet lang = c : * void CRYPTO_free(void *ptr, const char *file, int line) + * } + */ + public static MethodHandle CRYPTO_free$handle() { + return CRYPTO_free.HANDLE; + } + + /** + * Address for: + * {@snippet lang = c : * void CRYPTO_free(void *ptr, const char *file, int line) + * } + */ + public static MemorySegment CRYPTO_free$address() { + return CRYPTO_free.ADDR; + } + + /** + * {@snippet lang = c : * void CRYPTO_free(void *ptr, const char *file, int line) * } */ public static void CRYPTO_free(MemorySegment ptr, MemorySegment file, int line) { - var mh$ = CRYPTO_free$MH(); + var mh$ = CRYPTO_free.HANDLE; try { if (TRACE_DOWNCALLS) { traceDowncall("CRYPTO_free", ptr, file, line); } mh$.invokeExact(ptr, file, line); } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); + throw new AssertionError("should not reach here", ex$); } } - private static MethodHandle BIO_ctrl_pending$MH() { - class Holder { - static final FunctionDescriptor DESC = FunctionDescriptor.of( - openssl_h.C_LONG, - openssl_h.C_POINTER - ); - - static final MethodHandle MH = Linker.nativeLinker().downcallHandle( - openssl_h.findOrThrow("BIO_ctrl_pending"), - DESC); - } - return Holder.MH; + private static class BIO_ctrl_pending { + public static final FunctionDescriptor DESC = FunctionDescriptor.of(openssl_h.C_LONG, openssl_h.C_POINTER); + + public static final MemorySegment ADDR = openssl_h.findOrThrow("BIO_ctrl_pending"); + + public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); } /** - * {@snippet lang=c : - * size_t BIO_ctrl_pending(BIO *b) + * Function descriptor for: + * {@snippet lang = c : * size_t BIO_ctrl_pending(BIO *b) + * } + */ + public static FunctionDescriptor BIO_ctrl_pending$descriptor() { + return BIO_ctrl_pending.DESC; + } + + /** + * Downcall method handle for: + * {@snippet lang = c : * size_t BIO_ctrl_pending(BIO *b) + * } + */ + public static MethodHandle BIO_ctrl_pending$handle() { + return BIO_ctrl_pending.HANDLE; + } + + /** + * Address for: + * {@snippet lang = c : * size_t BIO_ctrl_pending(BIO *b) + * } + */ + public static MemorySegment BIO_ctrl_pending$address() { + return BIO_ctrl_pending.ADDR; + } + + /** + * {@snippet lang = c : * size_t BIO_ctrl_pending(BIO *b) * } */ public static long BIO_ctrl_pending(MemorySegment b) { - var mh$ = BIO_ctrl_pending$MH(); + var mh$ = BIO_ctrl_pending.HANDLE; try { if (TRACE_DOWNCALLS) { traceDowncall("BIO_ctrl_pending", b); } return (long) mh$.invokeExact(b); } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); + throw new AssertionError("should not reach here", ex$); } } - private static MethodHandle BIO_s_file$MH() { - class Holder { - static final FunctionDescriptor DESC = FunctionDescriptor.of( - openssl_h.C_POINTER ); + private static class BIO_s_file { + public static final FunctionDescriptor DESC = FunctionDescriptor.of(openssl_h.C_POINTER); - static final MethodHandle MH = Linker.nativeLinker().downcallHandle( - openssl_h.findOrThrow("BIO_s_file"), - DESC); - } - return Holder.MH; + public static final MemorySegment ADDR = openssl_h.findOrThrow("BIO_s_file"); + + public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); } /** - * {@snippet lang=c : - * const BIO_METHOD *BIO_s_file(void) + * Function descriptor for: + * {@snippet lang = c : * const BIO_METHOD *BIO_s_file() + * } + */ + public static FunctionDescriptor BIO_s_file$descriptor() { + return BIO_s_file.DESC; + } + + /** + * Downcall method handle for: + * {@snippet lang = c : * const BIO_METHOD *BIO_s_file() + * } + */ + public static MethodHandle BIO_s_file$handle() { + return BIO_s_file.HANDLE; + } + + /** + * Address for: + * {@snippet lang = c : * const BIO_METHOD *BIO_s_file() + * } + */ + public static MemorySegment BIO_s_file$address() { + return BIO_s_file.ADDR; + } + + /** + * {@snippet lang = c : * const BIO_METHOD *BIO_s_file() * } */ public static MemorySegment BIO_s_file() { - var mh$ = BIO_s_file$MH(); + var mh$ = BIO_s_file.HANDLE; try { if (TRACE_DOWNCALLS) { traceDowncall("BIO_s_file"); } return (MemorySegment) mh$.invokeExact(); } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); + throw new AssertionError("should not reach here", ex$); } } - private static MethodHandle BIO_new_file$MH() { - class Holder { - static final FunctionDescriptor DESC = FunctionDescriptor.of( - openssl_h.C_POINTER, - openssl_h.C_POINTER, - openssl_h.C_POINTER - ); - - static final MethodHandle MH = Linker.nativeLinker().downcallHandle( - openssl_h.findOrThrow("BIO_new_file"), - DESC); - } - return Holder.MH; + private static class BIO_new_file { + public static final FunctionDescriptor DESC = + FunctionDescriptor.of(openssl_h.C_POINTER, openssl_h.C_POINTER, openssl_h.C_POINTER); + + public static final MemorySegment ADDR = openssl_h.findOrThrow("BIO_new_file"); + + public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); } /** - * {@snippet lang=c : - * BIO *BIO_new_file(const char *filename, const char *mode) + * Function descriptor for: + * {@snippet lang = c : * BIO *BIO_new_file(const char *filename, const char *mode) + * } + */ + public static FunctionDescriptor BIO_new_file$descriptor() { + return BIO_new_file.DESC; + } + + /** + * Downcall method handle for: + * {@snippet lang = c : * BIO *BIO_new_file(const char *filename, const char *mode) + * } + */ + public static MethodHandle BIO_new_file$handle() { + return BIO_new_file.HANDLE; + } + + /** + * Address for: + * {@snippet lang = c : * BIO *BIO_new_file(const char *filename, const char *mode) + * } + */ + public static MemorySegment BIO_new_file$address() { + return BIO_new_file.ADDR; + } + + /** + * {@snippet lang = c : * BIO *BIO_new_file(const char *filename, const char *mode) * } */ public static MemorySegment BIO_new_file(MemorySegment filename, MemorySegment mode) { - var mh$ = BIO_new_file$MH(); + var mh$ = BIO_new_file.HANDLE; try { if (TRACE_DOWNCALLS) { traceDowncall("BIO_new_file", filename, mode); } return (MemorySegment) mh$.invokeExact(filename, mode); } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); + throw new AssertionError("should not reach here", ex$); } } - private static MethodHandle BIO_new$MH() { - class Holder { - static final FunctionDescriptor DESC = FunctionDescriptor.of( - openssl_h.C_POINTER, - openssl_h.C_POINTER - ); - - static final MethodHandle MH = Linker.nativeLinker().downcallHandle( - openssl_h.findOrThrow("BIO_new"), - DESC); - } - return Holder.MH; + private static class BIO_new { + public static final FunctionDescriptor DESC = FunctionDescriptor.of(openssl_h.C_POINTER, openssl_h.C_POINTER); + + public static final MemorySegment ADDR = openssl_h.findOrThrow("BIO_new"); + + public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); } /** - * {@snippet lang=c : - * BIO *BIO_new(const BIO_METHOD *type) + * Function descriptor for: + * {@snippet lang = c : * BIO *BIO_new(const BIO_METHOD *type) + * } + */ + public static FunctionDescriptor BIO_new$descriptor() { + return BIO_new.DESC; + } + + /** + * Downcall method handle for: + * {@snippet lang = c : * BIO *BIO_new(const BIO_METHOD *type) + * } + */ + public static MethodHandle BIO_new$handle() { + return BIO_new.HANDLE; + } + + /** + * Address for: + * {@snippet lang = c : * BIO *BIO_new(const BIO_METHOD *type) + * } + */ + public static MemorySegment BIO_new$address() { + return BIO_new.ADDR; + } + + /** + * {@snippet lang = c : * BIO *BIO_new(const BIO_METHOD *type) * } */ public static MemorySegment BIO_new(MemorySegment type) { - var mh$ = BIO_new$MH(); + var mh$ = BIO_new.HANDLE; try { if (TRACE_DOWNCALLS) { traceDowncall("BIO_new", type); } return (MemorySegment) mh$.invokeExact(type); } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); + throw new AssertionError("should not reach here", ex$); } } - private static MethodHandle BIO_free$MH() { - class Holder { - static final FunctionDescriptor DESC = FunctionDescriptor.of( - openssl_h.C_INT, - openssl_h.C_POINTER - ); - - static final MethodHandle MH = Linker.nativeLinker().downcallHandle( - openssl_h.findOrThrow("BIO_free"), - DESC); - } - return Holder.MH; + private static class BIO_free { + public static final FunctionDescriptor DESC = FunctionDescriptor.of(openssl_h.C_INT, openssl_h.C_POINTER); + + public static final MemorySegment ADDR = openssl_h.findOrThrow("BIO_free"); + + public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); } /** - * {@snippet lang=c : - * int BIO_free(BIO *a) + * Function descriptor for: + * {@snippet lang = c : * int BIO_free(BIO *a) + * } + */ + public static FunctionDescriptor BIO_free$descriptor() { + return BIO_free.DESC; + } + + /** + * Downcall method handle for: + * {@snippet lang = c : * int BIO_free(BIO *a) + * } + */ + public static MethodHandle BIO_free$handle() { + return BIO_free.HANDLE; + } + + /** + * Address for: + * {@snippet lang = c : * int BIO_free(BIO *a) + * } + */ + public static MemorySegment BIO_free$address() { + return BIO_free.ADDR; + } + + /** + * {@snippet lang = c : * int BIO_free(BIO *a) * } */ public static int BIO_free(MemorySegment a) { - var mh$ = BIO_free$MH(); + var mh$ = BIO_free.HANDLE; try { if (TRACE_DOWNCALLS) { traceDowncall("BIO_free", a); } return (int) mh$.invokeExact(a); } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); + throw new AssertionError("should not reach here", ex$); } } - private static MethodHandle BIO_read$MH() { - class Holder { - static final FunctionDescriptor DESC = FunctionDescriptor.of( - openssl_h.C_INT, - openssl_h.C_POINTER, - openssl_h.C_POINTER, - openssl_h.C_INT - ); - - static final MethodHandle MH = Linker.nativeLinker().downcallHandle( - openssl_h.findOrThrow("BIO_read"), - DESC); - } - return Holder.MH; + private static class BIO_read { + public static final FunctionDescriptor DESC = + FunctionDescriptor.of(openssl_h.C_INT, openssl_h.C_POINTER, openssl_h.C_POINTER, openssl_h.C_INT); + + public static final MemorySegment ADDR = openssl_h.findOrThrow("BIO_read"); + + public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); } /** - * {@snippet lang=c : - * int BIO_read(BIO *b, void *data, int dlen) + * Function descriptor for: + * {@snippet lang = c : * int BIO_read(BIO *b, void *data, int dlen) + * } + */ + public static FunctionDescriptor BIO_read$descriptor() { + return BIO_read.DESC; + } + + /** + * Downcall method handle for: + * {@snippet lang = c : * int BIO_read(BIO *b, void *data, int dlen) + * } + */ + public static MethodHandle BIO_read$handle() { + return BIO_read.HANDLE; + } + + /** + * Address for: + * {@snippet lang = c : * int BIO_read(BIO *b, void *data, int dlen) + * } + */ + public static MemorySegment BIO_read$address() { + return BIO_read.ADDR; + } + + /** + * {@snippet lang = c : * int BIO_read(BIO *b, void *data, int dlen) * } */ public static int BIO_read(MemorySegment b, MemorySegment data, int dlen) { - var mh$ = BIO_read$MH(); + var mh$ = BIO_read.HANDLE; try { if (TRACE_DOWNCALLS) { traceDowncall("BIO_read", b, data, dlen); } return (int) mh$.invokeExact(b, data, dlen); } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); + throw new AssertionError("should not reach here", ex$); } } - private static MethodHandle BIO_write$MH() { - class Holder { - static final FunctionDescriptor DESC = FunctionDescriptor.of( - openssl_h.C_INT, - openssl_h.C_POINTER, - openssl_h.C_POINTER, - openssl_h.C_INT - ); - - static final MethodHandle MH = Linker.nativeLinker().downcallHandle( - openssl_h.findOrThrow("BIO_write"), - DESC); - } - return Holder.MH; + private static class BIO_write { + public static final FunctionDescriptor DESC = + FunctionDescriptor.of(openssl_h.C_INT, openssl_h.C_POINTER, openssl_h.C_POINTER, openssl_h.C_INT); + + public static final MemorySegment ADDR = openssl_h.findOrThrow("BIO_write"); + + public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); } /** - * {@snippet lang=c : - * int BIO_write(BIO *b, const void *data, int dlen) + * Function descriptor for: + * {@snippet lang = c : * int BIO_write(BIO *b, const void *data, int dlen) + * } + */ + public static FunctionDescriptor BIO_write$descriptor() { + return BIO_write.DESC; + } + + /** + * Downcall method handle for: + * {@snippet lang = c : * int BIO_write(BIO *b, const void *data, int dlen) + * } + */ + public static MethodHandle BIO_write$handle() { + return BIO_write.HANDLE; + } + + /** + * Address for: + * {@snippet lang = c : * int BIO_write(BIO *b, const void *data, int dlen) + * } + */ + public static MemorySegment BIO_write$address() { + return BIO_write.ADDR; + } + + /** + * {@snippet lang = c : * int BIO_write(BIO *b, const void *data, int dlen) * } */ public static int BIO_write(MemorySegment b, MemorySegment data, int dlen) { - var mh$ = BIO_write$MH(); + var mh$ = BIO_write.HANDLE; try { if (TRACE_DOWNCALLS) { traceDowncall("BIO_write", b, data, dlen); } return (int) mh$.invokeExact(b, data, dlen); } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); + throw new AssertionError("should not reach here", ex$); } } - private static MethodHandle BIO_ctrl$MH() { - class Holder { - static final FunctionDescriptor DESC = FunctionDescriptor.of( - openssl_h.C_LONG, - openssl_h.C_POINTER, - openssl_h.C_INT, - openssl_h.C_LONG, - openssl_h.C_POINTER - ); - - static final MethodHandle MH = Linker.nativeLinker().downcallHandle( - openssl_h.findOrThrow("BIO_ctrl"), - DESC); - } - return Holder.MH; + private static class BIO_ctrl { + public static final FunctionDescriptor DESC = FunctionDescriptor.of(openssl_h.C_LONG, openssl_h.C_POINTER, + openssl_h.C_INT, openssl_h.C_LONG, openssl_h.C_POINTER); + + public static final MemorySegment ADDR = openssl_h.findOrThrow("BIO_ctrl"); + + public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); } /** - * {@snippet lang=c : - * long BIO_ctrl(BIO *bp, int cmd, long larg, void *parg) + * Function descriptor for: + * {@snippet lang = c : * long BIO_ctrl(BIO *bp, int cmd, long larg, void *parg) + * } + */ + public static FunctionDescriptor BIO_ctrl$descriptor() { + return BIO_ctrl.DESC; + } + + /** + * Downcall method handle for: + * {@snippet lang = c : * long BIO_ctrl(BIO *bp, int cmd, long larg, void *parg) + * } + */ + public static MethodHandle BIO_ctrl$handle() { + return BIO_ctrl.HANDLE; + } + + /** + * Address for: + * {@snippet lang = c : * long BIO_ctrl(BIO *bp, int cmd, long larg, void *parg) + * } + */ + public static MemorySegment BIO_ctrl$address() { + return BIO_ctrl.ADDR; + } + + /** + * {@snippet lang = c : * long BIO_ctrl(BIO *bp, int cmd, long larg, void *parg) * } */ public static long BIO_ctrl(MemorySegment bp, int cmd, long larg, MemorySegment parg) { - var mh$ = BIO_ctrl$MH(); + var mh$ = BIO_ctrl.HANDLE; try { if (TRACE_DOWNCALLS) { traceDowncall("BIO_ctrl", bp, cmd, larg, parg); } return (long) mh$.invokeExact(bp, cmd, larg, parg); } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); + throw new AssertionError("should not reach here", ex$); } } - private static MethodHandle BIO_s_mem$MH() { - class Holder { - static final FunctionDescriptor DESC = FunctionDescriptor.of( - openssl_h.C_POINTER ); + private static class BIO_s_mem { + public static final FunctionDescriptor DESC = FunctionDescriptor.of(openssl_h.C_POINTER); - static final MethodHandle MH = Linker.nativeLinker().downcallHandle( - openssl_h.findOrThrow("BIO_s_mem"), - DESC); - } - return Holder.MH; + public static final MemorySegment ADDR = openssl_h.findOrThrow("BIO_s_mem"); + + public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); } /** - * {@snippet lang=c : - * const BIO_METHOD *BIO_s_mem(void) + * Function descriptor for: + * {@snippet lang = c : * const BIO_METHOD *BIO_s_mem() + * } + */ + public static FunctionDescriptor BIO_s_mem$descriptor() { + return BIO_s_mem.DESC; + } + + /** + * Downcall method handle for: + * {@snippet lang = c : * const BIO_METHOD *BIO_s_mem() + * } + */ + public static MethodHandle BIO_s_mem$handle() { + return BIO_s_mem.HANDLE; + } + + /** + * Address for: + * {@snippet lang = c : * const BIO_METHOD *BIO_s_mem() + * } + */ + public static MemorySegment BIO_s_mem$address() { + return BIO_s_mem.ADDR; + } + + /** + * {@snippet lang = c : * const BIO_METHOD *BIO_s_mem() * } */ public static MemorySegment BIO_s_mem() { - var mh$ = BIO_s_mem$MH(); + var mh$ = BIO_s_mem.HANDLE; try { if (TRACE_DOWNCALLS) { traceDowncall("BIO_s_mem"); } return (MemorySegment) mh$.invokeExact(); } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); + throw new AssertionError("should not reach here", ex$); } } - private static MethodHandle BIO_s_bio$MH() { - class Holder { - static final FunctionDescriptor DESC = FunctionDescriptor.of( - openssl_h.C_POINTER ); + private static class BIO_s_bio { + public static final FunctionDescriptor DESC = FunctionDescriptor.of(openssl_h.C_POINTER); - static final MethodHandle MH = Linker.nativeLinker().downcallHandle( - openssl_h.findOrThrow("BIO_s_bio"), - DESC); - } - return Holder.MH; + public static final MemorySegment ADDR = openssl_h.findOrThrow("BIO_s_bio"); + + public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); } /** - * {@snippet lang=c : - * const BIO_METHOD *BIO_s_bio(void) + * Function descriptor for: + * {@snippet lang = c : * const BIO_METHOD *BIO_s_bio() + * } + */ + public static FunctionDescriptor BIO_s_bio$descriptor() { + return BIO_s_bio.DESC; + } + + /** + * Downcall method handle for: + * {@snippet lang = c : * const BIO_METHOD *BIO_s_bio() + * } + */ + public static MethodHandle BIO_s_bio$handle() { + return BIO_s_bio.HANDLE; + } + + /** + * Address for: + * {@snippet lang = c : * const BIO_METHOD *BIO_s_bio() + * } + */ + public static MemorySegment BIO_s_bio$address() { + return BIO_s_bio.ADDR; + } + + /** + * {@snippet lang = c : * const BIO_METHOD *BIO_s_bio() * } */ public static MemorySegment BIO_s_bio() { - var mh$ = BIO_s_bio$MH(); + var mh$ = BIO_s_bio.HANDLE; try { if (TRACE_DOWNCALLS) { traceDowncall("BIO_s_bio"); } return (MemorySegment) mh$.invokeExact(); } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); + throw new AssertionError("should not reach here", ex$); } } - private static MethodHandle BIO_new_bio_pair$MH() { - class Holder { - static final FunctionDescriptor DESC = FunctionDescriptor.of( - openssl_h.C_INT, - openssl_h.C_POINTER, - openssl_h.C_LONG, - openssl_h.C_POINTER, - openssl_h.C_LONG - ); - - static final MethodHandle MH = Linker.nativeLinker().downcallHandle( - openssl_h.findOrThrow("BIO_new_bio_pair"), - DESC); - } - return Holder.MH; + private static class BIO_new_bio_pair { + public static final FunctionDescriptor DESC = FunctionDescriptor.of(openssl_h.C_INT, openssl_h.C_POINTER, + openssl_h.C_LONG, openssl_h.C_POINTER, openssl_h.C_LONG); + + public static final MemorySegment ADDR = openssl_h.findOrThrow("BIO_new_bio_pair"); + + public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); } /** - * {@snippet lang=c : - * int BIO_new_bio_pair(BIO **bio1, size_t writebuf1, BIO **bio2, size_t writebuf2) + * Function descriptor for: + * {@snippet lang = c : * int BIO_new_bio_pair(BIO **bio1, size_t writebuf1, BIO **bio2, size_t writebuf2) + * } + */ + public static FunctionDescriptor BIO_new_bio_pair$descriptor() { + return BIO_new_bio_pair.DESC; + } + + /** + * Downcall method handle for: + * {@snippet lang = c : * int BIO_new_bio_pair(BIO **bio1, size_t writebuf1, BIO **bio2, size_t writebuf2) + * } + */ + public static MethodHandle BIO_new_bio_pair$handle() { + return BIO_new_bio_pair.HANDLE; + } + + /** + * Address for: + * {@snippet lang = c : * int BIO_new_bio_pair(BIO **bio1, size_t writebuf1, BIO **bio2, size_t writebuf2) + * } + */ + public static MemorySegment BIO_new_bio_pair$address() { + return BIO_new_bio_pair.ADDR; + } + + /** + * {@snippet lang = c : * int BIO_new_bio_pair(BIO **bio1, size_t writebuf1, BIO **bio2, size_t writebuf2) * } */ public static int BIO_new_bio_pair(MemorySegment bio1, long writebuf1, MemorySegment bio2, long writebuf2) { - var mh$ = BIO_new_bio_pair$MH(); + var mh$ = BIO_new_bio_pair.HANDLE; try { if (TRACE_DOWNCALLS) { traceDowncall("BIO_new_bio_pair", bio1, writebuf1, bio2, writebuf2); } return (int) mh$.invokeExact(bio1, writebuf1, bio2, writebuf2); } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); + throw new AssertionError("should not reach here", ex$); } } - private static MethodHandle BN_new$MH() { - class Holder { - static final FunctionDescriptor DESC = FunctionDescriptor.of( - openssl_h.C_POINTER ); + private static class BN_new { + public static final FunctionDescriptor DESC = FunctionDescriptor.of(openssl_h.C_POINTER); - static final MethodHandle MH = Linker.nativeLinker().downcallHandle( - openssl_h.findOrThrow("BN_new"), - DESC); - } - return Holder.MH; + public static final MemorySegment ADDR = openssl_h.findOrThrow("BN_new"); + + public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); } /** - * {@snippet lang=c : - * BIGNUM *BN_new(void) + * Function descriptor for: + * {@snippet lang = c : * BIGNUM *BN_new() + * } + */ + public static FunctionDescriptor BN_new$descriptor() { + return BN_new.DESC; + } + + /** + * Downcall method handle for: + * {@snippet lang = c : * BIGNUM *BN_new() + * } + */ + public static MethodHandle BN_new$handle() { + return BN_new.HANDLE; + } + + /** + * Address for: + * {@snippet lang = c : * BIGNUM *BN_new() + * } + */ + public static MemorySegment BN_new$address() { + return BN_new.ADDR; + } + + /** + * {@snippet lang = c : * BIGNUM *BN_new() * } */ public static MemorySegment BN_new() { - var mh$ = BN_new$MH(); + var mh$ = BN_new.HANDLE; try { if (TRACE_DOWNCALLS) { traceDowncall("BN_new"); } return (MemorySegment) mh$.invokeExact(); } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); + throw new AssertionError("should not reach here", ex$); } } - private static MethodHandle BN_set_word$MH() { - class Holder { - static final FunctionDescriptor DESC = FunctionDescriptor.of( - openssl_h.C_INT, - openssl_h.C_POINTER, - openssl_h.C_LONG - ); - - static final MethodHandle MH = Linker.nativeLinker().downcallHandle( - openssl_h.findOrThrow("BN_set_word"), - DESC); - } - return Holder.MH; + private static class BN_set_word { + public static final FunctionDescriptor DESC = + FunctionDescriptor.of(openssl_h.C_INT, openssl_h.C_POINTER, openssl_h.C_LONG); + + public static final MemorySegment ADDR = openssl_h.findOrThrow("BN_set_word"); + + public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); } /** - * {@snippet lang=c : - * int BN_set_word(BIGNUM *a, unsigned long w) + * Function descriptor for: + * {@snippet lang = c : * int BN_set_word(BIGNUM *a, unsigned long w) + * } + */ + public static FunctionDescriptor BN_set_word$descriptor() { + return BN_set_word.DESC; + } + + /** + * Downcall method handle for: + * {@snippet lang = c : * int BN_set_word(BIGNUM *a, unsigned long w) + * } + */ + public static MethodHandle BN_set_word$handle() { + return BN_set_word.HANDLE; + } + + /** + * Address for: + * {@snippet lang = c : * int BN_set_word(BIGNUM *a, unsigned long w) + * } + */ + public static MemorySegment BN_set_word$address() { + return BN_set_word.ADDR; + } + + /** + * {@snippet lang = c : * int BN_set_word(BIGNUM *a, unsigned long w) * } */ public static int BN_set_word(MemorySegment a, long w) { - var mh$ = BN_set_word$MH(); + var mh$ = BN_set_word.HANDLE; try { if (TRACE_DOWNCALLS) { traceDowncall("BN_set_word", a, w); } return (int) mh$.invokeExact(a, w); } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); + throw new AssertionError("should not reach here", ex$); } } - private static MethodHandle BN_get_rfc2409_prime_768$MH() { - class Holder { - static final FunctionDescriptor DESC = FunctionDescriptor.of( - openssl_h.C_POINTER, - openssl_h.C_POINTER - ); - - static final MethodHandle MH = Linker.nativeLinker().downcallHandle( - openssl_h.findOrThrow("BN_get_rfc2409_prime_768"), - DESC); - } - return Holder.MH; + private static class BN_get_rfc2409_prime_768 { + public static final FunctionDescriptor DESC = FunctionDescriptor.of(openssl_h.C_POINTER, openssl_h.C_POINTER); + + public static final MemorySegment ADDR = openssl_h.findOrThrow("BN_get_rfc2409_prime_768"); + + public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); } /** - * {@snippet lang=c : - * BIGNUM *BN_get_rfc2409_prime_768(BIGNUM *bn) + * Function descriptor for: + * {@snippet lang = c : * BIGNUM *BN_get_rfc2409_prime_768(BIGNUM *bn) + * } + */ + public static FunctionDescriptor BN_get_rfc2409_prime_768$descriptor() { + return BN_get_rfc2409_prime_768.DESC; + } + + /** + * Downcall method handle for: + * {@snippet lang = c : * BIGNUM *BN_get_rfc2409_prime_768(BIGNUM *bn) + * } + */ + public static MethodHandle BN_get_rfc2409_prime_768$handle() { + return BN_get_rfc2409_prime_768.HANDLE; + } + + /** + * Address for: + * {@snippet lang = c : * BIGNUM *BN_get_rfc2409_prime_768(BIGNUM *bn) + * } + */ + public static MemorySegment BN_get_rfc2409_prime_768$address() { + return BN_get_rfc2409_prime_768.ADDR; + } + + /** + * {@snippet lang = c : * BIGNUM *BN_get_rfc2409_prime_768(BIGNUM *bn) * } */ public static MemorySegment BN_get_rfc2409_prime_768(MemorySegment bn) { - var mh$ = BN_get_rfc2409_prime_768$MH(); + var mh$ = BN_get_rfc2409_prime_768.HANDLE; try { if (TRACE_DOWNCALLS) { traceDowncall("BN_get_rfc2409_prime_768", bn); } return (MemorySegment) mh$.invokeExact(bn); } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); + throw new AssertionError("should not reach here", ex$); } } - private static MethodHandle BN_get_rfc2409_prime_1024$MH() { - class Holder { - static final FunctionDescriptor DESC = FunctionDescriptor.of( - openssl_h.C_POINTER, - openssl_h.C_POINTER - ); - - static final MethodHandle MH = Linker.nativeLinker().downcallHandle( - openssl_h.findOrThrow("BN_get_rfc2409_prime_1024"), - DESC); - } - return Holder.MH; + private static class BN_get_rfc2409_prime_1024 { + public static final FunctionDescriptor DESC = FunctionDescriptor.of(openssl_h.C_POINTER, openssl_h.C_POINTER); + + public static final MemorySegment ADDR = openssl_h.findOrThrow("BN_get_rfc2409_prime_1024"); + + public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); } /** - * {@snippet lang=c : - * BIGNUM *BN_get_rfc2409_prime_1024(BIGNUM *bn) + * Function descriptor for: + * {@snippet lang = c : * BIGNUM *BN_get_rfc2409_prime_1024(BIGNUM *bn) + * } + */ + public static FunctionDescriptor BN_get_rfc2409_prime_1024$descriptor() { + return BN_get_rfc2409_prime_1024.DESC; + } + + /** + * Downcall method handle for: + * {@snippet lang = c : * BIGNUM *BN_get_rfc2409_prime_1024(BIGNUM *bn) + * } + */ + public static MethodHandle BN_get_rfc2409_prime_1024$handle() { + return BN_get_rfc2409_prime_1024.HANDLE; + } + + /** + * Address for: + * {@snippet lang = c : * BIGNUM *BN_get_rfc2409_prime_1024(BIGNUM *bn) + * } + */ + public static MemorySegment BN_get_rfc2409_prime_1024$address() { + return BN_get_rfc2409_prime_1024.ADDR; + } + + /** + * {@snippet lang = c : * BIGNUM *BN_get_rfc2409_prime_1024(BIGNUM *bn) * } */ public static MemorySegment BN_get_rfc2409_prime_1024(MemorySegment bn) { - var mh$ = BN_get_rfc2409_prime_1024$MH(); + var mh$ = BN_get_rfc2409_prime_1024.HANDLE; try { if (TRACE_DOWNCALLS) { traceDowncall("BN_get_rfc2409_prime_1024", bn); } return (MemorySegment) mh$.invokeExact(bn); } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); + throw new AssertionError("should not reach here", ex$); } } - private static MethodHandle BN_get_rfc3526_prime_1536$MH() { - class Holder { - static final FunctionDescriptor DESC = FunctionDescriptor.of( - openssl_h.C_POINTER, - openssl_h.C_POINTER - ); - - static final MethodHandle MH = Linker.nativeLinker().downcallHandle( - openssl_h.findOrThrow("BN_get_rfc3526_prime_1536"), - DESC); - } - return Holder.MH; + private static class BN_get_rfc3526_prime_1536 { + public static final FunctionDescriptor DESC = FunctionDescriptor.of(openssl_h.C_POINTER, openssl_h.C_POINTER); + + public static final MemorySegment ADDR = openssl_h.findOrThrow("BN_get_rfc3526_prime_1536"); + + public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); } /** - * {@snippet lang=c : - * BIGNUM *BN_get_rfc3526_prime_1536(BIGNUM *bn) + * Function descriptor for: + * {@snippet lang = c : * BIGNUM *BN_get_rfc3526_prime_1536(BIGNUM *bn) + * } + */ + public static FunctionDescriptor BN_get_rfc3526_prime_1536$descriptor() { + return BN_get_rfc3526_prime_1536.DESC; + } + + /** + * Downcall method handle for: + * {@snippet lang = c : * BIGNUM *BN_get_rfc3526_prime_1536(BIGNUM *bn) + * } + */ + public static MethodHandle BN_get_rfc3526_prime_1536$handle() { + return BN_get_rfc3526_prime_1536.HANDLE; + } + + /** + * Address for: + * {@snippet lang = c : * BIGNUM *BN_get_rfc3526_prime_1536(BIGNUM *bn) + * } + */ + public static MemorySegment BN_get_rfc3526_prime_1536$address() { + return BN_get_rfc3526_prime_1536.ADDR; + } + + /** + * {@snippet lang = c : * BIGNUM *BN_get_rfc3526_prime_1536(BIGNUM *bn) * } */ public static MemorySegment BN_get_rfc3526_prime_1536(MemorySegment bn) { - var mh$ = BN_get_rfc3526_prime_1536$MH(); + var mh$ = BN_get_rfc3526_prime_1536.HANDLE; try { if (TRACE_DOWNCALLS) { traceDowncall("BN_get_rfc3526_prime_1536", bn); } return (MemorySegment) mh$.invokeExact(bn); } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); + throw new AssertionError("should not reach here", ex$); } } - private static MethodHandle BN_get_rfc3526_prime_2048$MH() { - class Holder { - static final FunctionDescriptor DESC = FunctionDescriptor.of( - openssl_h.C_POINTER, - openssl_h.C_POINTER - ); - - static final MethodHandle MH = Linker.nativeLinker().downcallHandle( - openssl_h.findOrThrow("BN_get_rfc3526_prime_2048"), - DESC); - } - return Holder.MH; + private static class BN_get_rfc3526_prime_2048 { + public static final FunctionDescriptor DESC = FunctionDescriptor.of(openssl_h.C_POINTER, openssl_h.C_POINTER); + + public static final MemorySegment ADDR = openssl_h.findOrThrow("BN_get_rfc3526_prime_2048"); + + public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); } /** - * {@snippet lang=c : - * BIGNUM *BN_get_rfc3526_prime_2048(BIGNUM *bn) + * Function descriptor for: + * {@snippet lang = c : * BIGNUM *BN_get_rfc3526_prime_2048(BIGNUM *bn) + * } + */ + public static FunctionDescriptor BN_get_rfc3526_prime_2048$descriptor() { + return BN_get_rfc3526_prime_2048.DESC; + } + + /** + * Downcall method handle for: + * {@snippet lang = c : * BIGNUM *BN_get_rfc3526_prime_2048(BIGNUM *bn) + * } + */ + public static MethodHandle BN_get_rfc3526_prime_2048$handle() { + return BN_get_rfc3526_prime_2048.HANDLE; + } + + /** + * Address for: + * {@snippet lang = c : * BIGNUM *BN_get_rfc3526_prime_2048(BIGNUM *bn) + * } + */ + public static MemorySegment BN_get_rfc3526_prime_2048$address() { + return BN_get_rfc3526_prime_2048.ADDR; + } + + /** + * {@snippet lang = c : * BIGNUM *BN_get_rfc3526_prime_2048(BIGNUM *bn) * } */ public static MemorySegment BN_get_rfc3526_prime_2048(MemorySegment bn) { - var mh$ = BN_get_rfc3526_prime_2048$MH(); + var mh$ = BN_get_rfc3526_prime_2048.HANDLE; try { if (TRACE_DOWNCALLS) { traceDowncall("BN_get_rfc3526_prime_2048", bn); } return (MemorySegment) mh$.invokeExact(bn); } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); + throw new AssertionError("should not reach here", ex$); } } - private static MethodHandle BN_get_rfc3526_prime_3072$MH() { - class Holder { - static final FunctionDescriptor DESC = FunctionDescriptor.of( - openssl_h.C_POINTER, - openssl_h.C_POINTER - ); - - static final MethodHandle MH = Linker.nativeLinker().downcallHandle( - openssl_h.findOrThrow("BN_get_rfc3526_prime_3072"), - DESC); - } - return Holder.MH; + private static class BN_get_rfc3526_prime_3072 { + public static final FunctionDescriptor DESC = FunctionDescriptor.of(openssl_h.C_POINTER, openssl_h.C_POINTER); + + public static final MemorySegment ADDR = openssl_h.findOrThrow("BN_get_rfc3526_prime_3072"); + + public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); } /** - * {@snippet lang=c : - * BIGNUM *BN_get_rfc3526_prime_3072(BIGNUM *bn) + * Function descriptor for: + * {@snippet lang = c : * BIGNUM *BN_get_rfc3526_prime_3072(BIGNUM *bn) + * } + */ + public static FunctionDescriptor BN_get_rfc3526_prime_3072$descriptor() { + return BN_get_rfc3526_prime_3072.DESC; + } + + /** + * Downcall method handle for: + * {@snippet lang = c : * BIGNUM *BN_get_rfc3526_prime_3072(BIGNUM *bn) + * } + */ + public static MethodHandle BN_get_rfc3526_prime_3072$handle() { + return BN_get_rfc3526_prime_3072.HANDLE; + } + + /** + * Address for: + * {@snippet lang = c : * BIGNUM *BN_get_rfc3526_prime_3072(BIGNUM *bn) + * } + */ + public static MemorySegment BN_get_rfc3526_prime_3072$address() { + return BN_get_rfc3526_prime_3072.ADDR; + } + + /** + * {@snippet lang = c : * BIGNUM *BN_get_rfc3526_prime_3072(BIGNUM *bn) * } */ public static MemorySegment BN_get_rfc3526_prime_3072(MemorySegment bn) { - var mh$ = BN_get_rfc3526_prime_3072$MH(); + var mh$ = BN_get_rfc3526_prime_3072.HANDLE; try { if (TRACE_DOWNCALLS) { traceDowncall("BN_get_rfc3526_prime_3072", bn); } return (MemorySegment) mh$.invokeExact(bn); } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); + throw new AssertionError("should not reach here", ex$); } } - private static MethodHandle BN_get_rfc3526_prime_4096$MH() { - class Holder { - static final FunctionDescriptor DESC = FunctionDescriptor.of( - openssl_h.C_POINTER, - openssl_h.C_POINTER - ); - - static final MethodHandle MH = Linker.nativeLinker().downcallHandle( - openssl_h.findOrThrow("BN_get_rfc3526_prime_4096"), - DESC); - } - return Holder.MH; + private static class BN_get_rfc3526_prime_4096 { + public static final FunctionDescriptor DESC = FunctionDescriptor.of(openssl_h.C_POINTER, openssl_h.C_POINTER); + + public static final MemorySegment ADDR = openssl_h.findOrThrow("BN_get_rfc3526_prime_4096"); + + public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); } /** - * {@snippet lang=c : - * BIGNUM *BN_get_rfc3526_prime_4096(BIGNUM *bn) + * Function descriptor for: + * {@snippet lang = c : * BIGNUM *BN_get_rfc3526_prime_4096(BIGNUM *bn) + * } + */ + public static FunctionDescriptor BN_get_rfc3526_prime_4096$descriptor() { + return BN_get_rfc3526_prime_4096.DESC; + } + + /** + * Downcall method handle for: + * {@snippet lang = c : * BIGNUM *BN_get_rfc3526_prime_4096(BIGNUM *bn) + * } + */ + public static MethodHandle BN_get_rfc3526_prime_4096$handle() { + return BN_get_rfc3526_prime_4096.HANDLE; + } + + /** + * Address for: + * {@snippet lang = c : * BIGNUM *BN_get_rfc3526_prime_4096(BIGNUM *bn) + * } + */ + public static MemorySegment BN_get_rfc3526_prime_4096$address() { + return BN_get_rfc3526_prime_4096.ADDR; + } + + /** + * {@snippet lang = c : * BIGNUM *BN_get_rfc3526_prime_4096(BIGNUM *bn) * } */ public static MemorySegment BN_get_rfc3526_prime_4096(MemorySegment bn) { - var mh$ = BN_get_rfc3526_prime_4096$MH(); + var mh$ = BN_get_rfc3526_prime_4096.HANDLE; try { if (TRACE_DOWNCALLS) { traceDowncall("BN_get_rfc3526_prime_4096", bn); } return (MemorySegment) mh$.invokeExact(bn); } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); + throw new AssertionError("should not reach here", ex$); } } - private static MethodHandle BN_get_rfc3526_prime_6144$MH() { - class Holder { - static final FunctionDescriptor DESC = FunctionDescriptor.of( - openssl_h.C_POINTER, - openssl_h.C_POINTER - ); - - static final MethodHandle MH = Linker.nativeLinker().downcallHandle( - openssl_h.findOrThrow("BN_get_rfc3526_prime_6144"), - DESC); - } - return Holder.MH; + private static class BN_get_rfc3526_prime_6144 { + public static final FunctionDescriptor DESC = FunctionDescriptor.of(openssl_h.C_POINTER, openssl_h.C_POINTER); + + public static final MemorySegment ADDR = openssl_h.findOrThrow("BN_get_rfc3526_prime_6144"); + + public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); } /** - * {@snippet lang=c : - * BIGNUM *BN_get_rfc3526_prime_6144(BIGNUM *bn) + * Function descriptor for: + * {@snippet lang = c : * BIGNUM *BN_get_rfc3526_prime_6144(BIGNUM *bn) + * } + */ + public static FunctionDescriptor BN_get_rfc3526_prime_6144$descriptor() { + return BN_get_rfc3526_prime_6144.DESC; + } + + /** + * Downcall method handle for: + * {@snippet lang = c : * BIGNUM *BN_get_rfc3526_prime_6144(BIGNUM *bn) + * } + */ + public static MethodHandle BN_get_rfc3526_prime_6144$handle() { + return BN_get_rfc3526_prime_6144.HANDLE; + } + + /** + * Address for: + * {@snippet lang = c : * BIGNUM *BN_get_rfc3526_prime_6144(BIGNUM *bn) + * } + */ + public static MemorySegment BN_get_rfc3526_prime_6144$address() { + return BN_get_rfc3526_prime_6144.ADDR; + } + + /** + * {@snippet lang = c : * BIGNUM *BN_get_rfc3526_prime_6144(BIGNUM *bn) * } */ public static MemorySegment BN_get_rfc3526_prime_6144(MemorySegment bn) { - var mh$ = BN_get_rfc3526_prime_6144$MH(); + var mh$ = BN_get_rfc3526_prime_6144.HANDLE; try { if (TRACE_DOWNCALLS) { traceDowncall("BN_get_rfc3526_prime_6144", bn); } return (MemorySegment) mh$.invokeExact(bn); } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); + throw new AssertionError("should not reach here", ex$); } } - private static MethodHandle BN_get_rfc3526_prime_8192$MH() { - class Holder { - static final FunctionDescriptor DESC = FunctionDescriptor.of( - openssl_h.C_POINTER, - openssl_h.C_POINTER - ); - - static final MethodHandle MH = Linker.nativeLinker().downcallHandle( - openssl_h.findOrThrow("BN_get_rfc3526_prime_8192"), - DESC); - } - return Holder.MH; + private static class BN_get_rfc3526_prime_8192 { + public static final FunctionDescriptor DESC = FunctionDescriptor.of(openssl_h.C_POINTER, openssl_h.C_POINTER); + + public static final MemorySegment ADDR = openssl_h.findOrThrow("BN_get_rfc3526_prime_8192"); + + public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); } /** - * {@snippet lang=c : - * BIGNUM *BN_get_rfc3526_prime_8192(BIGNUM *bn) + * Function descriptor for: + * {@snippet lang = c : * BIGNUM *BN_get_rfc3526_prime_8192(BIGNUM *bn) + * } + */ + public static FunctionDescriptor BN_get_rfc3526_prime_8192$descriptor() { + return BN_get_rfc3526_prime_8192.DESC; + } + + /** + * Downcall method handle for: + * {@snippet lang = c : * BIGNUM *BN_get_rfc3526_prime_8192(BIGNUM *bn) + * } + */ + public static MethodHandle BN_get_rfc3526_prime_8192$handle() { + return BN_get_rfc3526_prime_8192.HANDLE; + } + + /** + * Address for: + * {@snippet lang = c : * BIGNUM *BN_get_rfc3526_prime_8192(BIGNUM *bn) + * } + */ + public static MemorySegment BN_get_rfc3526_prime_8192$address() { + return BN_get_rfc3526_prime_8192.ADDR; + } + + /** + * {@snippet lang = c : * BIGNUM *BN_get_rfc3526_prime_8192(BIGNUM *bn) * } */ public static MemorySegment BN_get_rfc3526_prime_8192(MemorySegment bn) { - var mh$ = BN_get_rfc3526_prime_8192$MH(); + var mh$ = BN_get_rfc3526_prime_8192.HANDLE; try { if (TRACE_DOWNCALLS) { traceDowncall("BN_get_rfc3526_prime_8192", bn); } return (MemorySegment) mh$.invokeExact(bn); } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); + throw new AssertionError("should not reach here", ex$); } } - private static MethodHandle ASN1_STRING_length$MH() { - class Holder { - static final FunctionDescriptor DESC = FunctionDescriptor.of( - openssl_h.C_INT, - openssl_h.C_POINTER - ); - - static final MethodHandle MH = Linker.nativeLinker().downcallHandle( - openssl_h.findOrThrow("ASN1_STRING_length"), - DESC); - } - return Holder.MH; + private static class ASN1_STRING_length { + public static final FunctionDescriptor DESC = FunctionDescriptor.of(openssl_h.C_INT, openssl_h.C_POINTER); + + public static final MemorySegment ADDR = openssl_h.findOrThrow("ASN1_STRING_length"); + + public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); } /** - * {@snippet lang=c : - * int ASN1_STRING_length(const ASN1_STRING *x) + * Function descriptor for: + * {@snippet lang = c : * int ASN1_STRING_length(const ASN1_STRING *x) + * } + */ + public static FunctionDescriptor ASN1_STRING_length$descriptor() { + return ASN1_STRING_length.DESC; + } + + /** + * Downcall method handle for: + * {@snippet lang = c : * int ASN1_STRING_length(const ASN1_STRING *x) + * } + */ + public static MethodHandle ASN1_STRING_length$handle() { + return ASN1_STRING_length.HANDLE; + } + + /** + * Address for: + * {@snippet lang = c : * int ASN1_STRING_length(const ASN1_STRING *x) + * } + */ + public static MemorySegment ASN1_STRING_length$address() { + return ASN1_STRING_length.ADDR; + } + + /** + * {@snippet lang = c : * int ASN1_STRING_length(const ASN1_STRING *x) * } */ public static int ASN1_STRING_length(MemorySegment x) { - var mh$ = ASN1_STRING_length$MH(); + var mh$ = ASN1_STRING_length.HANDLE; try { if (TRACE_DOWNCALLS) { traceDowncall("ASN1_STRING_length", x); } return (int) mh$.invokeExact(x); } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); + throw new AssertionError("should not reach here", ex$); } } - private static MethodHandle ASN1_STRING_get0_data$MH() { - class Holder { - static final FunctionDescriptor DESC = FunctionDescriptor.of( - openssl_h.C_POINTER, - openssl_h.C_POINTER - ); - - static final MethodHandle MH = Linker.nativeLinker().downcallHandle( - openssl_h.findOrThrow("ASN1_STRING_get0_data"), - DESC); - } - return Holder.MH; + private static class ASN1_STRING_get0_data { + public static final FunctionDescriptor DESC = FunctionDescriptor.of(openssl_h.C_POINTER, openssl_h.C_POINTER); + + public static final MemorySegment ADDR = openssl_h.findOrThrow("ASN1_STRING_get0_data"); + + public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); } /** - * {@snippet lang=c : - * const unsigned char *ASN1_STRING_get0_data(const ASN1_STRING *x) + * Function descriptor for: + * {@snippet lang = c : * const unsigned char *ASN1_STRING_get0_data(const ASN1_STRING *x) + * } + */ + public static FunctionDescriptor ASN1_STRING_get0_data$descriptor() { + return ASN1_STRING_get0_data.DESC; + } + + /** + * Downcall method handle for: + * {@snippet lang = c : * const unsigned char *ASN1_STRING_get0_data(const ASN1_STRING *x) + * } + */ + public static MethodHandle ASN1_STRING_get0_data$handle() { + return ASN1_STRING_get0_data.HANDLE; + } + + /** + * Address for: + * {@snippet lang = c : * const unsigned char *ASN1_STRING_get0_data(const ASN1_STRING *x) + * } + */ + public static MemorySegment ASN1_STRING_get0_data$address() { + return ASN1_STRING_get0_data.ADDR; + } + + /** + * {@snippet lang = c : * const unsigned char *ASN1_STRING_get0_data(const ASN1_STRING *x) * } */ public static MemorySegment ASN1_STRING_get0_data(MemorySegment x) { - var mh$ = ASN1_STRING_get0_data$MH(); + var mh$ = ASN1_STRING_get0_data.HANDLE; try { if (TRACE_DOWNCALLS) { traceDowncall("ASN1_STRING_get0_data", x); } return (MemorySegment) mh$.invokeExact(x); } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); + throw new AssertionError("should not reach here", ex$); } } - private static MethodHandle EVP_MD_get0_provider$MH() { - class Holder { - static final FunctionDescriptor DESC = FunctionDescriptor.of( - openssl_h.C_POINTER, - openssl_h.C_POINTER - ); - - static final MethodHandle MH = Linker.nativeLinker().downcallHandle( - openssl_h.findOrThrow("EVP_MD_get0_provider"), - DESC); - } - return Holder.MH; + private static class EVP_MD_get0_provider { + public static final FunctionDescriptor DESC = FunctionDescriptor.of(openssl_h.C_POINTER, openssl_h.C_POINTER); + + public static final MemorySegment ADDR = openssl_h.findOrThrow("EVP_MD_get0_provider"); + + public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); } /** - * {@snippet lang=c : - * const OSSL_PROVIDER *EVP_MD_get0_provider(const EVP_MD *md) + * Function descriptor for: + * {@snippet lang = c : * const OSSL_PROVIDER *EVP_MD_get0_provider(const EVP_MD *md) + * } + */ + public static FunctionDescriptor EVP_MD_get0_provider$descriptor() { + return EVP_MD_get0_provider.DESC; + } + + /** + * Downcall method handle for: + * {@snippet lang = c : * const OSSL_PROVIDER *EVP_MD_get0_provider(const EVP_MD *md) + * } + */ + public static MethodHandle EVP_MD_get0_provider$handle() { + return EVP_MD_get0_provider.HANDLE; + } + + /** + * Address for: + * {@snippet lang = c : * const OSSL_PROVIDER *EVP_MD_get0_provider(const EVP_MD *md) + * } + */ + public static MemorySegment EVP_MD_get0_provider$address() { + return EVP_MD_get0_provider.ADDR; + } + + /** + * {@snippet lang = c : * const OSSL_PROVIDER *EVP_MD_get0_provider(const EVP_MD *md) * } */ public static MemorySegment EVP_MD_get0_provider(MemorySegment md) { - var mh$ = EVP_MD_get0_provider$MH(); + var mh$ = EVP_MD_get0_provider.HANDLE; try { if (TRACE_DOWNCALLS) { traceDowncall("EVP_MD_get0_provider", md); } return (MemorySegment) mh$.invokeExact(md); } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); + throw new AssertionError("should not reach here", ex$); } } - private static MethodHandle EVP_MD_fetch$MH() { - class Holder { - static final FunctionDescriptor DESC = FunctionDescriptor.of( - openssl_h.C_POINTER, - openssl_h.C_POINTER, - openssl_h.C_POINTER, - openssl_h.C_POINTER - ); - - static final MethodHandle MH = Linker.nativeLinker().downcallHandle( - openssl_h.findOrThrow("EVP_MD_fetch"), - DESC); - } - return Holder.MH; + private static class EVP_MD_fetch { + public static final FunctionDescriptor DESC = FunctionDescriptor.of(openssl_h.C_POINTER, openssl_h.C_POINTER, + openssl_h.C_POINTER, openssl_h.C_POINTER); + + public static final MemorySegment ADDR = openssl_h.findOrThrow("EVP_MD_fetch"); + + public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); } /** - * {@snippet lang=c : - * EVP_MD *EVP_MD_fetch(OSSL_LIB_CTX *ctx, const char *algorithm, const char *properties) + * Function descriptor for: + * {@snippet lang = c : * EVP_MD *EVP_MD_fetch(OSSL_LIB_CTX *ctx, const char *algorithm, const char *properties) + * } + */ + public static FunctionDescriptor EVP_MD_fetch$descriptor() { + return EVP_MD_fetch.DESC; + } + + /** + * Downcall method handle for: + * {@snippet lang = c : * EVP_MD *EVP_MD_fetch(OSSL_LIB_CTX *ctx, const char *algorithm, const char *properties) + * } + */ + public static MethodHandle EVP_MD_fetch$handle() { + return EVP_MD_fetch.HANDLE; + } + + /** + * Address for: + * {@snippet lang = c : * EVP_MD *EVP_MD_fetch(OSSL_LIB_CTX *ctx, const char *algorithm, const char *properties) + * } + */ + public static MemorySegment EVP_MD_fetch$address() { + return EVP_MD_fetch.ADDR; + } + + /** + * {@snippet lang = c : * EVP_MD *EVP_MD_fetch(OSSL_LIB_CTX *ctx, const char *algorithm, const char *properties) * } */ public static MemorySegment EVP_MD_fetch(MemorySegment ctx, MemorySegment algorithm, MemorySegment properties) { - var mh$ = EVP_MD_fetch$MH(); + var mh$ = EVP_MD_fetch.HANDLE; try { if (TRACE_DOWNCALLS) { traceDowncall("EVP_MD_fetch", ctx, algorithm, properties); } return (MemorySegment) mh$.invokeExact(ctx, algorithm, properties); } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); + throw new AssertionError("should not reach here", ex$); } } - private static MethodHandle EVP_MD_free$MH() { - class Holder { - static final FunctionDescriptor DESC = FunctionDescriptor.ofVoid( - openssl_h.C_POINTER - ); - - static final MethodHandle MH = Linker.nativeLinker().downcallHandle( - openssl_h.findOrThrow("EVP_MD_free"), - DESC); - } - return Holder.MH; + private static class EVP_MD_free { + public static final FunctionDescriptor DESC = FunctionDescriptor.ofVoid(openssl_h.C_POINTER); + + public static final MemorySegment ADDR = openssl_h.findOrThrow("EVP_MD_free"); + + public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); } /** - * {@snippet lang=c : - * void EVP_MD_free(EVP_MD *md) + * Function descriptor for: + * {@snippet lang = c : * void EVP_MD_free(EVP_MD *md) + * } + */ + public static FunctionDescriptor EVP_MD_free$descriptor() { + return EVP_MD_free.DESC; + } + + /** + * Downcall method handle for: + * {@snippet lang = c : * void EVP_MD_free(EVP_MD *md) + * } + */ + public static MethodHandle EVP_MD_free$handle() { + return EVP_MD_free.HANDLE; + } + + /** + * Address for: + * {@snippet lang = c : * void EVP_MD_free(EVP_MD *md) + * } + */ + public static MemorySegment EVP_MD_free$address() { + return EVP_MD_free.ADDR; + } + + /** + * {@snippet lang = c : * void EVP_MD_free(EVP_MD *md) * } */ public static void EVP_MD_free(MemorySegment md) { - var mh$ = EVP_MD_free$MH(); + var mh$ = EVP_MD_free.HANDLE; try { if (TRACE_DOWNCALLS) { traceDowncall("EVP_MD_free", md); } mh$.invokeExact(md); } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); + throw new AssertionError("should not reach here", ex$); } } - private static MethodHandle EVP_PKEY_get_base_id$MH() { - class Holder { - static final FunctionDescriptor DESC = FunctionDescriptor.of( - openssl_h.C_INT, - openssl_h.C_POINTER - ); - - static final MethodHandle MH = Linker.nativeLinker().downcallHandle( - openssl_h.findOrThrow("EVP_PKEY_get_base_id"), - DESC); - } - return Holder.MH; + private static class EVP_PKEY_get_base_id { + public static final FunctionDescriptor DESC = FunctionDescriptor.of(openssl_h.C_INT, openssl_h.C_POINTER); + + public static final MemorySegment ADDR = openssl_h.findOrThrow("EVP_PKEY_get_base_id"); + + public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); } /** - * {@snippet lang=c : - * int EVP_PKEY_get_base_id(const EVP_PKEY *pkey) + * Function descriptor for: + * {@snippet lang = c : * int EVP_PKEY_get_base_id(const EVP_PKEY *pkey) + * } + */ + public static FunctionDescriptor EVP_PKEY_get_base_id$descriptor() { + return EVP_PKEY_get_base_id.DESC; + } + + /** + * Downcall method handle for: + * {@snippet lang = c : * int EVP_PKEY_get_base_id(const EVP_PKEY *pkey) + * } + */ + public static MethodHandle EVP_PKEY_get_base_id$handle() { + return EVP_PKEY_get_base_id.HANDLE; + } + + /** + * Address for: + * {@snippet lang = c : * int EVP_PKEY_get_base_id(const EVP_PKEY *pkey) + * } + */ + public static MemorySegment EVP_PKEY_get_base_id$address() { + return EVP_PKEY_get_base_id.ADDR; + } + + /** + * {@snippet lang = c : * int EVP_PKEY_get_base_id(const EVP_PKEY *pkey) * } */ public static int EVP_PKEY_get_base_id(MemorySegment pkey) { - var mh$ = EVP_PKEY_get_base_id$MH(); + var mh$ = EVP_PKEY_get_base_id.HANDLE; try { if (TRACE_DOWNCALLS) { traceDowncall("EVP_PKEY_get_base_id", pkey); } return (int) mh$.invokeExact(pkey); } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); + throw new AssertionError("should not reach here", ex$); } } - private static MethodHandle EVP_PKEY_get_bits$MH() { - class Holder { - static final FunctionDescriptor DESC = FunctionDescriptor.of( - openssl_h.C_INT, - openssl_h.C_POINTER - ); - - static final MethodHandle MH = Linker.nativeLinker().downcallHandle( - openssl_h.findOrThrow("EVP_PKEY_get_bits"), - DESC); - } - return Holder.MH; + private static class EVP_PKEY_get_bits { + public static final FunctionDescriptor DESC = FunctionDescriptor.of(openssl_h.C_INT, openssl_h.C_POINTER); + + public static final MemorySegment ADDR = openssl_h.findOrThrow("EVP_PKEY_get_bits"); + + public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); } /** - * {@snippet lang=c : - * int EVP_PKEY_get_bits(const EVP_PKEY *pkey) + * Function descriptor for: + * {@snippet lang = c : * int EVP_PKEY_get_bits(const EVP_PKEY *pkey) + * } + */ + public static FunctionDescriptor EVP_PKEY_get_bits$descriptor() { + return EVP_PKEY_get_bits.DESC; + } + + /** + * Downcall method handle for: + * {@snippet lang = c : * int EVP_PKEY_get_bits(const EVP_PKEY *pkey) + * } + */ + public static MethodHandle EVP_PKEY_get_bits$handle() { + return EVP_PKEY_get_bits.HANDLE; + } + + /** + * Address for: + * {@snippet lang = c : * int EVP_PKEY_get_bits(const EVP_PKEY *pkey) + * } + */ + public static MemorySegment EVP_PKEY_get_bits$address() { + return EVP_PKEY_get_bits.ADDR; + } + + /** + * {@snippet lang = c : * int EVP_PKEY_get_bits(const EVP_PKEY *pkey) * } */ public static int EVP_PKEY_get_bits(MemorySegment pkey) { - var mh$ = EVP_PKEY_get_bits$MH(); + var mh$ = EVP_PKEY_get_bits.HANDLE; try { if (TRACE_DOWNCALLS) { traceDowncall("EVP_PKEY_get_bits", pkey); } return (int) mh$.invokeExact(pkey); } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); + throw new AssertionError("should not reach here", ex$); } } - private static MethodHandle EVP_PKEY_free$MH() { - class Holder { - static final FunctionDescriptor DESC = FunctionDescriptor.ofVoid( - openssl_h.C_POINTER - ); - - static final MethodHandle MH = Linker.nativeLinker().downcallHandle( - openssl_h.findOrThrow("EVP_PKEY_free"), - DESC); - } - return Holder.MH; + private static class EVP_PKEY_free { + public static final FunctionDescriptor DESC = FunctionDescriptor.ofVoid(openssl_h.C_POINTER); + + public static final MemorySegment ADDR = openssl_h.findOrThrow("EVP_PKEY_free"); + + public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); } /** - * {@snippet lang=c : - * void EVP_PKEY_free(EVP_PKEY *pkey) + * Function descriptor for: + * {@snippet lang = c : * void EVP_PKEY_free(EVP_PKEY *pkey) + * } + */ + public static FunctionDescriptor EVP_PKEY_free$descriptor() { + return EVP_PKEY_free.DESC; + } + + /** + * Downcall method handle for: + * {@snippet lang = c : * void EVP_PKEY_free(EVP_PKEY *pkey) + * } + */ + public static MethodHandle EVP_PKEY_free$handle() { + return EVP_PKEY_free.HANDLE; + } + + /** + * Address for: + * {@snippet lang = c : * void EVP_PKEY_free(EVP_PKEY *pkey) + * } + */ + public static MemorySegment EVP_PKEY_free$address() { + return EVP_PKEY_free.ADDR; + } + + /** + * {@snippet lang = c : * void EVP_PKEY_free(EVP_PKEY *pkey) * } */ public static void EVP_PKEY_free(MemorySegment pkey) { - var mh$ = EVP_PKEY_free$MH(); + var mh$ = EVP_PKEY_free.HANDLE; try { if (TRACE_DOWNCALLS) { traceDowncall("EVP_PKEY_free", pkey); } mh$.invokeExact(pkey); } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); + throw new AssertionError("should not reach here", ex$); } } - private static MethodHandle EC_GROUP_free$MH() { - class Holder { - static final FunctionDescriptor DESC = FunctionDescriptor.ofVoid( - openssl_h.C_POINTER - ); - - static final MethodHandle MH = Linker.nativeLinker().downcallHandle( - openssl_h.findOrThrow("EC_GROUP_free"), - DESC); - } - return Holder.MH; + private static class EC_GROUP_free { + public static final FunctionDescriptor DESC = FunctionDescriptor.ofVoid(openssl_h.C_POINTER); + + public static final MemorySegment ADDR = openssl_h.findOrThrow("EC_GROUP_free"); + + public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); } /** - * {@snippet lang=c : - * void EC_GROUP_free(EC_GROUP *group) + * Function descriptor for: + * {@snippet lang = c : * void EC_GROUP_free(EC_GROUP *group) + * } + */ + public static FunctionDescriptor EC_GROUP_free$descriptor() { + return EC_GROUP_free.DESC; + } + + /** + * Downcall method handle for: + * {@snippet lang = c : * void EC_GROUP_free(EC_GROUP *group) + * } + */ + public static MethodHandle EC_GROUP_free$handle() { + return EC_GROUP_free.HANDLE; + } + + /** + * Address for: + * {@snippet lang = c : * void EC_GROUP_free(EC_GROUP *group) + * } + */ + public static MemorySegment EC_GROUP_free$address() { + return EC_GROUP_free.ADDR; + } + + /** + * {@snippet lang = c : * void EC_GROUP_free(EC_GROUP *group) * } */ public static void EC_GROUP_free(MemorySegment group) { - var mh$ = EC_GROUP_free$MH(); + var mh$ = EC_GROUP_free.HANDLE; try { if (TRACE_DOWNCALLS) { traceDowncall("EC_GROUP_free", group); } mh$.invokeExact(group); } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); + throw new AssertionError("should not reach here", ex$); } } - private static MethodHandle EC_GROUP_get_curve_name$MH() { - class Holder { - static final FunctionDescriptor DESC = FunctionDescriptor.of( - openssl_h.C_INT, - openssl_h.C_POINTER - ); - - static final MethodHandle MH = Linker.nativeLinker().downcallHandle( - openssl_h.findOrThrow("EC_GROUP_get_curve_name"), - DESC); - } - return Holder.MH; + private static class EC_GROUP_get_curve_name { + public static final FunctionDescriptor DESC = FunctionDescriptor.of(openssl_h.C_INT, openssl_h.C_POINTER); + + public static final MemorySegment ADDR = openssl_h.findOrThrow("EC_GROUP_get_curve_name"); + + public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); } /** - * {@snippet lang=c : - * int EC_GROUP_get_curve_name(const EC_GROUP *group) + * Function descriptor for: + * {@snippet lang = c : * int EC_GROUP_get_curve_name(const EC_GROUP *group) + * } + */ + public static FunctionDescriptor EC_GROUP_get_curve_name$descriptor() { + return EC_GROUP_get_curve_name.DESC; + } + + /** + * Downcall method handle for: + * {@snippet lang = c : * int EC_GROUP_get_curve_name(const EC_GROUP *group) + * } + */ + public static MethodHandle EC_GROUP_get_curve_name$handle() { + return EC_GROUP_get_curve_name.HANDLE; + } + + /** + * Address for: + * {@snippet lang = c : * int EC_GROUP_get_curve_name(const EC_GROUP *group) + * } + */ + public static MemorySegment EC_GROUP_get_curve_name$address() { + return EC_GROUP_get_curve_name.ADDR; + } + + /** + * {@snippet lang = c : * int EC_GROUP_get_curve_name(const EC_GROUP *group) * } */ public static int EC_GROUP_get_curve_name(MemorySegment group) { - var mh$ = EC_GROUP_get_curve_name$MH(); + var mh$ = EC_GROUP_get_curve_name.HANDLE; try { if (TRACE_DOWNCALLS) { traceDowncall("EC_GROUP_get_curve_name", group); } return (int) mh$.invokeExact(group); } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); + throw new AssertionError("should not reach here", ex$); } } - private static MethodHandle d2i_ECPKParameters$MH() { - class Holder { - static final FunctionDescriptor DESC = FunctionDescriptor.of( - openssl_h.C_POINTER, - openssl_h.C_POINTER, - openssl_h.C_POINTER, - openssl_h.C_LONG - ); - - static final MethodHandle MH = Linker.nativeLinker().downcallHandle( - openssl_h.findOrThrow("d2i_ECPKParameters"), - DESC); - } - return Holder.MH; + private static class d2i_ECPKParameters { + public static final FunctionDescriptor DESC = + FunctionDescriptor.of(openssl_h.C_POINTER, openssl_h.C_POINTER, openssl_h.C_POINTER, openssl_h.C_LONG); + + public static final MemorySegment ADDR = openssl_h.findOrThrow("d2i_ECPKParameters"); + + public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); } /** - * {@snippet lang=c : - * EC_GROUP *d2i_ECPKParameters(EC_GROUP **, const unsigned char **in, long len) + * Function descriptor for: + * {@snippet lang = c : * EC_GROUP *d2i_ECPKParameters(EC_GROUP **, const unsigned char **in, long len) + * } + */ + public static FunctionDescriptor d2i_ECPKParameters$descriptor() { + return d2i_ECPKParameters.DESC; + } + + /** + * Downcall method handle for: + * {@snippet lang = c : * EC_GROUP *d2i_ECPKParameters(EC_GROUP **, const unsigned char **in, long len) + * } + */ + public static MethodHandle d2i_ECPKParameters$handle() { + return d2i_ECPKParameters.HANDLE; + } + + /** + * Address for: + * {@snippet lang = c : * EC_GROUP *d2i_ECPKParameters(EC_GROUP **, const unsigned char **in, long len) + * } + */ + public static MemorySegment d2i_ECPKParameters$address() { + return d2i_ECPKParameters.ADDR; + } + + /** + * {@snippet lang = c : * EC_GROUP *d2i_ECPKParameters(EC_GROUP **, const unsigned char **in, long len) * } */ public static MemorySegment d2i_ECPKParameters(MemorySegment x0, MemorySegment in, long len) { - var mh$ = d2i_ECPKParameters$MH(); + var mh$ = d2i_ECPKParameters.HANDLE; try { if (TRACE_DOWNCALLS) { traceDowncall("d2i_ECPKParameters", x0, in, len); } return (MemorySegment) mh$.invokeExact(x0, in, len); } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); + throw new AssertionError("should not reach here", ex$); } } - private static MethodHandle EC_KEY_new_by_curve_name$MH() { - class Holder { - static final FunctionDescriptor DESC = FunctionDescriptor.of( - openssl_h.C_POINTER, - openssl_h.C_INT - ); - - static final MethodHandle MH = Linker.nativeLinker().downcallHandle( - openssl_h.findOrThrow("EC_KEY_new_by_curve_name"), - DESC); - } - return Holder.MH; + private static class EC_KEY_new_by_curve_name { + public static final FunctionDescriptor DESC = FunctionDescriptor.of(openssl_h.C_POINTER, openssl_h.C_INT); + + public static final MemorySegment ADDR = openssl_h.findOrThrow("EC_KEY_new_by_curve_name"); + + public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); } /** - * {@snippet lang=c : - * EC_KEY *EC_KEY_new_by_curve_name(int nid) + * Function descriptor for: + * {@snippet lang = c : * EC_KEY *EC_KEY_new_by_curve_name(int nid) + * } + */ + public static FunctionDescriptor EC_KEY_new_by_curve_name$descriptor() { + return EC_KEY_new_by_curve_name.DESC; + } + + /** + * Downcall method handle for: + * {@snippet lang = c : * EC_KEY *EC_KEY_new_by_curve_name(int nid) + * } + */ + public static MethodHandle EC_KEY_new_by_curve_name$handle() { + return EC_KEY_new_by_curve_name.HANDLE; + } + + /** + * Address for: + * {@snippet lang = c : * EC_KEY *EC_KEY_new_by_curve_name(int nid) + * } + */ + public static MemorySegment EC_KEY_new_by_curve_name$address() { + return EC_KEY_new_by_curve_name.ADDR; + } + + /** + * {@snippet lang = c : * EC_KEY *EC_KEY_new_by_curve_name(int nid) * } */ public static MemorySegment EC_KEY_new_by_curve_name(int nid) { - var mh$ = EC_KEY_new_by_curve_name$MH(); + var mh$ = EC_KEY_new_by_curve_name.HANDLE; try { if (TRACE_DOWNCALLS) { traceDowncall("EC_KEY_new_by_curve_name", nid); } return (MemorySegment) mh$.invokeExact(nid); } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); + throw new AssertionError("should not reach here", ex$); } } - private static MethodHandle EC_KEY_free$MH() { - class Holder { - static final FunctionDescriptor DESC = FunctionDescriptor.ofVoid( - openssl_h.C_POINTER - ); - - static final MethodHandle MH = Linker.nativeLinker().downcallHandle( - openssl_h.findOrThrow("EC_KEY_free"), - DESC); - } - return Holder.MH; + private static class EC_KEY_free { + public static final FunctionDescriptor DESC = FunctionDescriptor.ofVoid(openssl_h.C_POINTER); + + public static final MemorySegment ADDR = openssl_h.findOrThrow("EC_KEY_free"); + + public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); } /** - * {@snippet lang=c : - * void EC_KEY_free(EC_KEY *key) + * Function descriptor for: + * {@snippet lang = c : * void EC_KEY_free(EC_KEY *key) + * } + */ + public static FunctionDescriptor EC_KEY_free$descriptor() { + return EC_KEY_free.DESC; + } + + /** + * Downcall method handle for: + * {@snippet lang = c : * void EC_KEY_free(EC_KEY *key) + * } + */ + public static MethodHandle EC_KEY_free$handle() { + return EC_KEY_free.HANDLE; + } + + /** + * Address for: + * {@snippet lang = c : * void EC_KEY_free(EC_KEY *key) + * } + */ + public static MemorySegment EC_KEY_free$address() { + return EC_KEY_free.ADDR; + } + + /** + * {@snippet lang = c : * void EC_KEY_free(EC_KEY *key) * } */ public static void EC_KEY_free(MemorySegment key) { - var mh$ = EC_KEY_free$MH(); + var mh$ = EC_KEY_free.HANDLE; try { if (TRACE_DOWNCALLS) { traceDowncall("EC_KEY_free", key); } mh$.invokeExact(key); } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); + throw new AssertionError("should not reach here", ex$); } } - private static MethodHandle DH_new$MH() { - class Holder { - static final FunctionDescriptor DESC = FunctionDescriptor.of( - openssl_h.C_POINTER ); + private static class DH_new { + public static final FunctionDescriptor DESC = FunctionDescriptor.of(openssl_h.C_POINTER); - static final MethodHandle MH = Linker.nativeLinker().downcallHandle( - openssl_h.findOrThrow("DH_new"), - DESC); - } - return Holder.MH; + public static final MemorySegment ADDR = openssl_h.findOrThrow("DH_new"); + + public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); } /** - * {@snippet lang=c : - * DH *DH_new(void) + * Function descriptor for: + * {@snippet lang = c : * DH *DH_new() + * } + */ + public static FunctionDescriptor DH_new$descriptor() { + return DH_new.DESC; + } + + /** + * Downcall method handle for: + * {@snippet lang = c : * DH *DH_new() + * } + */ + public static MethodHandle DH_new$handle() { + return DH_new.HANDLE; + } + + /** + * Address for: + * {@snippet lang = c : * DH *DH_new() + * } + */ + public static MemorySegment DH_new$address() { + return DH_new.ADDR; + } + + /** + * {@snippet lang = c : * DH *DH_new() * } */ public static MemorySegment DH_new() { - var mh$ = DH_new$MH(); + var mh$ = DH_new.HANDLE; try { if (TRACE_DOWNCALLS) { traceDowncall("DH_new"); } return (MemorySegment) mh$.invokeExact(); } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); + throw new AssertionError("should not reach here", ex$); } } - private static MethodHandle DH_free$MH() { - class Holder { - static final FunctionDescriptor DESC = FunctionDescriptor.ofVoid( - openssl_h.C_POINTER - ); - - static final MethodHandle MH = Linker.nativeLinker().downcallHandle( - openssl_h.findOrThrow("DH_free"), - DESC); - } - return Holder.MH; + private static class DH_free { + public static final FunctionDescriptor DESC = FunctionDescriptor.ofVoid(openssl_h.C_POINTER); + + public static final MemorySegment ADDR = openssl_h.findOrThrow("DH_free"); + + public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); } /** - * {@snippet lang=c : - * void DH_free(DH *dh) + * Function descriptor for: + * {@snippet lang = c : * void DH_free(DH *dh) + * } + */ + public static FunctionDescriptor DH_free$descriptor() { + return DH_free.DESC; + } + + /** + * Downcall method handle for: + * {@snippet lang = c : * void DH_free(DH *dh) + * } + */ + public static MethodHandle DH_free$handle() { + return DH_free.HANDLE; + } + + /** + * Address for: + * {@snippet lang = c : * void DH_free(DH *dh) + * } + */ + public static MemorySegment DH_free$address() { + return DH_free.ADDR; + } + + /** + * {@snippet lang = c : * void DH_free(DH *dh) * } */ public static void DH_free(MemorySegment dh) { - var mh$ = DH_free$MH(); + var mh$ = DH_free.HANDLE; try { if (TRACE_DOWNCALLS) { traceDowncall("DH_free", dh); } mh$.invokeExact(dh); } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); + throw new AssertionError("should not reach here", ex$); } } - private static MethodHandle DH_set0_pqg$MH() { - class Holder { - static final FunctionDescriptor DESC = FunctionDescriptor.of( - openssl_h.C_INT, - openssl_h.C_POINTER, - openssl_h.C_POINTER, - openssl_h.C_POINTER, - openssl_h.C_POINTER - ); - - static final MethodHandle MH = Linker.nativeLinker().downcallHandle( - openssl_h.findOrThrow("DH_set0_pqg"), - DESC); - } - return Holder.MH; + private static class DH_set0_pqg { + public static final FunctionDescriptor DESC = FunctionDescriptor.of(openssl_h.C_INT, openssl_h.C_POINTER, + openssl_h.C_POINTER, openssl_h.C_POINTER, openssl_h.C_POINTER); + + public static final MemorySegment ADDR = openssl_h.findOrThrow("DH_set0_pqg"); + + public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); } /** - * {@snippet lang=c : - * int DH_set0_pqg(DH *dh, BIGNUM *p, BIGNUM *q, BIGNUM *g) + * Function descriptor for: + * {@snippet lang = c : * int DH_set0_pqg(DH *dh, BIGNUM *p, BIGNUM *q, BIGNUM *g) + * } + */ + public static FunctionDescriptor DH_set0_pqg$descriptor() { + return DH_set0_pqg.DESC; + } + + /** + * Downcall method handle for: + * {@snippet lang = c : * int DH_set0_pqg(DH *dh, BIGNUM *p, BIGNUM *q, BIGNUM *g) + * } + */ + public static MethodHandle DH_set0_pqg$handle() { + return DH_set0_pqg.HANDLE; + } + + /** + * Address for: + * {@snippet lang = c : * int DH_set0_pqg(DH *dh, BIGNUM *p, BIGNUM *q, BIGNUM *g) + * } + */ + public static MemorySegment DH_set0_pqg$address() { + return DH_set0_pqg.ADDR; + } + + /** + * {@snippet lang = c : * int DH_set0_pqg(DH *dh, BIGNUM *p, BIGNUM *q, BIGNUM *g) * } */ public static int DH_set0_pqg(MemorySegment dh, MemorySegment p, MemorySegment q, MemorySegment g) { - var mh$ = DH_set0_pqg$MH(); + var mh$ = DH_set0_pqg.HANDLE; try { if (TRACE_DOWNCALLS) { traceDowncall("DH_set0_pqg", dh, p, q, g); } return (int) mh$.invokeExact(dh, p, q, g); } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); + throw new AssertionError("should not reach here", ex$); } } - private static MethodHandle X509_STORE_set_flags$MH() { - class Holder { - static final FunctionDescriptor DESC = FunctionDescriptor.of( - openssl_h.C_INT, - openssl_h.C_POINTER, - openssl_h.C_LONG - ); - - static final MethodHandle MH = Linker.nativeLinker().downcallHandle( - openssl_h.findOrThrow("X509_STORE_set_flags"), - DESC); + private static class X509_STORE_set_flags { + public static final FunctionDescriptor DESC = + FunctionDescriptor.of(openssl_h.C_INT, openssl_h.C_POINTER, openssl_h.C_LONG); + + public static final MemorySegment ADDR = openssl_h.findOrThrow("X509_STORE_set_flags"); + + public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); + } + + /** + * Function descriptor for: + * {@snippet lang = c : * int X509_STORE_set_flags(X509_STORE *xs, unsigned long flags) + * } + */ + public static FunctionDescriptor X509_STORE_set_flags$descriptor() { + return X509_STORE_set_flags.DESC; + } + + /** + * Downcall method handle for: + * {@snippet lang = c : * int X509_STORE_set_flags(X509_STORE *xs, unsigned long flags) + * } + */ + public static MethodHandle X509_STORE_set_flags$handle() { + return X509_STORE_set_flags.HANDLE; + } + + /** + * Address for: + * {@snippet lang = c : * int X509_STORE_set_flags(X509_STORE *xs, unsigned long flags) + * } + */ + public static MemorySegment X509_STORE_set_flags$address() { + return X509_STORE_set_flags.ADDR; + } + + /** + * {@snippet lang = c : * int X509_STORE_set_flags(X509_STORE *xs, unsigned long flags) + * } + */ + public static int X509_STORE_set_flags(MemorySegment xs, long flags) { + var mh$ = X509_STORE_set_flags.HANDLE; + try { + if (TRACE_DOWNCALLS) { + traceDowncall("X509_STORE_set_flags", xs, flags); + } + return (int) mh$.invokeExact(xs, flags); + } catch (Throwable ex$) { + throw new AssertionError("should not reach here", ex$); } - return Holder.MH; + } + + private static class X509_STORE_CTX_get0_store { + public static final FunctionDescriptor DESC = FunctionDescriptor.of( + openssl_h.C_POINTER, + openssl_h.C_POINTER + ); + + public static final MemorySegment ADDR = openssl_h.findOrThrow("X509_STORE_CTX_get0_store"); + + public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); } /** + * Function descriptor for: * {@snippet lang=c : - * int X509_STORE_set_flags(X509_STORE *ctx, unsigned long flags) + * X509_STORE *X509_STORE_CTX_get0_store(const X509_STORE_CTX *ctx) * } */ - public static int X509_STORE_set_flags(MemorySegment ctx, long flags) { - var mh$ = X509_STORE_set_flags$MH(); + public static FunctionDescriptor X509_STORE_CTX_get0_store$descriptor() { + return X509_STORE_CTX_get0_store.DESC; + } + + /** + * Downcall method handle for: + * {@snippet lang=c : + * X509_STORE *X509_STORE_CTX_get0_store(const X509_STORE_CTX *ctx) + * } + */ + public static MethodHandle X509_STORE_CTX_get0_store$handle() { + return X509_STORE_CTX_get0_store.HANDLE; + } + + /** + * Address for: + * {@snippet lang=c : + * X509_STORE *X509_STORE_CTX_get0_store(const X509_STORE_CTX *ctx) + * } + */ + public static MemorySegment X509_STORE_CTX_get0_store$address() { + return X509_STORE_CTX_get0_store.ADDR; + } + + /** + * {@snippet lang=c : + * X509_STORE *X509_STORE_CTX_get0_store(const X509_STORE_CTX *ctx) + * } + */ + public static MemorySegment X509_STORE_CTX_get0_store(MemorySegment ctx) { + var mh$ = X509_STORE_CTX_get0_store.HANDLE; try { if (TRACE_DOWNCALLS) { - traceDowncall("X509_STORE_set_flags", ctx, flags); + traceDowncall("X509_STORE_CTX_get0_store", ctx); } - return (int) mh$.invokeExact(ctx, flags); + return (MemorySegment)mh$.invokeExact(ctx); + } catch (Error | RuntimeException ex) { + throw ex; } catch (Throwable ex$) { throw new AssertionError("should not reach here", ex$); } } - private static MethodHandle X509_STORE_CTX_get0_untrusted$MH() { - class Holder { - static final FunctionDescriptor DESC = FunctionDescriptor.of( - openssl_h.C_POINTER, - openssl_h.C_POINTER - ); - - static final MethodHandle MH = Linker.nativeLinker().downcallHandle( - openssl_h.findOrThrow("X509_STORE_CTX_get0_untrusted"), - DESC); - } - return Holder.MH; + private static class X509_STORE_CTX_get0_untrusted { + public static final FunctionDescriptor DESC = FunctionDescriptor.of(openssl_h.C_POINTER, openssl_h.C_POINTER); + + public static final MemorySegment ADDR = openssl_h.findOrThrow("X509_STORE_CTX_get0_untrusted"); + + public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); } /** - * {@snippet lang=c : - * struct stack_st_X509 *X509_STORE_CTX_get0_untrusted(const X509_STORE_CTX *ctx) + * Function descriptor for: + * {@snippet lang = c : * struct stack_st_X509 *X509_STORE_CTX_get0_untrusted(const X509_STORE_CTX *ctx) + * } + */ + public static FunctionDescriptor X509_STORE_CTX_get0_untrusted$descriptor() { + return X509_STORE_CTX_get0_untrusted.DESC; + } + + /** + * Downcall method handle for: + * {@snippet lang = c : * struct stack_st_X509 *X509_STORE_CTX_get0_untrusted(const X509_STORE_CTX *ctx) + * } + */ + public static MethodHandle X509_STORE_CTX_get0_untrusted$handle() { + return X509_STORE_CTX_get0_untrusted.HANDLE; + } + + /** + * Address for: + * {@snippet lang = c : * struct stack_st_X509 *X509_STORE_CTX_get0_untrusted(const X509_STORE_CTX *ctx) + * } + */ + public static MemorySegment X509_STORE_CTX_get0_untrusted$address() { + return X509_STORE_CTX_get0_untrusted.ADDR; + } + + /** + * {@snippet lang = c : * struct stack_st_X509 *X509_STORE_CTX_get0_untrusted(const X509_STORE_CTX *ctx) * } */ public static MemorySegment X509_STORE_CTX_get0_untrusted(MemorySegment ctx) { - var mh$ = X509_STORE_CTX_get0_untrusted$MH(); + var mh$ = X509_STORE_CTX_get0_untrusted.HANDLE; try { if (TRACE_DOWNCALLS) { traceDowncall("X509_STORE_CTX_get0_untrusted", ctx); } return (MemorySegment) mh$.invokeExact(ctx); } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); + throw new AssertionError("should not reach here", ex$); } } - private static MethodHandle X509_STORE_add_lookup$MH() { - class Holder { - static final FunctionDescriptor DESC = FunctionDescriptor.of( - openssl_h.C_POINTER, - openssl_h.C_POINTER, - openssl_h.C_POINTER - ); - - static final MethodHandle MH = Linker.nativeLinker().downcallHandle( - openssl_h.findOrThrow("X509_STORE_add_lookup"), - DESC); - } - return Holder.MH; + private static class X509_STORE_add_lookup { + public static final FunctionDescriptor DESC = + FunctionDescriptor.of(openssl_h.C_POINTER, openssl_h.C_POINTER, openssl_h.C_POINTER); + + public static final MemorySegment ADDR = openssl_h.findOrThrow("X509_STORE_add_lookup"); + + public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); } /** - * {@snippet lang=c : - * X509_LOOKUP *X509_STORE_add_lookup(X509_STORE *v, X509_LOOKUP_METHOD *m) + * Function descriptor for: + * {@snippet lang = c : * X509_LOOKUP *X509_STORE_add_lookup(X509_STORE *xs, X509_LOOKUP_METHOD *m) + * } + */ + public static FunctionDescriptor X509_STORE_add_lookup$descriptor() { + return X509_STORE_add_lookup.DESC; + } + + /** + * Downcall method handle for: + * {@snippet lang = c : * X509_LOOKUP *X509_STORE_add_lookup(X509_STORE *xs, X509_LOOKUP_METHOD *m) + * } + */ + public static MethodHandle X509_STORE_add_lookup$handle() { + return X509_STORE_add_lookup.HANDLE; + } + + /** + * Address for: + * {@snippet lang = c : * X509_LOOKUP *X509_STORE_add_lookup(X509_STORE *xs, X509_LOOKUP_METHOD *m) + * } + */ + public static MemorySegment X509_STORE_add_lookup$address() { + return X509_STORE_add_lookup.ADDR; + } + + /** + * {@snippet lang = c : * X509_LOOKUP *X509_STORE_add_lookup(X509_STORE *xs, X509_LOOKUP_METHOD *m) * } */ - public static MemorySegment X509_STORE_add_lookup(MemorySegment v, MemorySegment m) { - var mh$ = X509_STORE_add_lookup$MH(); + public static MemorySegment X509_STORE_add_lookup(MemorySegment xs, MemorySegment m) { + var mh$ = X509_STORE_add_lookup.HANDLE; try { if (TRACE_DOWNCALLS) { - traceDowncall("X509_STORE_add_lookup", v, m); + traceDowncall("X509_STORE_add_lookup", xs, m); } - return (MemorySegment) mh$.invokeExact(v, m); + return (MemorySegment) mh$.invokeExact(xs, m); } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); + throw new AssertionError("should not reach here", ex$); } } - private static MethodHandle X509_LOOKUP_hash_dir$MH() { - class Holder { - static final FunctionDescriptor DESC = FunctionDescriptor.of( - openssl_h.C_POINTER ); + private static class X509_LOOKUP_hash_dir { + public static final FunctionDescriptor DESC = FunctionDescriptor.of(openssl_h.C_POINTER); - static final MethodHandle MH = Linker.nativeLinker().downcallHandle( - openssl_h.findOrThrow("X509_LOOKUP_hash_dir"), - DESC); - } - return Holder.MH; + public static final MemorySegment ADDR = openssl_h.findOrThrow("X509_LOOKUP_hash_dir"); + + public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); } /** - * {@snippet lang=c : - * X509_LOOKUP_METHOD *X509_LOOKUP_hash_dir(void) + * Function descriptor for: + * {@snippet lang = c : * X509_LOOKUP_METHOD *X509_LOOKUP_hash_dir() + * } + */ + public static FunctionDescriptor X509_LOOKUP_hash_dir$descriptor() { + return X509_LOOKUP_hash_dir.DESC; + } + + /** + * Downcall method handle for: + * {@snippet lang = c : * X509_LOOKUP_METHOD *X509_LOOKUP_hash_dir() + * } + */ + public static MethodHandle X509_LOOKUP_hash_dir$handle() { + return X509_LOOKUP_hash_dir.HANDLE; + } + + /** + * Address for: + * {@snippet lang = c : * X509_LOOKUP_METHOD *X509_LOOKUP_hash_dir() + * } + */ + public static MemorySegment X509_LOOKUP_hash_dir$address() { + return X509_LOOKUP_hash_dir.ADDR; + } + + /** + * {@snippet lang = c : * X509_LOOKUP_METHOD *X509_LOOKUP_hash_dir() * } */ public static MemorySegment X509_LOOKUP_hash_dir() { - var mh$ = X509_LOOKUP_hash_dir$MH(); + var mh$ = X509_LOOKUP_hash_dir.HANDLE; try { if (TRACE_DOWNCALLS) { traceDowncall("X509_LOOKUP_hash_dir"); } return (MemorySegment) mh$.invokeExact(); } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); + throw new AssertionError("should not reach here", ex$); } } - private static MethodHandle X509_LOOKUP_file$MH() { - class Holder { - static final FunctionDescriptor DESC = FunctionDescriptor.of( - openssl_h.C_POINTER ); + private static class X509_LOOKUP_file { + public static final FunctionDescriptor DESC = FunctionDescriptor.of(openssl_h.C_POINTER); - static final MethodHandle MH = Linker.nativeLinker().downcallHandle( - openssl_h.findOrThrow("X509_LOOKUP_file"), - DESC); - } - return Holder.MH; + public static final MemorySegment ADDR = openssl_h.findOrThrow("X509_LOOKUP_file"); + + public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); } /** - * {@snippet lang=c : - * X509_LOOKUP_METHOD *X509_LOOKUP_file(void) + * Function descriptor for: + * {@snippet lang = c : * X509_LOOKUP_METHOD *X509_LOOKUP_file() + * } + */ + public static FunctionDescriptor X509_LOOKUP_file$descriptor() { + return X509_LOOKUP_file.DESC; + } + + /** + * Downcall method handle for: + * {@snippet lang = c : * X509_LOOKUP_METHOD *X509_LOOKUP_file() + * } + */ + public static MethodHandle X509_LOOKUP_file$handle() { + return X509_LOOKUP_file.HANDLE; + } + + /** + * Address for: + * {@snippet lang = c : * X509_LOOKUP_METHOD *X509_LOOKUP_file() + * } + */ + public static MemorySegment X509_LOOKUP_file$address() { + return X509_LOOKUP_file.ADDR; + } + + /** + * {@snippet lang = c : * X509_LOOKUP_METHOD *X509_LOOKUP_file() * } */ public static MemorySegment X509_LOOKUP_file() { - var mh$ = X509_LOOKUP_file$MH(); + var mh$ = X509_LOOKUP_file.HANDLE; try { if (TRACE_DOWNCALLS) { traceDowncall("X509_LOOKUP_file"); } return (MemorySegment) mh$.invokeExact(); } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); + throw new AssertionError("should not reach here", ex$); } } - private static MethodHandle X509_LOOKUP_ctrl$MH() { - class Holder { - static final FunctionDescriptor DESC = FunctionDescriptor.of( - openssl_h.C_INT, - openssl_h.C_POINTER, - openssl_h.C_INT, - openssl_h.C_POINTER, - openssl_h.C_LONG, - openssl_h.C_POINTER - ); - - static final MethodHandle MH = Linker.nativeLinker().downcallHandle( - openssl_h.findOrThrow("X509_LOOKUP_ctrl"), - DESC); - } - return Holder.MH; + private static class X509_LOOKUP_ctrl { + public static final FunctionDescriptor DESC = FunctionDescriptor.of(openssl_h.C_INT, openssl_h.C_POINTER, + openssl_h.C_INT, openssl_h.C_POINTER, openssl_h.C_LONG, openssl_h.C_POINTER); + + public static final MemorySegment ADDR = openssl_h.findOrThrow("X509_LOOKUP_ctrl"); + + public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); } /** - * {@snippet lang=c : - * int X509_LOOKUP_ctrl(X509_LOOKUP *ctx, int cmd, const char *argc, long argl, char **ret) + * Function descriptor for: + * {@snippet lang = c : * int X509_LOOKUP_ctrl(X509_LOOKUP *ctx, int cmd, const char *argc, long argl, char **ret) + * } + */ + public static FunctionDescriptor X509_LOOKUP_ctrl$descriptor() { + return X509_LOOKUP_ctrl.DESC; + } + + /** + * Downcall method handle for: + * {@snippet lang = c : * int X509_LOOKUP_ctrl(X509_LOOKUP *ctx, int cmd, const char *argc, long argl, char **ret) + * } + */ + public static MethodHandle X509_LOOKUP_ctrl$handle() { + return X509_LOOKUP_ctrl.HANDLE; + } + + /** + * Address for: + * {@snippet lang = c : * int X509_LOOKUP_ctrl(X509_LOOKUP *ctx, int cmd, const char *argc, long argl, char **ret) + * } + */ + public static MemorySegment X509_LOOKUP_ctrl$address() { + return X509_LOOKUP_ctrl.ADDR; + } + + /** + * {@snippet lang = c : * int X509_LOOKUP_ctrl(X509_LOOKUP *ctx, int cmd, const char *argc, long argl, char **ret) * } */ public static int X509_LOOKUP_ctrl(MemorySegment ctx, int cmd, MemorySegment argc, long argl, MemorySegment ret) { - var mh$ = X509_LOOKUP_ctrl$MH(); + var mh$ = X509_LOOKUP_ctrl.HANDLE; try { if (TRACE_DOWNCALLS) { traceDowncall("X509_LOOKUP_ctrl", ctx, cmd, argc, argl, ret); } return (int) mh$.invokeExact(ctx, cmd, argc, argl, ret); } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); + throw new AssertionError("should not reach here", ex$); } } - private static MethodHandle X509_STORE_CTX_get_ex_data$MH() { - class Holder { - static final FunctionDescriptor DESC = FunctionDescriptor.of( - openssl_h.C_POINTER, - openssl_h.C_POINTER, - openssl_h.C_INT - ); - - static final MethodHandle MH = Linker.nativeLinker().downcallHandle( - openssl_h.findOrThrow("X509_STORE_CTX_get_ex_data"), - DESC); - } - return Holder.MH; + private static class X509_STORE_CTX_get_ex_data { + public static final FunctionDescriptor DESC = + FunctionDescriptor.of(openssl_h.C_POINTER, openssl_h.C_POINTER, openssl_h.C_INT); + + public static final MemorySegment ADDR = openssl_h.findOrThrow("X509_STORE_CTX_get_ex_data"); + + public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); } /** - * {@snippet lang=c : - * void *X509_STORE_CTX_get_ex_data(const X509_STORE_CTX *ctx, int idx) + * Function descriptor for: + * {@snippet lang = c : * void *X509_STORE_CTX_get_ex_data(const X509_STORE_CTX *ctx, int idx) + * } + */ + public static FunctionDescriptor X509_STORE_CTX_get_ex_data$descriptor() { + return X509_STORE_CTX_get_ex_data.DESC; + } + + /** + * Downcall method handle for: + * {@snippet lang = c : * void *X509_STORE_CTX_get_ex_data(const X509_STORE_CTX *ctx, int idx) + * } + */ + public static MethodHandle X509_STORE_CTX_get_ex_data$handle() { + return X509_STORE_CTX_get_ex_data.HANDLE; + } + + /** + * Address for: + * {@snippet lang = c : * void *X509_STORE_CTX_get_ex_data(const X509_STORE_CTX *ctx, int idx) + * } + */ + public static MemorySegment X509_STORE_CTX_get_ex_data$address() { + return X509_STORE_CTX_get_ex_data.ADDR; + } + + /** + * {@snippet lang = c : * void *X509_STORE_CTX_get_ex_data(const X509_STORE_CTX *ctx, int idx) * } */ public static MemorySegment X509_STORE_CTX_get_ex_data(MemorySegment ctx, int idx) { - var mh$ = X509_STORE_CTX_get_ex_data$MH(); + var mh$ = X509_STORE_CTX_get_ex_data.HANDLE; try { if (TRACE_DOWNCALLS) { traceDowncall("X509_STORE_CTX_get_ex_data", ctx, idx); } return (MemorySegment) mh$.invokeExact(ctx, idx); } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); + throw new AssertionError("should not reach here", ex$); } } - private static MethodHandle X509_STORE_CTX_get_error$MH() { - class Holder { - static final FunctionDescriptor DESC = FunctionDescriptor.of( - openssl_h.C_INT, - openssl_h.C_POINTER - ); - - static final MethodHandle MH = Linker.nativeLinker().downcallHandle( - openssl_h.findOrThrow("X509_STORE_CTX_get_error"), - DESC); - } - return Holder.MH; + private static class X509_STORE_CTX_get_error { + public static final FunctionDescriptor DESC = FunctionDescriptor.of(openssl_h.C_INT, openssl_h.C_POINTER); + + public static final MemorySegment ADDR = openssl_h.findOrThrow("X509_STORE_CTX_get_error"); + + public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); } /** - * {@snippet lang=c : - * int X509_STORE_CTX_get_error(const X509_STORE_CTX *ctx) + * Function descriptor for: + * {@snippet lang = c : * int X509_STORE_CTX_get_error(const X509_STORE_CTX *ctx) + * } + */ + public static FunctionDescriptor X509_STORE_CTX_get_error$descriptor() { + return X509_STORE_CTX_get_error.DESC; + } + + /** + * Downcall method handle for: + * {@snippet lang = c : * int X509_STORE_CTX_get_error(const X509_STORE_CTX *ctx) + * } + */ + public static MethodHandle X509_STORE_CTX_get_error$handle() { + return X509_STORE_CTX_get_error.HANDLE; + } + + /** + * Address for: + * {@snippet lang = c : * int X509_STORE_CTX_get_error(const X509_STORE_CTX *ctx) + * } + */ + public static MemorySegment X509_STORE_CTX_get_error$address() { + return X509_STORE_CTX_get_error.ADDR; + } + + /** + * {@snippet lang = c : * int X509_STORE_CTX_get_error(const X509_STORE_CTX *ctx) * } */ public static int X509_STORE_CTX_get_error(MemorySegment ctx) { - var mh$ = X509_STORE_CTX_get_error$MH(); + var mh$ = X509_STORE_CTX_get_error.HANDLE; try { if (TRACE_DOWNCALLS) { traceDowncall("X509_STORE_CTX_get_error", ctx); } return (int) mh$.invokeExact(ctx); } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); + throw new AssertionError("should not reach here", ex$); } } - private static MethodHandle X509_STORE_CTX_set_error$MH() { - class Holder { - static final FunctionDescriptor DESC = FunctionDescriptor.ofVoid( - openssl_h.C_POINTER, - openssl_h.C_INT - ); - - static final MethodHandle MH = Linker.nativeLinker().downcallHandle( - openssl_h.findOrThrow("X509_STORE_CTX_set_error"), - DESC); - } - return Holder.MH; + private static class X509_STORE_CTX_set_error { + public static final FunctionDescriptor DESC = FunctionDescriptor.ofVoid(openssl_h.C_POINTER, openssl_h.C_INT); + + public static final MemorySegment ADDR = openssl_h.findOrThrow("X509_STORE_CTX_set_error"); + + public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); } /** - * {@snippet lang=c : - * void X509_STORE_CTX_set_error(X509_STORE_CTX *ctx, int s) + * Function descriptor for: + * {@snippet lang = c : * void X509_STORE_CTX_set_error(X509_STORE_CTX *ctx, int s) + * } + */ + public static FunctionDescriptor X509_STORE_CTX_set_error$descriptor() { + return X509_STORE_CTX_set_error.DESC; + } + + /** + * Downcall method handle for: + * {@snippet lang = c : * void X509_STORE_CTX_set_error(X509_STORE_CTX *ctx, int s) + * } + */ + public static MethodHandle X509_STORE_CTX_set_error$handle() { + return X509_STORE_CTX_set_error.HANDLE; + } + + /** + * Address for: + * {@snippet lang = c : * void X509_STORE_CTX_set_error(X509_STORE_CTX *ctx, int s) + * } + */ + public static MemorySegment X509_STORE_CTX_set_error$address() { + return X509_STORE_CTX_set_error.ADDR; + } + + /** + * {@snippet lang = c : * void X509_STORE_CTX_set_error(X509_STORE_CTX *ctx, int s) * } */ public static void X509_STORE_CTX_set_error(MemorySegment ctx, int s) { - var mh$ = X509_STORE_CTX_set_error$MH(); + var mh$ = X509_STORE_CTX_set_error.HANDLE; try { if (TRACE_DOWNCALLS) { traceDowncall("X509_STORE_CTX_set_error", ctx, s); } mh$.invokeExact(ctx, s); } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); + throw new AssertionError("should not reach here", ex$); } } - private static MethodHandle X509_STORE_CTX_get_error_depth$MH() { - class Holder { - static final FunctionDescriptor DESC = FunctionDescriptor.of( - openssl_h.C_INT, - openssl_h.C_POINTER - ); - - static final MethodHandle MH = Linker.nativeLinker().downcallHandle( - openssl_h.findOrThrow("X509_STORE_CTX_get_error_depth"), - DESC); - } - return Holder.MH; + private static class X509_STORE_CTX_get_error_depth { + public static final FunctionDescriptor DESC = FunctionDescriptor.of(openssl_h.C_INT, openssl_h.C_POINTER); + + public static final MemorySegment ADDR = openssl_h.findOrThrow("X509_STORE_CTX_get_error_depth"); + + public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); } /** - * {@snippet lang=c : - * int X509_STORE_CTX_get_error_depth(const X509_STORE_CTX *ctx) + * Function descriptor for: + * {@snippet lang = c : * int X509_STORE_CTX_get_error_depth(const X509_STORE_CTX *ctx) + * } + */ + public static FunctionDescriptor X509_STORE_CTX_get_error_depth$descriptor() { + return X509_STORE_CTX_get_error_depth.DESC; + } + + /** + * Downcall method handle for: + * {@snippet lang = c : * int X509_STORE_CTX_get_error_depth(const X509_STORE_CTX *ctx) + * } + */ + public static MethodHandle X509_STORE_CTX_get_error_depth$handle() { + return X509_STORE_CTX_get_error_depth.HANDLE; + } + + /** + * Address for: + * {@snippet lang = c : * int X509_STORE_CTX_get_error_depth(const X509_STORE_CTX *ctx) + * } + */ + public static MemorySegment X509_STORE_CTX_get_error_depth$address() { + return X509_STORE_CTX_get_error_depth.ADDR; + } + + /** + * {@snippet lang = c : * int X509_STORE_CTX_get_error_depth(const X509_STORE_CTX *ctx) * } */ public static int X509_STORE_CTX_get_error_depth(MemorySegment ctx) { - var mh$ = X509_STORE_CTX_get_error_depth$MH(); + var mh$ = X509_STORE_CTX_get_error_depth.HANDLE; try { if (TRACE_DOWNCALLS) { traceDowncall("X509_STORE_CTX_get_error_depth", ctx); } return (int) mh$.invokeExact(ctx); } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); + throw new AssertionError("should not reach here", ex$); } } - private static MethodHandle X509_STORE_CTX_get_current_cert$MH() { - class Holder { - static final FunctionDescriptor DESC = FunctionDescriptor.of( - openssl_h.C_POINTER, - openssl_h.C_POINTER - ); - - static final MethodHandle MH = Linker.nativeLinker().downcallHandle( - openssl_h.findOrThrow("X509_STORE_CTX_get_current_cert"), - DESC); - } - return Holder.MH; + private static class X509_STORE_CTX_get_current_cert { + public static final FunctionDescriptor DESC = FunctionDescriptor.of(openssl_h.C_POINTER, openssl_h.C_POINTER); + + public static final MemorySegment ADDR = openssl_h.findOrThrow("X509_STORE_CTX_get_current_cert"); + + public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); } /** - * {@snippet lang=c : - * X509 *X509_STORE_CTX_get_current_cert(const X509_STORE_CTX *ctx) + * Function descriptor for: + * {@snippet lang = c : * X509 *X509_STORE_CTX_get_current_cert(const X509_STORE_CTX *ctx) + * } + */ + public static FunctionDescriptor X509_STORE_CTX_get_current_cert$descriptor() { + return X509_STORE_CTX_get_current_cert.DESC; + } + + /** + * Downcall method handle for: + * {@snippet lang = c : * X509 *X509_STORE_CTX_get_current_cert(const X509_STORE_CTX *ctx) + * } + */ + public static MethodHandle X509_STORE_CTX_get_current_cert$handle() { + return X509_STORE_CTX_get_current_cert.HANDLE; + } + + /** + * Address for: + * {@snippet lang = c : * X509 *X509_STORE_CTX_get_current_cert(const X509_STORE_CTX *ctx) + * } + */ + public static MemorySegment X509_STORE_CTX_get_current_cert$address() { + return X509_STORE_CTX_get_current_cert.ADDR; + } + + /** + * {@snippet lang = c : * X509 *X509_STORE_CTX_get_current_cert(const X509_STORE_CTX *ctx) * } */ public static MemorySegment X509_STORE_CTX_get_current_cert(MemorySegment ctx) { - var mh$ = X509_STORE_CTX_get_current_cert$MH(); + var mh$ = X509_STORE_CTX_get_current_cert.HANDLE; try { if (TRACE_DOWNCALLS) { traceDowncall("X509_STORE_CTX_get_current_cert", ctx); } return (MemorySegment) mh$.invokeExact(ctx); } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); + throw new AssertionError("should not reach here", ex$); } } - private static MethodHandle X509_STORE_CTX_get0_current_issuer$MH() { - class Holder { - static final FunctionDescriptor DESC = FunctionDescriptor.of( - openssl_h.C_POINTER, - openssl_h.C_POINTER - ); - - static final MethodHandle MH = Linker.nativeLinker().downcallHandle( - openssl_h.findOrThrow("X509_STORE_CTX_get0_current_issuer"), - DESC); - } - return Holder.MH; + private static class X509_STORE_CTX_get1_issuer { + public static final FunctionDescriptor DESC = FunctionDescriptor.of(openssl_h.C_INT, openssl_h.C_POINTER, openssl_h.C_POINTER, openssl_h.C_POINTER); + + public static final MemorySegment ADDR = openssl_h.findOrThrow("X509_STORE_CTX_get1_issuer"); + + public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); } /** - * {@snippet lang=c : - * X509 *X509_STORE_CTX_get0_current_issuer(const X509_STORE_CTX *ctx) + * Function descriptor for: + * {@snippet lang = c : * int X509_STORE_CTX_get1_issuer(X509 **issuer, X509_STORE_CTX *ctx, X509 *x) + * } + */ + public static FunctionDescriptor X509_STORE_CTX_get1_issuer$descriptor() { + return X509_STORE_CTX_get1_issuer.DESC; + } + + /** + * Downcall method handle for: + * {@snippet lang = c : * int X509_STORE_CTX_get1_issuer(X509 **issuer, X509_STORE_CTX *ctx, X509 *x) + * } + */ + public static MethodHandle X509_STORE_CTX_get1_issuer$handle() { + return X509_STORE_CTX_get1_issuer.HANDLE; + } + + /** + * Address for: + * {@snippet lang = c : * int X509_STORE_CTX_get1_issuer(X509 **issuer, X509_STORE_CTX *ctx, X509 *x) + * } + */ + public static MemorySegment X509_STORE_CTX_get1_issuer$address() { + return X509_STORE_CTX_get1_issuer.ADDR; + } + + /** + * {@snippet lang = c : * int X509_STORE_CTX_get1_issuer(X509 **issuer, X509_STORE_CTX *ctx, X509 *x) * } */ - public static MemorySegment X509_STORE_CTX_get0_current_issuer(MemorySegment ctx) { - var mh$ = X509_STORE_CTX_get0_current_issuer$MH(); + public static int X509_STORE_CTX_get1_issuer(MemorySegment issuer, MemorySegment ctx, MemorySegment x) { + var mh$ = X509_STORE_CTX_get1_issuer.HANDLE; try { if (TRACE_DOWNCALLS) { - traceDowncall("X509_STORE_CTX_get0_current_issuer", ctx); + traceDowncall("X509_STORE_CTX_get1_issuer", issuer, ctx, x); } - return (MemorySegment) mh$.invokeExact(ctx); + return (int) mh$.invokeExact(issuer, ctx, x); } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); + throw new AssertionError("should not reach here", ex$); } } - private static MethodHandle d2i_X509_bio$MH() { - class Holder { - static final FunctionDescriptor DESC = FunctionDescriptor.of( - openssl_h.C_POINTER, - openssl_h.C_POINTER, - openssl_h.C_POINTER - ); - - static final MethodHandle MH = Linker.nativeLinker().downcallHandle( - openssl_h.findOrThrow("d2i_X509_bio"), - DESC); - } - return Holder.MH; + private static class d2i_X509_bio { + public static final FunctionDescriptor DESC = + FunctionDescriptor.of(openssl_h.C_POINTER, openssl_h.C_POINTER, openssl_h.C_POINTER); + + public static final MemorySegment ADDR = openssl_h.findOrThrow("d2i_X509_bio"); + + public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); } /** - * {@snippet lang=c : - * X509 *d2i_X509_bio(BIO *bp, X509 **x509) + * Function descriptor for: + * {@snippet lang = c : * X509 *d2i_X509_bio(BIO *bp, X509 **x509) + * } + */ + public static FunctionDescriptor d2i_X509_bio$descriptor() { + return d2i_X509_bio.DESC; + } + + /** + * Downcall method handle for: + * {@snippet lang = c : * X509 *d2i_X509_bio(BIO *bp, X509 **x509) + * } + */ + public static MethodHandle d2i_X509_bio$handle() { + return d2i_X509_bio.HANDLE; + } + + /** + * Address for: + * {@snippet lang = c : * X509 *d2i_X509_bio(BIO *bp, X509 **x509) + * } + */ + public static MemorySegment d2i_X509_bio$address() { + return d2i_X509_bio.ADDR; + } + + /** + * {@snippet lang = c : * X509 *d2i_X509_bio(BIO *bp, X509 **x509) * } */ public static MemorySegment d2i_X509_bio(MemorySegment bp, MemorySegment x509) { - var mh$ = d2i_X509_bio$MH(); + var mh$ = d2i_X509_bio.HANDLE; try { if (TRACE_DOWNCALLS) { traceDowncall("d2i_X509_bio", bp, x509); } return (MemorySegment) mh$.invokeExact(bp, x509); } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); + throw new AssertionError("should not reach here", ex$); } } - private static MethodHandle X509_free$MH() { - class Holder { - static final FunctionDescriptor DESC = FunctionDescriptor.ofVoid( - openssl_h.C_POINTER - ); - - static final MethodHandle MH = Linker.nativeLinker().downcallHandle( - openssl_h.findOrThrow("X509_free"), - DESC); - } - return Holder.MH; + private static class X509_free { + public static final FunctionDescriptor DESC = FunctionDescriptor.ofVoid(openssl_h.C_POINTER); + + public static final MemorySegment ADDR = openssl_h.findOrThrow("X509_free"); + + public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); } /** - * {@snippet lang=c : - * extern void X509_free(X509 *a) + * Function descriptor for: + * {@snippet lang = c : * extern void X509_free(X509 *a) + * } + */ + public static FunctionDescriptor X509_free$descriptor() { + return X509_free.DESC; + } + + /** + * Downcall method handle for: + * {@snippet lang = c : * extern void X509_free(X509 *a) + * } + */ + public static MethodHandle X509_free$handle() { + return X509_free.HANDLE; + } + + /** + * Address for: + * {@snippet lang = c : * extern void X509_free(X509 *a) + * } + */ + public static MemorySegment X509_free$address() { + return X509_free.ADDR; + } + + /** + * {@snippet lang = c : * extern void X509_free(X509 *a) * } */ public static void X509_free(MemorySegment a) { - var mh$ = X509_free$MH(); + var mh$ = X509_free.HANDLE; try { if (TRACE_DOWNCALLS) { traceDowncall("X509_free", a); } mh$.invokeExact(a); } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); + throw new AssertionError("should not reach here", ex$); } } - private static MethodHandle d2i_X509$MH() { - class Holder { - static final FunctionDescriptor DESC = FunctionDescriptor.of( - openssl_h.C_POINTER, - openssl_h.C_POINTER, - openssl_h.C_POINTER, - openssl_h.C_LONG - ); - - static final MethodHandle MH = Linker.nativeLinker().downcallHandle( - openssl_h.findOrThrow("d2i_X509"), - DESC); - } - return Holder.MH; + private static class d2i_X509 { + public static final FunctionDescriptor DESC = + FunctionDescriptor.of(openssl_h.C_POINTER, openssl_h.C_POINTER, openssl_h.C_POINTER, openssl_h.C_LONG); + + public static final MemorySegment ADDR = openssl_h.findOrThrow("d2i_X509"); + + public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); } /** - * {@snippet lang=c : - * extern X509 *d2i_X509(X509 **a, const unsigned char **in, long len) + * Function descriptor for: + * {@snippet lang = c : * extern X509 *d2i_X509(X509 **a, const unsigned char **in, long len) + * } + */ + public static FunctionDescriptor d2i_X509$descriptor() { + return d2i_X509.DESC; + } + + /** + * Downcall method handle for: + * {@snippet lang = c : * extern X509 *d2i_X509(X509 **a, const unsigned char **in, long len) + * } + */ + public static MethodHandle d2i_X509$handle() { + return d2i_X509.HANDLE; + } + + /** + * Address for: + * {@snippet lang = c : * extern X509 *d2i_X509(X509 **a, const unsigned char **in, long len) + * } + */ + public static MemorySegment d2i_X509$address() { + return d2i_X509.ADDR; + } + + /** + * {@snippet lang = c : * extern X509 *d2i_X509(X509 **a, const unsigned char **in, long len) * } */ public static MemorySegment d2i_X509(MemorySegment a, MemorySegment in, long len) { - var mh$ = d2i_X509$MH(); + var mh$ = d2i_X509.HANDLE; try { if (TRACE_DOWNCALLS) { traceDowncall("d2i_X509", a, in, len); } return (MemorySegment) mh$.invokeExact(a, in, len); } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); + throw new AssertionError("should not reach here", ex$); } } - private static MethodHandle i2d_X509$MH() { - class Holder { - static final FunctionDescriptor DESC = FunctionDescriptor.of( - openssl_h.C_INT, - openssl_h.C_POINTER, - openssl_h.C_POINTER - ); - - static final MethodHandle MH = Linker.nativeLinker().downcallHandle( - openssl_h.findOrThrow("i2d_X509"), - DESC); - } - return Holder.MH; + private static class i2d_X509 { + public static final FunctionDescriptor DESC = + FunctionDescriptor.of(openssl_h.C_INT, openssl_h.C_POINTER, openssl_h.C_POINTER); + + public static final MemorySegment ADDR = openssl_h.findOrThrow("i2d_X509"); + + public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); } /** - * {@snippet lang=c : - * extern int i2d_X509(const X509 *a, unsigned char **out) + * Function descriptor for: + * {@snippet lang = c : * extern int i2d_X509(const X509 *a, unsigned char **out) + * } + */ + public static FunctionDescriptor i2d_X509$descriptor() { + return i2d_X509.DESC; + } + + /** + * Downcall method handle for: + * {@snippet lang = c : * extern int i2d_X509(const X509 *a, unsigned char **out) + * } + */ + public static MethodHandle i2d_X509$handle() { + return i2d_X509.HANDLE; + } + + /** + * Address for: + * {@snippet lang = c : * extern int i2d_X509(const X509 *a, unsigned char **out) + * } + */ + public static MemorySegment i2d_X509$address() { + return i2d_X509.ADDR; + } + + /** + * {@snippet lang = c : * extern int i2d_X509(const X509 *a, unsigned char **out) * } */ public static int i2d_X509(MemorySegment a, MemorySegment out) { - var mh$ = i2d_X509$MH(); + var mh$ = i2d_X509.HANDLE; try { if (TRACE_DOWNCALLS) { traceDowncall("i2d_X509", a, out); } return (int) mh$.invokeExact(a, out); } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); + throw new AssertionError("should not reach here", ex$); } } - private static MethodHandle X509_get_ext_by_NID$MH() { - class Holder { - static final FunctionDescriptor DESC = FunctionDescriptor.of( - openssl_h.C_INT, - openssl_h.C_POINTER, - openssl_h.C_INT, - openssl_h.C_INT - ); - - static final MethodHandle MH = Linker.nativeLinker().downcallHandle( - openssl_h.findOrThrow("X509_get_ext_by_NID"), - DESC); - } - return Holder.MH; + private static class X509_get_ext_by_NID { + public static final FunctionDescriptor DESC = + FunctionDescriptor.of(openssl_h.C_INT, openssl_h.C_POINTER, openssl_h.C_INT, openssl_h.C_INT); + + public static final MemorySegment ADDR = openssl_h.findOrThrow("X509_get_ext_by_NID"); + + public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); } /** - * {@snippet lang=c : - * int X509_get_ext_by_NID(const X509 *x, int nid, int lastpos) + * Function descriptor for: + * {@snippet lang = c : * int X509_get_ext_by_NID(const X509 *x, int nid, int lastpos) + * } + */ + public static FunctionDescriptor X509_get_ext_by_NID$descriptor() { + return X509_get_ext_by_NID.DESC; + } + + /** + * Downcall method handle for: + * {@snippet lang = c : * int X509_get_ext_by_NID(const X509 *x, int nid, int lastpos) + * } + */ + public static MethodHandle X509_get_ext_by_NID$handle() { + return X509_get_ext_by_NID.HANDLE; + } + + /** + * Address for: + * {@snippet lang = c : * int X509_get_ext_by_NID(const X509 *x, int nid, int lastpos) + * } + */ + public static MemorySegment X509_get_ext_by_NID$address() { + return X509_get_ext_by_NID.ADDR; + } + + /** + * {@snippet lang = c : * int X509_get_ext_by_NID(const X509 *x, int nid, int lastpos) * } */ public static int X509_get_ext_by_NID(MemorySegment x, int nid, int lastpos) { - var mh$ = X509_get_ext_by_NID$MH(); + var mh$ = X509_get_ext_by_NID.HANDLE; try { if (TRACE_DOWNCALLS) { traceDowncall("X509_get_ext_by_NID", x, nid, lastpos); } return (int) mh$.invokeExact(x, nid, lastpos); } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); + throw new AssertionError("should not reach here", ex$); } } - private static MethodHandle X509_get_ext$MH() { - class Holder { - static final FunctionDescriptor DESC = FunctionDescriptor.of( - openssl_h.C_POINTER, - openssl_h.C_POINTER, - openssl_h.C_INT - ); - - static final MethodHandle MH = Linker.nativeLinker().downcallHandle( - openssl_h.findOrThrow("X509_get_ext"), - DESC); - } - return Holder.MH; + private static class X509_get_ext { + public static final FunctionDescriptor DESC = + FunctionDescriptor.of(openssl_h.C_POINTER, openssl_h.C_POINTER, openssl_h.C_INT); + + public static final MemorySegment ADDR = openssl_h.findOrThrow("X509_get_ext"); + + public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); } /** - * {@snippet lang=c : - * X509_EXTENSION *X509_get_ext(const X509 *x, int loc) + * Function descriptor for: + * {@snippet lang = c : * X509_EXTENSION *X509_get_ext(const X509 *x, int loc) + * } + */ + public static FunctionDescriptor X509_get_ext$descriptor() { + return X509_get_ext.DESC; + } + + /** + * Downcall method handle for: + * {@snippet lang = c : * X509_EXTENSION *X509_get_ext(const X509 *x, int loc) + * } + */ + public static MethodHandle X509_get_ext$handle() { + return X509_get_ext.HANDLE; + } + + /** + * Address for: + * {@snippet lang = c : * X509_EXTENSION *X509_get_ext(const X509 *x, int loc) + * } + */ + public static MemorySegment X509_get_ext$address() { + return X509_get_ext.ADDR; + } + + /** + * {@snippet lang = c : * X509_EXTENSION *X509_get_ext(const X509 *x, int loc) * } */ public static MemorySegment X509_get_ext(MemorySegment x, int loc) { - var mh$ = X509_get_ext$MH(); + var mh$ = X509_get_ext.HANDLE; try { if (TRACE_DOWNCALLS) { traceDowncall("X509_get_ext", x, loc); } return (MemorySegment) mh$.invokeExact(x, loc); } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); + throw new AssertionError("should not reach here", ex$); } } - private static MethodHandle X509_EXTENSION_get_data$MH() { - class Holder { - static final FunctionDescriptor DESC = FunctionDescriptor.of( - openssl_h.C_POINTER, - openssl_h.C_POINTER - ); - - static final MethodHandle MH = Linker.nativeLinker().downcallHandle( - openssl_h.findOrThrow("X509_EXTENSION_get_data"), - DESC); - } - return Holder.MH; + private static class X509_EXTENSION_get_data { + public static final FunctionDescriptor DESC = FunctionDescriptor.of(openssl_h.C_POINTER, openssl_h.C_POINTER); + + public static final MemorySegment ADDR = openssl_h.findOrThrow("X509_EXTENSION_get_data"); + + public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); } /** - * {@snippet lang=c : - * ASN1_OCTET_STRING *X509_EXTENSION_get_data(X509_EXTENSION *ne) + * Function descriptor for: + * {@snippet lang = c : * ASN1_OCTET_STRING *X509_EXTENSION_get_data(X509_EXTENSION *ne) + * } + */ + public static FunctionDescriptor X509_EXTENSION_get_data$descriptor() { + return X509_EXTENSION_get_data.DESC; + } + + /** + * Downcall method handle for: + * {@snippet lang = c : * ASN1_OCTET_STRING *X509_EXTENSION_get_data(X509_EXTENSION *ne) + * } + */ + public static MethodHandle X509_EXTENSION_get_data$handle() { + return X509_EXTENSION_get_data.HANDLE; + } + + /** + * Address for: + * {@snippet lang = c : * ASN1_OCTET_STRING *X509_EXTENSION_get_data(X509_EXTENSION *ne) + * } + */ + public static MemorySegment X509_EXTENSION_get_data$address() { + return X509_EXTENSION_get_data.ADDR; + } + + /** + * {@snippet lang = c : * ASN1_OCTET_STRING *X509_EXTENSION_get_data(X509_EXTENSION *ne) * } */ public static MemorySegment X509_EXTENSION_get_data(MemorySegment ne) { - var mh$ = X509_EXTENSION_get_data$MH(); + var mh$ = X509_EXTENSION_get_data.HANDLE; try { if (TRACE_DOWNCALLS) { traceDowncall("X509_EXTENSION_get_data", ne); } return (MemorySegment) mh$.invokeExact(ne); } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); + throw new AssertionError("should not reach here", ex$); } } - private static MethodHandle PEM_ASN1_read_bio$MH() { - class Holder { - static final FunctionDescriptor DESC = FunctionDescriptor.of( - openssl_h.C_POINTER, - openssl_h.C_POINTER, - openssl_h.C_POINTER, - openssl_h.C_POINTER, - openssl_h.C_POINTER, - openssl_h.C_POINTER, - openssl_h.C_POINTER - ); - - static final MethodHandle MH = Linker.nativeLinker().downcallHandle( - openssl_h.findOrThrow("PEM_ASN1_read_bio"), - DESC); - } - return Holder.MH; + private static class PEM_ASN1_read_bio { + public static final FunctionDescriptor DESC = + FunctionDescriptor.of(openssl_h.C_POINTER, openssl_h.C_POINTER, openssl_h.C_POINTER, + openssl_h.C_POINTER, openssl_h.C_POINTER, openssl_h.C_POINTER, openssl_h.C_POINTER); + + public static final MemorySegment ADDR = openssl_h.findOrThrow("PEM_ASN1_read_bio"); + + public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); } /** - * {@snippet lang=c : - * void *PEM_ASN1_read_bio(d2i_of_void *d2i, const char *name, BIO *bp, void **x, pem_password_cb *cb, void *u) + * Function descriptor for: + * {@snippet lang = c + * : * void *PEM_ASN1_read_bio(d2i_of_void *d2i, const char *name, BIO *bp, void **x, pem_password_cb *cb, void *u) + * } + */ + public static FunctionDescriptor PEM_ASN1_read_bio$descriptor() { + return PEM_ASN1_read_bio.DESC; + } + + /** + * Downcall method handle for: + * {@snippet lang = c + * : * void *PEM_ASN1_read_bio(d2i_of_void *d2i, const char *name, BIO *bp, void **x, pem_password_cb *cb, void *u) + * } + */ + public static MethodHandle PEM_ASN1_read_bio$handle() { + return PEM_ASN1_read_bio.HANDLE; + } + + /** + * Address for: + * {@snippet lang = c + * : * void *PEM_ASN1_read_bio(d2i_of_void *d2i, const char *name, BIO *bp, void **x, pem_password_cb *cb, void *u) * } */ - public static MemorySegment PEM_ASN1_read_bio(MemorySegment d2i, MemorySegment name, MemorySegment bp, MemorySegment x, MemorySegment cb, MemorySegment u) { - var mh$ = PEM_ASN1_read_bio$MH(); + public static MemorySegment PEM_ASN1_read_bio$address() { + return PEM_ASN1_read_bio.ADDR; + } + + /** + * {@snippet lang = c + * : * void *PEM_ASN1_read_bio(d2i_of_void *d2i, const char *name, BIO *bp, void **x, pem_password_cb *cb, void *u) + * } + */ + public static MemorySegment PEM_ASN1_read_bio(MemorySegment d2i, MemorySegment name, MemorySegment bp, + MemorySegment x, MemorySegment cb, MemorySegment u) { + var mh$ = PEM_ASN1_read_bio.HANDLE; try { if (TRACE_DOWNCALLS) { traceDowncall("PEM_ASN1_read_bio", d2i, name, bp, x, cb, u); } return (MemorySegment) mh$.invokeExact(d2i, name, bp, x, cb, u); } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); + throw new AssertionError("should not reach here", ex$); } } - private static MethodHandle PEM_read_bio_X509_AUX$MH() { - class Holder { - static final FunctionDescriptor DESC = FunctionDescriptor.of( - openssl_h.C_POINTER, - openssl_h.C_POINTER, - openssl_h.C_POINTER, - openssl_h.C_POINTER, - openssl_h.C_POINTER - ); - - static final MethodHandle MH = Linker.nativeLinker().downcallHandle( - openssl_h.findOrThrow("PEM_read_bio_X509_AUX"), - DESC); - } - return Holder.MH; + private static class PEM_read_bio_X509_AUX { + public static final FunctionDescriptor DESC = FunctionDescriptor.of(openssl_h.C_POINTER, openssl_h.C_POINTER, + openssl_h.C_POINTER, openssl_h.C_POINTER, openssl_h.C_POINTER); + + public static final MemorySegment ADDR = openssl_h.findOrThrow("PEM_read_bio_X509_AUX"); + + public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); } /** - * {@snippet lang=c : - * extern X509 *PEM_read_bio_X509_AUX(BIO *out, X509 **x, pem_password_cb *cb, void *u) + * Function descriptor for: + * {@snippet lang = c : * extern X509 *PEM_read_bio_X509_AUX(BIO *out, X509 **x, pem_password_cb *cb, void *u) + * } + */ + public static FunctionDescriptor PEM_read_bio_X509_AUX$descriptor() { + return PEM_read_bio_X509_AUX.DESC; + } + + /** + * Downcall method handle for: + * {@snippet lang = c : * extern X509 *PEM_read_bio_X509_AUX(BIO *out, X509 **x, pem_password_cb *cb, void *u) * } */ - public static MemorySegment PEM_read_bio_X509_AUX(MemorySegment out, MemorySegment x, MemorySegment cb, MemorySegment u) { - var mh$ = PEM_read_bio_X509_AUX$MH(); + public static MethodHandle PEM_read_bio_X509_AUX$handle() { + return PEM_read_bio_X509_AUX.HANDLE; + } + + /** + * Address for: + * {@snippet lang = c : * extern X509 *PEM_read_bio_X509_AUX(BIO *out, X509 **x, pem_password_cb *cb, void *u) + * } + */ + public static MemorySegment PEM_read_bio_X509_AUX$address() { + return PEM_read_bio_X509_AUX.ADDR; + } + + /** + * {@snippet lang = c : * extern X509 *PEM_read_bio_X509_AUX(BIO *out, X509 **x, pem_password_cb *cb, void *u) + * } + */ + public static MemorySegment PEM_read_bio_X509_AUX(MemorySegment out, MemorySegment x, MemorySegment cb, + MemorySegment u) { + var mh$ = PEM_read_bio_X509_AUX.HANDLE; try { if (TRACE_DOWNCALLS) { traceDowncall("PEM_read_bio_X509_AUX", out, x, cb, u); } return (MemorySegment) mh$.invokeExact(out, x, cb, u); } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); + throw new AssertionError("should not reach here", ex$); } } - private static MethodHandle PEM_read_bio_ECPKParameters$MH() { - class Holder { - static final FunctionDescriptor DESC = FunctionDescriptor.of( - openssl_h.C_POINTER, - openssl_h.C_POINTER, - openssl_h.C_POINTER, - openssl_h.C_POINTER, - openssl_h.C_POINTER - ); - - static final MethodHandle MH = Linker.nativeLinker().downcallHandle( - openssl_h.findOrThrow("PEM_read_bio_ECPKParameters"), - DESC); - } - return Holder.MH; + private static class PEM_read_bio_ECPKParameters { + public static final FunctionDescriptor DESC = FunctionDescriptor.of(openssl_h.C_POINTER, openssl_h.C_POINTER, + openssl_h.C_POINTER, openssl_h.C_POINTER, openssl_h.C_POINTER); + + public static final MemorySegment ADDR = openssl_h.findOrThrow("PEM_read_bio_ECPKParameters"); + + public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); } /** - * {@snippet lang=c : - * EC_GROUP *PEM_read_bio_ECPKParameters(BIO *out, EC_GROUP **x, pem_password_cb *cb, void *u) + * Function descriptor for: + * {@snippet lang = c + * : * EC_GROUP *PEM_read_bio_ECPKParameters(BIO *out, EC_GROUP **x, pem_password_cb *cb, void *u) * } */ - public static MemorySegment PEM_read_bio_ECPKParameters(MemorySegment out, MemorySegment x, MemorySegment cb, MemorySegment u) { - var mh$ = PEM_read_bio_ECPKParameters$MH(); + public static FunctionDescriptor PEM_read_bio_ECPKParameters$descriptor() { + return PEM_read_bio_ECPKParameters.DESC; + } + + /** + * Downcall method handle for: + * {@snippet lang = c + * : * EC_GROUP *PEM_read_bio_ECPKParameters(BIO *out, EC_GROUP **x, pem_password_cb *cb, void *u) + * } + */ + public static MethodHandle PEM_read_bio_ECPKParameters$handle() { + return PEM_read_bio_ECPKParameters.HANDLE; + } + + /** + * Address for: + * {@snippet lang = c + * : * EC_GROUP *PEM_read_bio_ECPKParameters(BIO *out, EC_GROUP **x, pem_password_cb *cb, void *u) + * } + */ + public static MemorySegment PEM_read_bio_ECPKParameters$address() { + return PEM_read_bio_ECPKParameters.ADDR; + } + + /** + * {@snippet lang = c + * : * EC_GROUP *PEM_read_bio_ECPKParameters(BIO *out, EC_GROUP **x, pem_password_cb *cb, void *u) + * } + */ + public static MemorySegment PEM_read_bio_ECPKParameters(MemorySegment out, MemorySegment x, MemorySegment cb, + MemorySegment u) { + var mh$ = PEM_read_bio_ECPKParameters.HANDLE; try { if (TRACE_DOWNCALLS) { traceDowncall("PEM_read_bio_ECPKParameters", out, x, cb, u); } return (MemorySegment) mh$.invokeExact(out, x, cb, u); } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); + throw new AssertionError("should not reach here", ex$); } } - private static MethodHandle PEM_read_bio_DHparams$MH() { - class Holder { - static final FunctionDescriptor DESC = FunctionDescriptor.of( - openssl_h.C_POINTER, - openssl_h.C_POINTER, - openssl_h.C_POINTER, - openssl_h.C_POINTER, - openssl_h.C_POINTER - ); - - static final MethodHandle MH = Linker.nativeLinker().downcallHandle( - openssl_h.findOrThrow("PEM_read_bio_DHparams"), - DESC); - } - return Holder.MH; + private static class PEM_read_bio_DHparams { + public static final FunctionDescriptor DESC = FunctionDescriptor.of(openssl_h.C_POINTER, openssl_h.C_POINTER, + openssl_h.C_POINTER, openssl_h.C_POINTER, openssl_h.C_POINTER); + + public static final MemorySegment ADDR = openssl_h.findOrThrow("PEM_read_bio_DHparams"); + + public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); } /** - * {@snippet lang=c : - * DH *PEM_read_bio_DHparams(BIO *out, DH **x, pem_password_cb *cb, void *u) + * Function descriptor for: + * {@snippet lang = c : * DH *PEM_read_bio_DHparams(BIO *out, DH **x, pem_password_cb *cb, void *u) + * } + */ + public static FunctionDescriptor PEM_read_bio_DHparams$descriptor() { + return PEM_read_bio_DHparams.DESC; + } + + /** + * Downcall method handle for: + * {@snippet lang = c : * DH *PEM_read_bio_DHparams(BIO *out, DH **x, pem_password_cb *cb, void *u) + * } + */ + public static MethodHandle PEM_read_bio_DHparams$handle() { + return PEM_read_bio_DHparams.HANDLE; + } + + /** + * Address for: + * {@snippet lang = c : * DH *PEM_read_bio_DHparams(BIO *out, DH **x, pem_password_cb *cb, void *u) * } */ - public static MemorySegment PEM_read_bio_DHparams(MemorySegment out, MemorySegment x, MemorySegment cb, MemorySegment u) { - var mh$ = PEM_read_bio_DHparams$MH(); + public static MemorySegment PEM_read_bio_DHparams$address() { + return PEM_read_bio_DHparams.ADDR; + } + + /** + * {@snippet lang = c : * DH *PEM_read_bio_DHparams(BIO *out, DH **x, pem_password_cb *cb, void *u) + * } + */ + public static MemorySegment PEM_read_bio_DHparams(MemorySegment out, MemorySegment x, MemorySegment cb, + MemorySegment u) { + var mh$ = PEM_read_bio_DHparams.HANDLE; try { if (TRACE_DOWNCALLS) { traceDowncall("PEM_read_bio_DHparams", out, x, cb, u); } return (MemorySegment) mh$.invokeExact(out, x, cb, u); } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); + throw new AssertionError("should not reach here", ex$); } } - private static MethodHandle PEM_read_bio_PrivateKey$MH() { - class Holder { - static final FunctionDescriptor DESC = FunctionDescriptor.of( - openssl_h.C_POINTER, - openssl_h.C_POINTER, - openssl_h.C_POINTER, - openssl_h.C_POINTER, - openssl_h.C_POINTER - ); - - static final MethodHandle MH = Linker.nativeLinker().downcallHandle( - openssl_h.findOrThrow("PEM_read_bio_PrivateKey"), - DESC); - } - return Holder.MH; + private static class PEM_read_bio_PrivateKey { + public static final FunctionDescriptor DESC = FunctionDescriptor.of(openssl_h.C_POINTER, openssl_h.C_POINTER, + openssl_h.C_POINTER, openssl_h.C_POINTER, openssl_h.C_POINTER); + + public static final MemorySegment ADDR = openssl_h.findOrThrow("PEM_read_bio_PrivateKey"); + + public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); } /** - * {@snippet lang=c : - * extern EVP_PKEY *PEM_read_bio_PrivateKey(BIO *out, EVP_PKEY **x, pem_password_cb *cb, void *u) + * Function descriptor for: + * {@snippet lang = c + * : * extern EVP_PKEY *PEM_read_bio_PrivateKey(BIO *out, EVP_PKEY **x, pem_password_cb *cb, void *u) + * } + */ + public static FunctionDescriptor PEM_read_bio_PrivateKey$descriptor() { + return PEM_read_bio_PrivateKey.DESC; + } + + /** + * Downcall method handle for: + * {@snippet lang = c + * : * extern EVP_PKEY *PEM_read_bio_PrivateKey(BIO *out, EVP_PKEY **x, pem_password_cb *cb, void *u) * } */ - public static MemorySegment PEM_read_bio_PrivateKey(MemorySegment out, MemorySegment x, MemorySegment cb, MemorySegment u) { - var mh$ = PEM_read_bio_PrivateKey$MH(); + public static MethodHandle PEM_read_bio_PrivateKey$handle() { + return PEM_read_bio_PrivateKey.HANDLE; + } + + /** + * Address for: + * {@snippet lang = c + * : * extern EVP_PKEY *PEM_read_bio_PrivateKey(BIO *out, EVP_PKEY **x, pem_password_cb *cb, void *u) + * } + */ + public static MemorySegment PEM_read_bio_PrivateKey$address() { + return PEM_read_bio_PrivateKey.ADDR; + } + + /** + * {@snippet lang = c + * : * extern EVP_PKEY *PEM_read_bio_PrivateKey(BIO *out, EVP_PKEY **x, pem_password_cb *cb, void *u) + * } + */ + public static MemorySegment PEM_read_bio_PrivateKey(MemorySegment out, MemorySegment x, MemorySegment cb, + MemorySegment u) { + var mh$ = PEM_read_bio_PrivateKey.HANDLE; try { if (TRACE_DOWNCALLS) { traceDowncall("PEM_read_bio_PrivateKey", out, x, cb, u); } return (MemorySegment) mh$.invokeExact(out, x, cb, u); } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); + throw new AssertionError("should not reach here", ex$); } } - private static MethodHandle PEM_read_bio_Parameters$MH() { - class Holder { - static final FunctionDescriptor DESC = FunctionDescriptor.of( - openssl_h.C_POINTER, - openssl_h.C_POINTER, - openssl_h.C_POINTER - ); - - static final MethodHandle MH = Linker.nativeLinker().downcallHandle( - openssl_h.findOrThrow("PEM_read_bio_Parameters"), - DESC); - } - return Holder.MH; + private static class PEM_read_bio_Parameters { + public static final FunctionDescriptor DESC = + FunctionDescriptor.of(openssl_h.C_POINTER, openssl_h.C_POINTER, openssl_h.C_POINTER); + + public static final MemorySegment ADDR = openssl_h.findOrThrow("PEM_read_bio_Parameters"); + + public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); } /** - * {@snippet lang=c : - * EVP_PKEY *PEM_read_bio_Parameters(BIO *bp, EVP_PKEY **x) + * Function descriptor for: + * {@snippet lang = c : * EVP_PKEY *PEM_read_bio_Parameters(BIO *bp, EVP_PKEY **x) + * } + */ + public static FunctionDescriptor PEM_read_bio_Parameters$descriptor() { + return PEM_read_bio_Parameters.DESC; + } + + /** + * Downcall method handle for: + * {@snippet lang = c : * EVP_PKEY *PEM_read_bio_Parameters(BIO *bp, EVP_PKEY **x) + * } + */ + public static MethodHandle PEM_read_bio_Parameters$handle() { + return PEM_read_bio_Parameters.HANDLE; + } + + /** + * Address for: + * {@snippet lang = c : * EVP_PKEY *PEM_read_bio_Parameters(BIO *bp, EVP_PKEY **x) + * } + */ + public static MemorySegment PEM_read_bio_Parameters$address() { + return PEM_read_bio_Parameters.ADDR; + } + + /** + * {@snippet lang = c : * EVP_PKEY *PEM_read_bio_Parameters(BIO *bp, EVP_PKEY **x) * } */ public static MemorySegment PEM_read_bio_Parameters(MemorySegment bp, MemorySegment x) { - var mh$ = PEM_read_bio_Parameters$MH(); + var mh$ = PEM_read_bio_Parameters.HANDLE; try { if (TRACE_DOWNCALLS) { traceDowncall("PEM_read_bio_Parameters", bp, x); } return (MemorySegment) mh$.invokeExact(bp, x); } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); + throw new AssertionError("should not reach here", ex$); } } - private static MethodHandle SSL_CTX_get_options$MH() { - class Holder { - static final FunctionDescriptor DESC = FunctionDescriptor.of( - openssl_h.C_LONG, - openssl_h.C_POINTER - ); - - static final MethodHandle MH = Linker.nativeLinker().downcallHandle( - openssl_h.findOrThrow("SSL_CTX_get_options"), - DESC); - } - return Holder.MH; + private static class SSL_CTX_get_options { + public static final FunctionDescriptor DESC = FunctionDescriptor.of(openssl_h.C_LONG, openssl_h.C_POINTER); + + public static final MemorySegment ADDR = openssl_h.findOrThrow("SSL_CTX_get_options"); + + public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); } /** - * {@snippet lang=c : - * uint64_t SSL_CTX_get_options(const SSL_CTX *ctx) + * Function descriptor for: + * {@snippet lang = c : * uint64_t SSL_CTX_get_options(const SSL_CTX *ctx) + * } + */ + public static FunctionDescriptor SSL_CTX_get_options$descriptor() { + return SSL_CTX_get_options.DESC; + } + + /** + * Downcall method handle for: + * {@snippet lang = c : * uint64_t SSL_CTX_get_options(const SSL_CTX *ctx) + * } + */ + public static MethodHandle SSL_CTX_get_options$handle() { + return SSL_CTX_get_options.HANDLE; + } + + /** + * Address for: + * {@snippet lang = c : * uint64_t SSL_CTX_get_options(const SSL_CTX *ctx) + * } + */ + public static MemorySegment SSL_CTX_get_options$address() { + return SSL_CTX_get_options.ADDR; + } + + /** + * {@snippet lang = c : * uint64_t SSL_CTX_get_options(const SSL_CTX *ctx) * } */ public static long SSL_CTX_get_options(MemorySegment ctx) { - var mh$ = SSL_CTX_get_options$MH(); + var mh$ = SSL_CTX_get_options.HANDLE; try { if (TRACE_DOWNCALLS) { traceDowncall("SSL_CTX_get_options", ctx); } return (long) mh$.invokeExact(ctx); } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); + throw new AssertionError("should not reach here", ex$); } } - private static MethodHandle SSL_get_options$MH() { - class Holder { - static final FunctionDescriptor DESC = FunctionDescriptor.of( - openssl_h.C_LONG, - openssl_h.C_POINTER - ); - - static final MethodHandle MH = Linker.nativeLinker().downcallHandle( - openssl_h.findOrThrow("SSL_get_options"), - DESC); - } - return Holder.MH; + private static class SSL_get_options { + public static final FunctionDescriptor DESC = FunctionDescriptor.of(openssl_h.C_LONG, openssl_h.C_POINTER); + + public static final MemorySegment ADDR = openssl_h.findOrThrow("SSL_get_options"); + + public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); } /** - * {@snippet lang=c : - * uint64_t SSL_get_options(const SSL *s) + * Function descriptor for: + * {@snippet lang = c : * uint64_t SSL_get_options(const SSL *s) + * } + */ + public static FunctionDescriptor SSL_get_options$descriptor() { + return SSL_get_options.DESC; + } + + /** + * Downcall method handle for: + * {@snippet lang = c : * uint64_t SSL_get_options(const SSL *s) + * } + */ + public static MethodHandle SSL_get_options$handle() { + return SSL_get_options.HANDLE; + } + + /** + * Address for: + * {@snippet lang = c : * uint64_t SSL_get_options(const SSL *s) + * } + */ + public static MemorySegment SSL_get_options$address() { + return SSL_get_options.ADDR; + } + + /** + * {@snippet lang = c : * uint64_t SSL_get_options(const SSL *s) * } */ public static long SSL_get_options(MemorySegment s) { - var mh$ = SSL_get_options$MH(); + var mh$ = SSL_get_options.HANDLE; try { if (TRACE_DOWNCALLS) { traceDowncall("SSL_get_options", s); } return (long) mh$.invokeExact(s); } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); + throw new AssertionError("should not reach here", ex$); } } - private static MethodHandle SSL_CTX_clear_options$MH() { - class Holder { - static final FunctionDescriptor DESC = FunctionDescriptor.of( - openssl_h.C_LONG, - openssl_h.C_POINTER, - openssl_h.C_LONG - ); - - static final MethodHandle MH = Linker.nativeLinker().downcallHandle( - openssl_h.findOrThrow("SSL_CTX_clear_options"), - DESC); - } - return Holder.MH; + private static class SSL_CTX_clear_options { + public static final FunctionDescriptor DESC = + FunctionDescriptor.of(openssl_h.C_LONG, openssl_h.C_POINTER, openssl_h.C_LONG); + + public static final MemorySegment ADDR = openssl_h.findOrThrow("SSL_CTX_clear_options"); + + public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); } /** - * {@snippet lang=c : - * uint64_t SSL_CTX_clear_options(SSL_CTX *ctx, uint64_t op) + * Function descriptor for: + * {@snippet lang = c : * uint64_t SSL_CTX_clear_options(SSL_CTX *ctx, uint64_t op) + * } + */ + public static FunctionDescriptor SSL_CTX_clear_options$descriptor() { + return SSL_CTX_clear_options.DESC; + } + + /** + * Downcall method handle for: + * {@snippet lang = c : * uint64_t SSL_CTX_clear_options(SSL_CTX *ctx, uint64_t op) + * } + */ + public static MethodHandle SSL_CTX_clear_options$handle() { + return SSL_CTX_clear_options.HANDLE; + } + + /** + * Address for: + * {@snippet lang = c : * uint64_t SSL_CTX_clear_options(SSL_CTX *ctx, uint64_t op) + * } + */ + public static MemorySegment SSL_CTX_clear_options$address() { + return SSL_CTX_clear_options.ADDR; + } + + /** + * {@snippet lang = c : * uint64_t SSL_CTX_clear_options(SSL_CTX *ctx, uint64_t op) * } */ public static long SSL_CTX_clear_options(MemorySegment ctx, long op) { - var mh$ = SSL_CTX_clear_options$MH(); + var mh$ = SSL_CTX_clear_options.HANDLE; try { if (TRACE_DOWNCALLS) { traceDowncall("SSL_CTX_clear_options", ctx, op); } return (long) mh$.invokeExact(ctx, op); } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); + throw new AssertionError("should not reach here", ex$); } } - private static MethodHandle SSL_CTX_set_options$MH() { - class Holder { - static final FunctionDescriptor DESC = FunctionDescriptor.of( - openssl_h.C_LONG, - openssl_h.C_POINTER, - openssl_h.C_LONG - ); - - static final MethodHandle MH = Linker.nativeLinker().downcallHandle( - openssl_h.findOrThrow("SSL_CTX_set_options"), - DESC); - } - return Holder.MH; + private static class SSL_CTX_set_options { + public static final FunctionDescriptor DESC = + FunctionDescriptor.of(openssl_h.C_LONG, openssl_h.C_POINTER, openssl_h.C_LONG); + + public static final MemorySegment ADDR = openssl_h.findOrThrow("SSL_CTX_set_options"); + + public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); } /** - * {@snippet lang=c : - * uint64_t SSL_CTX_set_options(SSL_CTX *ctx, uint64_t op) + * Function descriptor for: + * {@snippet lang = c : * uint64_t SSL_CTX_set_options(SSL_CTX *ctx, uint64_t op) + * } + */ + public static FunctionDescriptor SSL_CTX_set_options$descriptor() { + return SSL_CTX_set_options.DESC; + } + + /** + * Downcall method handle for: + * {@snippet lang = c : * uint64_t SSL_CTX_set_options(SSL_CTX *ctx, uint64_t op) + * } + */ + public static MethodHandle SSL_CTX_set_options$handle() { + return SSL_CTX_set_options.HANDLE; + } + + /** + * Address for: + * {@snippet lang = c : * uint64_t SSL_CTX_set_options(SSL_CTX *ctx, uint64_t op) + * } + */ + public static MemorySegment SSL_CTX_set_options$address() { + return SSL_CTX_set_options.ADDR; + } + + /** + * {@snippet lang = c : * uint64_t SSL_CTX_set_options(SSL_CTX *ctx, uint64_t op) * } */ public static long SSL_CTX_set_options(MemorySegment ctx, long op) { - var mh$ = SSL_CTX_set_options$MH(); + var mh$ = SSL_CTX_set_options.HANDLE; try { if (TRACE_DOWNCALLS) { traceDowncall("SSL_CTX_set_options", ctx, op); } return (long) mh$.invokeExact(ctx, op); } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); + throw new AssertionError("should not reach here", ex$); } } - private static MethodHandle SSL_set_options$MH() { - class Holder { - static final FunctionDescriptor DESC = FunctionDescriptor.of( - openssl_h.C_LONG, - openssl_h.C_POINTER, - openssl_h.C_LONG - ); - - static final MethodHandle MH = Linker.nativeLinker().downcallHandle( - openssl_h.findOrThrow("SSL_set_options"), - DESC); - } - return Holder.MH; + private static class SSL_set_options { + public static final FunctionDescriptor DESC = + FunctionDescriptor.of(openssl_h.C_LONG, openssl_h.C_POINTER, openssl_h.C_LONG); + + public static final MemorySegment ADDR = openssl_h.findOrThrow("SSL_set_options"); + + public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); } /** - * {@snippet lang=c : - * uint64_t SSL_set_options(SSL *s, uint64_t op) + * Function descriptor for: + * {@snippet lang = c : * uint64_t SSL_set_options(SSL *s, uint64_t op) + * } + */ + public static FunctionDescriptor SSL_set_options$descriptor() { + return SSL_set_options.DESC; + } + + /** + * Downcall method handle for: + * {@snippet lang = c : * uint64_t SSL_set_options(SSL *s, uint64_t op) + * } + */ + public static MethodHandle SSL_set_options$handle() { + return SSL_set_options.HANDLE; + } + + /** + * Address for: + * {@snippet lang = c : * uint64_t SSL_set_options(SSL *s, uint64_t op) + * } + */ + public static MemorySegment SSL_set_options$address() { + return SSL_set_options.ADDR; + } + + /** + * {@snippet lang = c : * uint64_t SSL_set_options(SSL *s, uint64_t op) * } */ public static long SSL_set_options(MemorySegment s, long op) { - var mh$ = SSL_set_options$MH(); + var mh$ = SSL_set_options.HANDLE; try { if (TRACE_DOWNCALLS) { traceDowncall("SSL_set_options", s, op); } return (long) mh$.invokeExact(s, op); } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); + throw new AssertionError("should not reach here", ex$); } } - private static MethodHandle SSL_CTX_set_alpn_select_cb$MH() { - class Holder { - static final FunctionDescriptor DESC = FunctionDescriptor.ofVoid( - openssl_h.C_POINTER, - openssl_h.C_POINTER, - openssl_h.C_POINTER - ); - - static final MethodHandle MH = Linker.nativeLinker().downcallHandle( - openssl_h.findOrThrow("SSL_CTX_set_alpn_select_cb"), - DESC); - } - return Holder.MH; + private static class SSL_CTX_set_alpn_select_cb { + public static final FunctionDescriptor DESC = + FunctionDescriptor.ofVoid(openssl_h.C_POINTER, openssl_h.C_POINTER, openssl_h.C_POINTER); + + public static final MemorySegment ADDR = openssl_h.findOrThrow("SSL_CTX_set_alpn_select_cb"); + + public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); } /** - * {@snippet lang=c : - * void SSL_CTX_set_alpn_select_cb(SSL_CTX *ctx, SSL_CTX_alpn_select_cb_func cb, void *arg) + * Function descriptor for: + * {@snippet lang = c : * void SSL_CTX_set_alpn_select_cb(SSL_CTX *ctx, SSL_CTX_alpn_select_cb_func cb, void *arg) + * } + */ + public static FunctionDescriptor SSL_CTX_set_alpn_select_cb$descriptor() { + return SSL_CTX_set_alpn_select_cb.DESC; + } + + /** + * Downcall method handle for: + * {@snippet lang = c : * void SSL_CTX_set_alpn_select_cb(SSL_CTX *ctx, SSL_CTX_alpn_select_cb_func cb, void *arg) + * } + */ + public static MethodHandle SSL_CTX_set_alpn_select_cb$handle() { + return SSL_CTX_set_alpn_select_cb.HANDLE; + } + + /** + * Address for: + * {@snippet lang = c : * void SSL_CTX_set_alpn_select_cb(SSL_CTX *ctx, SSL_CTX_alpn_select_cb_func cb, void *arg) + * } + */ + public static MemorySegment SSL_CTX_set_alpn_select_cb$address() { + return SSL_CTX_set_alpn_select_cb.ADDR; + } + + /** + * {@snippet lang = c : * void SSL_CTX_set_alpn_select_cb(SSL_CTX *ctx, SSL_CTX_alpn_select_cb_func cb, void *arg) * } */ public static void SSL_CTX_set_alpn_select_cb(MemorySegment ctx, MemorySegment cb, MemorySegment arg) { - var mh$ = SSL_CTX_set_alpn_select_cb$MH(); + var mh$ = SSL_CTX_set_alpn_select_cb.HANDLE; try { if (TRACE_DOWNCALLS) { traceDowncall("SSL_CTX_set_alpn_select_cb", ctx, cb, arg); } mh$.invokeExact(ctx, cb, arg); } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); + throw new AssertionError("should not reach here", ex$); } } - private static MethodHandle SSL_get0_alpn_selected$MH() { - class Holder { - static final FunctionDescriptor DESC = FunctionDescriptor.ofVoid( - openssl_h.C_POINTER, - openssl_h.C_POINTER, - openssl_h.C_POINTER - ); - - static final MethodHandle MH = Linker.nativeLinker().downcallHandle( - openssl_h.findOrThrow("SSL_get0_alpn_selected"), - DESC); - } - return Holder.MH; + private static class SSL_get0_alpn_selected { + public static final FunctionDescriptor DESC = + FunctionDescriptor.ofVoid(openssl_h.C_POINTER, openssl_h.C_POINTER, openssl_h.C_POINTER); + + public static final MemorySegment ADDR = openssl_h.findOrThrow("SSL_get0_alpn_selected"); + + public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); } /** - * {@snippet lang=c : - * void SSL_get0_alpn_selected(const SSL *ssl, const unsigned char **data, unsigned int *len) + * Function descriptor for: + * {@snippet lang = c : * void SSL_get0_alpn_selected(const SSL *ssl, const unsigned char **data, unsigned int *len) + * } + */ + public static FunctionDescriptor SSL_get0_alpn_selected$descriptor() { + return SSL_get0_alpn_selected.DESC; + } + + /** + * Downcall method handle for: + * {@snippet lang = c : * void SSL_get0_alpn_selected(const SSL *ssl, const unsigned char **data, unsigned int *len) + * } + */ + public static MethodHandle SSL_get0_alpn_selected$handle() { + return SSL_get0_alpn_selected.HANDLE; + } + + /** + * Address for: + * {@snippet lang = c : * void SSL_get0_alpn_selected(const SSL *ssl, const unsigned char **data, unsigned int *len) + * } + */ + public static MemorySegment SSL_get0_alpn_selected$address() { + return SSL_get0_alpn_selected.ADDR; + } + + /** + * {@snippet lang = c : * void SSL_get0_alpn_selected(const SSL *ssl, const unsigned char **data, unsigned int *len) * } */ public static void SSL_get0_alpn_selected(MemorySegment ssl, MemorySegment data, MemorySegment len) { - var mh$ = SSL_get0_alpn_selected$MH(); + var mh$ = SSL_get0_alpn_selected.HANDLE; try { if (TRACE_DOWNCALLS) { traceDowncall("SSL_get0_alpn_selected", ssl, data, len); } mh$.invokeExact(ssl, data, len); } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); + throw new AssertionError("should not reach here", ex$); } } - private static MethodHandle SSL_in_init$MH() { - class Holder { - static final FunctionDescriptor DESC = FunctionDescriptor.of( - openssl_h.C_INT, - openssl_h.C_POINTER - ); - - static final MethodHandle MH = Linker.nativeLinker().downcallHandle( - openssl_h.findOrThrow("SSL_in_init"), - DESC); - } - return Holder.MH; + private static class SSL_in_init { + public static final FunctionDescriptor DESC = FunctionDescriptor.of(openssl_h.C_INT, openssl_h.C_POINTER); + + public static final MemorySegment ADDR = openssl_h.findOrThrow("SSL_in_init"); + + public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); } /** - * {@snippet lang=c : - * int SSL_in_init(const SSL *s) + * Function descriptor for: + * {@snippet lang = c : * int SSL_in_init(const SSL *s) + * } + */ + public static FunctionDescriptor SSL_in_init$descriptor() { + return SSL_in_init.DESC; + } + + /** + * Downcall method handle for: + * {@snippet lang = c : * int SSL_in_init(const SSL *s) + * } + */ + public static MethodHandle SSL_in_init$handle() { + return SSL_in_init.HANDLE; + } + + /** + * Address for: + * {@snippet lang = c : * int SSL_in_init(const SSL *s) + * } + */ + public static MemorySegment SSL_in_init$address() { + return SSL_in_init.ADDR; + } + + /** + * {@snippet lang = c : * int SSL_in_init(const SSL *s) * } */ public static int SSL_in_init(MemorySegment s) { - var mh$ = SSL_in_init$MH(); + var mh$ = SSL_in_init.HANDLE; try { if (TRACE_DOWNCALLS) { traceDowncall("SSL_in_init", s); } return (int) mh$.invokeExact(s); } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); + throw new AssertionError("should not reach here", ex$); } } - private static MethodHandle SSL_CTX_set0_tmp_dh_pkey$MH() { - class Holder { - static final FunctionDescriptor DESC = FunctionDescriptor.of( - openssl_h.C_INT, - openssl_h.C_POINTER, - openssl_h.C_POINTER - ); - - static final MethodHandle MH = Linker.nativeLinker().downcallHandle( - openssl_h.findOrThrow("SSL_CTX_set0_tmp_dh_pkey"), - DESC); - } - return Holder.MH; + private static class SSL_CTX_set0_tmp_dh_pkey { + public static final FunctionDescriptor DESC = + FunctionDescriptor.of(openssl_h.C_INT, openssl_h.C_POINTER, openssl_h.C_POINTER); + + public static final MemorySegment ADDR = openssl_h.findOrThrow("SSL_CTX_set0_tmp_dh_pkey"); + + public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); } /** - * {@snippet lang=c : - * int SSL_CTX_set0_tmp_dh_pkey(SSL_CTX *ctx, EVP_PKEY *dhpkey) + * Function descriptor for: + * {@snippet lang = c : * int SSL_CTX_set0_tmp_dh_pkey(SSL_CTX *ctx, EVP_PKEY *dhpkey) + * } + */ + public static FunctionDescriptor SSL_CTX_set0_tmp_dh_pkey$descriptor() { + return SSL_CTX_set0_tmp_dh_pkey.DESC; + } + + /** + * Downcall method handle for: + * {@snippet lang = c : * int SSL_CTX_set0_tmp_dh_pkey(SSL_CTX *ctx, EVP_PKEY *dhpkey) + * } + */ + public static MethodHandle SSL_CTX_set0_tmp_dh_pkey$handle() { + return SSL_CTX_set0_tmp_dh_pkey.HANDLE; + } + + /** + * Address for: + * {@snippet lang = c : * int SSL_CTX_set0_tmp_dh_pkey(SSL_CTX *ctx, EVP_PKEY *dhpkey) + * } + */ + public static MemorySegment SSL_CTX_set0_tmp_dh_pkey$address() { + return SSL_CTX_set0_tmp_dh_pkey.ADDR; + } + + /** + * {@snippet lang = c : * int SSL_CTX_set0_tmp_dh_pkey(SSL_CTX *ctx, EVP_PKEY *dhpkey) * } */ public static int SSL_CTX_set0_tmp_dh_pkey(MemorySegment ctx, MemorySegment dhpkey) { - var mh$ = SSL_CTX_set0_tmp_dh_pkey$MH(); + var mh$ = SSL_CTX_set0_tmp_dh_pkey.HANDLE; try { if (TRACE_DOWNCALLS) { traceDowncall("SSL_CTX_set0_tmp_dh_pkey", ctx, dhpkey); } return (int) mh$.invokeExact(ctx, dhpkey); } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); + throw new AssertionError("should not reach here", ex$); } } - private static MethodHandle SSL_CTX_set_cipher_list$MH() { - class Holder { - static final FunctionDescriptor DESC = FunctionDescriptor.of( - openssl_h.C_INT, - openssl_h.C_POINTER, - openssl_h.C_POINTER - ); - - static final MethodHandle MH = Linker.nativeLinker().downcallHandle( - openssl_h.findOrThrow("SSL_CTX_set_cipher_list"), - DESC); - } - return Holder.MH; + private static class SSL_CTX_set_cipher_list { + public static final FunctionDescriptor DESC = + FunctionDescriptor.of(openssl_h.C_INT, openssl_h.C_POINTER, openssl_h.C_POINTER); + + public static final MemorySegment ADDR = openssl_h.findOrThrow("SSL_CTX_set_cipher_list"); + + public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); } /** - * {@snippet lang=c : - * int SSL_CTX_set_cipher_list(SSL_CTX *, const char *str) + * Function descriptor for: + * {@snippet lang = c : * int SSL_CTX_set_cipher_list(SSL_CTX *, const char *str) + * } + */ + public static FunctionDescriptor SSL_CTX_set_cipher_list$descriptor() { + return SSL_CTX_set_cipher_list.DESC; + } + + /** + * Downcall method handle for: + * {@snippet lang = c : * int SSL_CTX_set_cipher_list(SSL_CTX *, const char *str) + * } + */ + public static MethodHandle SSL_CTX_set_cipher_list$handle() { + return SSL_CTX_set_cipher_list.HANDLE; + } + + /** + * Address for: + * {@snippet lang = c : * int SSL_CTX_set_cipher_list(SSL_CTX *, const char *str) + * } + */ + public static MemorySegment SSL_CTX_set_cipher_list$address() { + return SSL_CTX_set_cipher_list.ADDR; + } + + /** + * {@snippet lang = c : * int SSL_CTX_set_cipher_list(SSL_CTX *, const char *str) * } */ public static int SSL_CTX_set_cipher_list(MemorySegment x0, MemorySegment str) { - var mh$ = SSL_CTX_set_cipher_list$MH(); + var mh$ = SSL_CTX_set_cipher_list.HANDLE; try { if (TRACE_DOWNCALLS) { traceDowncall("SSL_CTX_set_cipher_list", x0, str); } return (int) mh$.invokeExact(x0, str); } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); + throw new AssertionError("should not reach here", ex$); } } - private static MethodHandle SSL_CTX_new$MH() { - class Holder { - static final FunctionDescriptor DESC = FunctionDescriptor.of( - openssl_h.C_POINTER, - openssl_h.C_POINTER - ); - - static final MethodHandle MH = Linker.nativeLinker().downcallHandle( - openssl_h.findOrThrow("SSL_CTX_new"), - DESC); - } - return Holder.MH; + private static class SSL_CTX_new { + public static final FunctionDescriptor DESC = FunctionDescriptor.of(openssl_h.C_POINTER, openssl_h.C_POINTER); + + public static final MemorySegment ADDR = openssl_h.findOrThrow("SSL_CTX_new"); + + public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); } /** - * {@snippet lang=c : - * SSL_CTX *SSL_CTX_new(const SSL_METHOD *meth) + * Function descriptor for: + * {@snippet lang = c : * SSL_CTX *SSL_CTX_new(const SSL_METHOD *meth) + * } + */ + public static FunctionDescriptor SSL_CTX_new$descriptor() { + return SSL_CTX_new.DESC; + } + + /** + * Downcall method handle for: + * {@snippet lang = c : * SSL_CTX *SSL_CTX_new(const SSL_METHOD *meth) + * } + */ + public static MethodHandle SSL_CTX_new$handle() { + return SSL_CTX_new.HANDLE; + } + + /** + * Address for: + * {@snippet lang = c : * SSL_CTX *SSL_CTX_new(const SSL_METHOD *meth) + * } + */ + public static MemorySegment SSL_CTX_new$address() { + return SSL_CTX_new.ADDR; + } + + /** + * {@snippet lang = c : * SSL_CTX *SSL_CTX_new(const SSL_METHOD *meth) * } */ public static MemorySegment SSL_CTX_new(MemorySegment meth) { - var mh$ = SSL_CTX_new$MH(); + var mh$ = SSL_CTX_new.HANDLE; try { if (TRACE_DOWNCALLS) { traceDowncall("SSL_CTX_new", meth); } return (MemorySegment) mh$.invokeExact(meth); } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); + throw new AssertionError("should not reach here", ex$); } } - private static MethodHandle SSL_CTX_free$MH() { - class Holder { - static final FunctionDescriptor DESC = FunctionDescriptor.ofVoid( - openssl_h.C_POINTER - ); - - static final MethodHandle MH = Linker.nativeLinker().downcallHandle( - openssl_h.findOrThrow("SSL_CTX_free"), - DESC); - } - return Holder.MH; + private static class SSL_CTX_free { + public static final FunctionDescriptor DESC = FunctionDescriptor.ofVoid(openssl_h.C_POINTER); + + public static final MemorySegment ADDR = openssl_h.findOrThrow("SSL_CTX_free"); + + public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); } /** - * {@snippet lang=c : - * void SSL_CTX_free(SSL_CTX *) + * Function descriptor for: + * {@snippet lang = c : * void SSL_CTX_free(SSL_CTX *) + * } + */ + public static FunctionDescriptor SSL_CTX_free$descriptor() { + return SSL_CTX_free.DESC; + } + + /** + * Downcall method handle for: + * {@snippet lang = c : * void SSL_CTX_free(SSL_CTX *) + * } + */ + public static MethodHandle SSL_CTX_free$handle() { + return SSL_CTX_free.HANDLE; + } + + /** + * Address for: + * {@snippet lang = c : * void SSL_CTX_free(SSL_CTX *) + * } + */ + public static MemorySegment SSL_CTX_free$address() { + return SSL_CTX_free.ADDR; + } + + /** + * {@snippet lang = c : * void SSL_CTX_free(SSL_CTX *) * } */ public static void SSL_CTX_free(MemorySegment x0) { - var mh$ = SSL_CTX_free$MH(); + var mh$ = SSL_CTX_free.HANDLE; try { if (TRACE_DOWNCALLS) { traceDowncall("SSL_CTX_free", x0); } mh$.invokeExact(x0); } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); + throw new AssertionError("should not reach here", ex$); } } - private static MethodHandle SSL_CTX_set_timeout$MH() { - class Holder { - static final FunctionDescriptor DESC = FunctionDescriptor.of( - openssl_h.C_LONG, - openssl_h.C_POINTER, - openssl_h.C_LONG - ); - - static final MethodHandle MH = Linker.nativeLinker().downcallHandle( - openssl_h.findOrThrow("SSL_CTX_set_timeout"), - DESC); - } - return Holder.MH; + private static class SSL_CTX_set_timeout { + public static final FunctionDescriptor DESC = + FunctionDescriptor.of(openssl_h.C_LONG, openssl_h.C_POINTER, openssl_h.C_LONG); + + public static final MemorySegment ADDR = openssl_h.findOrThrow("SSL_CTX_set_timeout"); + + public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); } /** - * {@snippet lang=c : - * long SSL_CTX_set_timeout(SSL_CTX *ctx, long t) + * Function descriptor for: + * {@snippet lang = c : * long SSL_CTX_set_timeout(SSL_CTX *ctx, long t) + * } + */ + public static FunctionDescriptor SSL_CTX_set_timeout$descriptor() { + return SSL_CTX_set_timeout.DESC; + } + + /** + * Downcall method handle for: + * {@snippet lang = c : * long SSL_CTX_set_timeout(SSL_CTX *ctx, long t) + * } + */ + public static MethodHandle SSL_CTX_set_timeout$handle() { + return SSL_CTX_set_timeout.HANDLE; + } + + /** + * Address for: + * {@snippet lang = c : * long SSL_CTX_set_timeout(SSL_CTX *ctx, long t) + * } + */ + public static MemorySegment SSL_CTX_set_timeout$address() { + return SSL_CTX_set_timeout.ADDR; + } + + /** + * {@snippet lang = c : * long SSL_CTX_set_timeout(SSL_CTX *ctx, long t) * } */ public static long SSL_CTX_set_timeout(MemorySegment ctx, long t) { - var mh$ = SSL_CTX_set_timeout$MH(); + var mh$ = SSL_CTX_set_timeout.HANDLE; try { if (TRACE_DOWNCALLS) { traceDowncall("SSL_CTX_set_timeout", ctx, t); } return (long) mh$.invokeExact(ctx, t); } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); + throw new AssertionError("should not reach here", ex$); } } - private static MethodHandle SSL_CTX_get_timeout$MH() { - class Holder { - static final FunctionDescriptor DESC = FunctionDescriptor.of( - openssl_h.C_LONG, - openssl_h.C_POINTER - ); - - static final MethodHandle MH = Linker.nativeLinker().downcallHandle( - openssl_h.findOrThrow("SSL_CTX_get_timeout"), - DESC); - } - return Holder.MH; + private static class SSL_CTX_get_timeout { + public static final FunctionDescriptor DESC = FunctionDescriptor.of(openssl_h.C_LONG, openssl_h.C_POINTER); + + public static final MemorySegment ADDR = openssl_h.findOrThrow("SSL_CTX_get_timeout"); + + public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); } /** - * {@snippet lang=c : - * long SSL_CTX_get_timeout(const SSL_CTX *ctx) + * Function descriptor for: + * {@snippet lang = c : * long SSL_CTX_get_timeout(const SSL_CTX *ctx) + * } + */ + public static FunctionDescriptor SSL_CTX_get_timeout$descriptor() { + return SSL_CTX_get_timeout.DESC; + } + + /** + * Downcall method handle for: + * {@snippet lang = c : * long SSL_CTX_get_timeout(const SSL_CTX *ctx) + * } + */ + public static MethodHandle SSL_CTX_get_timeout$handle() { + return SSL_CTX_get_timeout.HANDLE; + } + + /** + * Address for: + * {@snippet lang = c : * long SSL_CTX_get_timeout(const SSL_CTX *ctx) + * } + */ + public static MemorySegment SSL_CTX_get_timeout$address() { + return SSL_CTX_get_timeout.ADDR; + } + + /** + * {@snippet lang = c : * long SSL_CTX_get_timeout(const SSL_CTX *ctx) * } */ public static long SSL_CTX_get_timeout(MemorySegment ctx) { - var mh$ = SSL_CTX_get_timeout$MH(); + var mh$ = SSL_CTX_get_timeout.HANDLE; try { if (TRACE_DOWNCALLS) { traceDowncall("SSL_CTX_get_timeout", ctx); } return (long) mh$.invokeExact(ctx); } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); + throw new AssertionError("should not reach here", ex$); } } - private static MethodHandle SSL_CTX_get_cert_store$MH() { - class Holder { - static final FunctionDescriptor DESC = FunctionDescriptor.of( - openssl_h.C_POINTER, - openssl_h.C_POINTER - ); - - static final MethodHandle MH = Linker.nativeLinker().downcallHandle( - openssl_h.findOrThrow("SSL_CTX_get_cert_store"), - DESC); - } - return Holder.MH; + private static class SSL_CTX_get_cert_store { + public static final FunctionDescriptor DESC = FunctionDescriptor.of(openssl_h.C_POINTER, openssl_h.C_POINTER); + + public static final MemorySegment ADDR = openssl_h.findOrThrow("SSL_CTX_get_cert_store"); + + public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); } /** - * {@snippet lang=c : - * X509_STORE *SSL_CTX_get_cert_store(const SSL_CTX *) + * Function descriptor for: + * {@snippet lang = c : * X509_STORE *SSL_CTX_get_cert_store(const SSL_CTX *) + * } + */ + public static FunctionDescriptor SSL_CTX_get_cert_store$descriptor() { + return SSL_CTX_get_cert_store.DESC; + } + + /** + * Downcall method handle for: + * {@snippet lang = c : * X509_STORE *SSL_CTX_get_cert_store(const SSL_CTX *) + * } + */ + public static MethodHandle SSL_CTX_get_cert_store$handle() { + return SSL_CTX_get_cert_store.HANDLE; + } + + /** + * Address for: + * {@snippet lang = c : * X509_STORE *SSL_CTX_get_cert_store(const SSL_CTX *) + * } + */ + public static MemorySegment SSL_CTX_get_cert_store$address() { + return SSL_CTX_get_cert_store.ADDR; + } + + /** + * {@snippet lang = c : * X509_STORE *SSL_CTX_get_cert_store(const SSL_CTX *) * } */ public static MemorySegment SSL_CTX_get_cert_store(MemorySegment x0) { - var mh$ = SSL_CTX_get_cert_store$MH(); + var mh$ = SSL_CTX_get_cert_store.HANDLE; try { if (TRACE_DOWNCALLS) { traceDowncall("SSL_CTX_get_cert_store", x0); } return (MemorySegment) mh$.invokeExact(x0); } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); + throw new AssertionError("should not reach here", ex$); } } - private static MethodHandle SSL_get_current_cipher$MH() { - class Holder { - static final FunctionDescriptor DESC = FunctionDescriptor.of( - openssl_h.C_POINTER, - openssl_h.C_POINTER - ); - - static final MethodHandle MH = Linker.nativeLinker().downcallHandle( - openssl_h.findOrThrow("SSL_get_current_cipher"), - DESC); - } - return Holder.MH; + private static class SSL_get_current_cipher { + public static final FunctionDescriptor DESC = FunctionDescriptor.of(openssl_h.C_POINTER, openssl_h.C_POINTER); + + public static final MemorySegment ADDR = openssl_h.findOrThrow("SSL_get_current_cipher"); + + public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); } /** - * {@snippet lang=c : - * const SSL_CIPHER *SSL_get_current_cipher(const SSL *s) + * Function descriptor for: + * {@snippet lang = c : * const SSL_CIPHER *SSL_get_current_cipher(const SSL *s) + * } + */ + public static FunctionDescriptor SSL_get_current_cipher$descriptor() { + return SSL_get_current_cipher.DESC; + } + + /** + * Downcall method handle for: + * {@snippet lang = c : * const SSL_CIPHER *SSL_get_current_cipher(const SSL *s) + * } + */ + public static MethodHandle SSL_get_current_cipher$handle() { + return SSL_get_current_cipher.HANDLE; + } + + /** + * Address for: + * {@snippet lang = c : * const SSL_CIPHER *SSL_get_current_cipher(const SSL *s) + * } + */ + public static MemorySegment SSL_get_current_cipher$address() { + return SSL_get_current_cipher.ADDR; + } + + /** + * {@snippet lang = c : * const SSL_CIPHER *SSL_get_current_cipher(const SSL *s) * } */ public static MemorySegment SSL_get_current_cipher(MemorySegment s) { - var mh$ = SSL_get_current_cipher$MH(); + var mh$ = SSL_get_current_cipher.HANDLE; try { if (TRACE_DOWNCALLS) { traceDowncall("SSL_get_current_cipher", s); } return (MemorySegment) mh$.invokeExact(s); } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); + throw new AssertionError("should not reach here", ex$); } } - private static MethodHandle SSL_CIPHER_get_name$MH() { - class Holder { - static final FunctionDescriptor DESC = FunctionDescriptor.of( - openssl_h.C_POINTER, - openssl_h.C_POINTER - ); - - static final MethodHandle MH = Linker.nativeLinker().downcallHandle( - openssl_h.findOrThrow("SSL_CIPHER_get_name"), - DESC); - } - return Holder.MH; + private static class SSL_CIPHER_get_name { + public static final FunctionDescriptor DESC = FunctionDescriptor.of(openssl_h.C_POINTER, openssl_h.C_POINTER); + + public static final MemorySegment ADDR = openssl_h.findOrThrow("SSL_CIPHER_get_name"); + + public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); } /** - * {@snippet lang=c : - * const char *SSL_CIPHER_get_name(const SSL_CIPHER *c) + * Function descriptor for: + * {@snippet lang = c : * const char *SSL_CIPHER_get_name(const SSL_CIPHER *c) + * } + */ + public static FunctionDescriptor SSL_CIPHER_get_name$descriptor() { + return SSL_CIPHER_get_name.DESC; + } + + /** + * Downcall method handle for: + * {@snippet lang = c : * const char *SSL_CIPHER_get_name(const SSL_CIPHER *c) + * } + */ + public static MethodHandle SSL_CIPHER_get_name$handle() { + return SSL_CIPHER_get_name.HANDLE; + } + + /** + * Address for: + * {@snippet lang = c : * const char *SSL_CIPHER_get_name(const SSL_CIPHER *c) + * } + */ + public static MemorySegment SSL_CIPHER_get_name$address() { + return SSL_CIPHER_get_name.ADDR; + } + + /** + * {@snippet lang = c : * const char *SSL_CIPHER_get_name(const SSL_CIPHER *c) * } */ public static MemorySegment SSL_CIPHER_get_name(MemorySegment c) { - var mh$ = SSL_CIPHER_get_name$MH(); + var mh$ = SSL_CIPHER_get_name.HANDLE; try { if (TRACE_DOWNCALLS) { traceDowncall("SSL_CIPHER_get_name", c); } return (MemorySegment) mh$.invokeExact(c); } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); + throw new AssertionError("should not reach here", ex$); } } - private static MethodHandle SSL_CIPHER_get_kx_nid$MH() { - class Holder { - static final FunctionDescriptor DESC = FunctionDescriptor.of( - openssl_h.C_INT, - openssl_h.C_POINTER - ); - - static final MethodHandle MH = Linker.nativeLinker().downcallHandle( - openssl_h.findOrThrow("SSL_CIPHER_get_kx_nid"), - DESC); - } - return Holder.MH; + private static class SSL_CIPHER_get_kx_nid { + public static final FunctionDescriptor DESC = FunctionDescriptor.of(openssl_h.C_INT, openssl_h.C_POINTER); + + public static final MemorySegment ADDR = openssl_h.findOrThrow("SSL_CIPHER_get_kx_nid"); + + public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); } /** - * {@snippet lang=c : - * int SSL_CIPHER_get_kx_nid(const SSL_CIPHER *c) + * Function descriptor for: + * {@snippet lang = c : * int SSL_CIPHER_get_kx_nid(const SSL_CIPHER *c) + * } + */ + public static FunctionDescriptor SSL_CIPHER_get_kx_nid$descriptor() { + return SSL_CIPHER_get_kx_nid.DESC; + } + + /** + * Downcall method handle for: + * {@snippet lang = c : * int SSL_CIPHER_get_kx_nid(const SSL_CIPHER *c) + * } + */ + public static MethodHandle SSL_CIPHER_get_kx_nid$handle() { + return SSL_CIPHER_get_kx_nid.HANDLE; + } + + /** + * Address for: + * {@snippet lang = c : * int SSL_CIPHER_get_kx_nid(const SSL_CIPHER *c) + * } + */ + public static MemorySegment SSL_CIPHER_get_kx_nid$address() { + return SSL_CIPHER_get_kx_nid.ADDR; + } + + /** + * {@snippet lang = c : * int SSL_CIPHER_get_kx_nid(const SSL_CIPHER *c) * } */ public static int SSL_CIPHER_get_kx_nid(MemorySegment c) { - var mh$ = SSL_CIPHER_get_kx_nid$MH(); + var mh$ = SSL_CIPHER_get_kx_nid.HANDLE; try { if (TRACE_DOWNCALLS) { traceDowncall("SSL_CIPHER_get_kx_nid", c); } return (int) mh$.invokeExact(c); } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); + throw new AssertionError("should not reach here", ex$); } } - private static MethodHandle SSL_CIPHER_get_auth_nid$MH() { - class Holder { - static final FunctionDescriptor DESC = FunctionDescriptor.of( - openssl_h.C_INT, - openssl_h.C_POINTER - ); - - static final MethodHandle MH = Linker.nativeLinker().downcallHandle( - openssl_h.findOrThrow("SSL_CIPHER_get_auth_nid"), - DESC); - } - return Holder.MH; + private static class SSL_CIPHER_get_auth_nid { + public static final FunctionDescriptor DESC = FunctionDescriptor.of(openssl_h.C_INT, openssl_h.C_POINTER); + + public static final MemorySegment ADDR = openssl_h.findOrThrow("SSL_CIPHER_get_auth_nid"); + + public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); } /** - * {@snippet lang=c : - * int SSL_CIPHER_get_auth_nid(const SSL_CIPHER *c) + * Function descriptor for: + * {@snippet lang = c : * int SSL_CIPHER_get_auth_nid(const SSL_CIPHER *c) + * } + */ + public static FunctionDescriptor SSL_CIPHER_get_auth_nid$descriptor() { + return SSL_CIPHER_get_auth_nid.DESC; + } + + /** + * Downcall method handle for: + * {@snippet lang = c : * int SSL_CIPHER_get_auth_nid(const SSL_CIPHER *c) + * } + */ + public static MethodHandle SSL_CIPHER_get_auth_nid$handle() { + return SSL_CIPHER_get_auth_nid.HANDLE; + } + + /** + * Address for: + * {@snippet lang = c : * int SSL_CIPHER_get_auth_nid(const SSL_CIPHER *c) + * } + */ + public static MemorySegment SSL_CIPHER_get_auth_nid$address() { + return SSL_CIPHER_get_auth_nid.ADDR; + } + + /** + * {@snippet lang = c : * int SSL_CIPHER_get_auth_nid(const SSL_CIPHER *c) * } */ public static int SSL_CIPHER_get_auth_nid(MemorySegment c) { - var mh$ = SSL_CIPHER_get_auth_nid$MH(); + var mh$ = SSL_CIPHER_get_auth_nid.HANDLE; try { if (TRACE_DOWNCALLS) { traceDowncall("SSL_CIPHER_get_auth_nid", c); } return (int) mh$.invokeExact(c); } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); + throw new AssertionError("should not reach here", ex$); } } - private static MethodHandle SSL_pending$MH() { - class Holder { - static final FunctionDescriptor DESC = FunctionDescriptor.of( - openssl_h.C_INT, - openssl_h.C_POINTER - ); - - static final MethodHandle MH = Linker.nativeLinker().downcallHandle( - openssl_h.findOrThrow("SSL_pending"), - DESC); - } - return Holder.MH; + private static class SSL_pending { + public static final FunctionDescriptor DESC = FunctionDescriptor.of(openssl_h.C_INT, openssl_h.C_POINTER); + + public static final MemorySegment ADDR = openssl_h.findOrThrow("SSL_pending"); + + public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); } /** - * {@snippet lang=c : - * int SSL_pending(const SSL *s) + * Function descriptor for: + * {@snippet lang = c : * int SSL_pending(const SSL *s) + * } + */ + public static FunctionDescriptor SSL_pending$descriptor() { + return SSL_pending.DESC; + } + + /** + * Downcall method handle for: + * {@snippet lang = c : * int SSL_pending(const SSL *s) + * } + */ + public static MethodHandle SSL_pending$handle() { + return SSL_pending.HANDLE; + } + + /** + * Address for: + * {@snippet lang = c : * int SSL_pending(const SSL *s) + * } + */ + public static MemorySegment SSL_pending$address() { + return SSL_pending.ADDR; + } + + /** + * {@snippet lang = c : * int SSL_pending(const SSL *s) * } */ public static int SSL_pending(MemorySegment s) { - var mh$ = SSL_pending$MH(); + var mh$ = SSL_pending.HANDLE; try { if (TRACE_DOWNCALLS) { traceDowncall("SSL_pending", s); } return (int) mh$.invokeExact(s); } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); + throw new AssertionError("should not reach here", ex$); } } - private static MethodHandle SSL_set_bio$MH() { - class Holder { - static final FunctionDescriptor DESC = FunctionDescriptor.ofVoid( - openssl_h.C_POINTER, - openssl_h.C_POINTER, - openssl_h.C_POINTER - ); - - static final MethodHandle MH = Linker.nativeLinker().downcallHandle( - openssl_h.findOrThrow("SSL_set_bio"), - DESC); - } - return Holder.MH; + private static class SSL_set_bio { + public static final FunctionDescriptor DESC = + FunctionDescriptor.ofVoid(openssl_h.C_POINTER, openssl_h.C_POINTER, openssl_h.C_POINTER); + + public static final MemorySegment ADDR = openssl_h.findOrThrow("SSL_set_bio"); + + public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); } /** - * {@snippet lang=c : - * void SSL_set_bio(SSL *s, BIO *rbio, BIO *wbio) + * Function descriptor for: + * {@snippet lang = c : * void SSL_set_bio(SSL *s, BIO *rbio, BIO *wbio) + * } + */ + public static FunctionDescriptor SSL_set_bio$descriptor() { + return SSL_set_bio.DESC; + } + + /** + * Downcall method handle for: + * {@snippet lang = c : * void SSL_set_bio(SSL *s, BIO *rbio, BIO *wbio) + * } + */ + public static MethodHandle SSL_set_bio$handle() { + return SSL_set_bio.HANDLE; + } + + /** + * Address for: + * {@snippet lang = c : * void SSL_set_bio(SSL *s, BIO *rbio, BIO *wbio) + * } + */ + public static MemorySegment SSL_set_bio$address() { + return SSL_set_bio.ADDR; + } + + /** + * {@snippet lang = c : * void SSL_set_bio(SSL *s, BIO *rbio, BIO *wbio) * } */ public static void SSL_set_bio(MemorySegment s, MemorySegment rbio, MemorySegment wbio) { - var mh$ = SSL_set_bio$MH(); + var mh$ = SSL_set_bio.HANDLE; try { if (TRACE_DOWNCALLS) { traceDowncall("SSL_set_bio", s, rbio, wbio); } mh$.invokeExact(s, rbio, wbio); } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); + throw new AssertionError("should not reach here", ex$); } } - private static MethodHandle SSL_set_cipher_list$MH() { - class Holder { - static final FunctionDescriptor DESC = FunctionDescriptor.of( - openssl_h.C_INT, - openssl_h.C_POINTER, - openssl_h.C_POINTER - ); - - static final MethodHandle MH = Linker.nativeLinker().downcallHandle( - openssl_h.findOrThrow("SSL_set_cipher_list"), - DESC); - } - return Holder.MH; + private static class SSL_set_cipher_list { + public static final FunctionDescriptor DESC = + FunctionDescriptor.of(openssl_h.C_INT, openssl_h.C_POINTER, openssl_h.C_POINTER); + + public static final MemorySegment ADDR = openssl_h.findOrThrow("SSL_set_cipher_list"); + + public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); } /** - * {@snippet lang=c : - * int SSL_set_cipher_list(SSL *s, const char *str) + * Function descriptor for: + * {@snippet lang = c : * int SSL_set_cipher_list(SSL *s, const char *str) + * } + */ + public static FunctionDescriptor SSL_set_cipher_list$descriptor() { + return SSL_set_cipher_list.DESC; + } + + /** + * Downcall method handle for: + * {@snippet lang = c : * int SSL_set_cipher_list(SSL *s, const char *str) + * } + */ + public static MethodHandle SSL_set_cipher_list$handle() { + return SSL_set_cipher_list.HANDLE; + } + + /** + * Address for: + * {@snippet lang = c : * int SSL_set_cipher_list(SSL *s, const char *str) + * } + */ + public static MemorySegment SSL_set_cipher_list$address() { + return SSL_set_cipher_list.ADDR; + } + + /** + * {@snippet lang = c : * int SSL_set_cipher_list(SSL *s, const char *str) * } */ public static int SSL_set_cipher_list(MemorySegment s, MemorySegment str) { - var mh$ = SSL_set_cipher_list$MH(); + var mh$ = SSL_set_cipher_list.HANDLE; try { if (TRACE_DOWNCALLS) { traceDowncall("SSL_set_cipher_list", s, str); } return (int) mh$.invokeExact(s, str); } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); + throw new AssertionError("should not reach here", ex$); } } - private static MethodHandle SSL_CTX_set_ciphersuites$MH() { - class Holder { - static final FunctionDescriptor DESC = FunctionDescriptor.of( - openssl_h.C_INT, - openssl_h.C_POINTER, - openssl_h.C_POINTER - ); - - static final MethodHandle MH = Linker.nativeLinker().downcallHandle( - openssl_h.findOrThrow("SSL_CTX_set_ciphersuites"), - DESC); - } - return Holder.MH; + private static class SSL_CTX_set_ciphersuites { + public static final FunctionDescriptor DESC = + FunctionDescriptor.of(openssl_h.C_INT, openssl_h.C_POINTER, openssl_h.C_POINTER); + + public static final MemorySegment ADDR = openssl_h.findOrThrow("SSL_CTX_set_ciphersuites"); + + public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); } /** - * {@snippet lang=c : - * int SSL_CTX_set_ciphersuites(SSL_CTX *ctx, const char *str) + * Function descriptor for: + * {@snippet lang = c : * int SSL_CTX_set_ciphersuites(SSL_CTX *ctx, const char *str) + * } + */ + public static FunctionDescriptor SSL_CTX_set_ciphersuites$descriptor() { + return SSL_CTX_set_ciphersuites.DESC; + } + + /** + * Downcall method handle for: + * {@snippet lang = c : * int SSL_CTX_set_ciphersuites(SSL_CTX *ctx, const char *str) + * } + */ + public static MethodHandle SSL_CTX_set_ciphersuites$handle() { + return SSL_CTX_set_ciphersuites.HANDLE; + } + + /** + * Address for: + * {@snippet lang = c : * int SSL_CTX_set_ciphersuites(SSL_CTX *ctx, const char *str) + * } + */ + public static MemorySegment SSL_CTX_set_ciphersuites$address() { + return SSL_CTX_set_ciphersuites.ADDR; + } + + /** + * {@snippet lang = c : * int SSL_CTX_set_ciphersuites(SSL_CTX *ctx, const char *str) * } */ public static int SSL_CTX_set_ciphersuites(MemorySegment ctx, MemorySegment str) { - var mh$ = SSL_CTX_set_ciphersuites$MH(); + var mh$ = SSL_CTX_set_ciphersuites.HANDLE; try { if (TRACE_DOWNCALLS) { traceDowncall("SSL_CTX_set_ciphersuites", ctx, str); } return (int) mh$.invokeExact(ctx, str); } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); + throw new AssertionError("should not reach here", ex$); } } - private static MethodHandle SSL_set_verify$MH() { - class Holder { - static final FunctionDescriptor DESC = FunctionDescriptor.ofVoid( - openssl_h.C_POINTER, - openssl_h.C_INT, - openssl_h.C_POINTER - ); - - static final MethodHandle MH = Linker.nativeLinker().downcallHandle( - openssl_h.findOrThrow("SSL_set_verify"), - DESC); - } - return Holder.MH; + private static class SSL_set_verify { + public static final FunctionDescriptor DESC = + FunctionDescriptor.ofVoid(openssl_h.C_POINTER, openssl_h.C_INT, openssl_h.C_POINTER); + + public static final MemorySegment ADDR = openssl_h.findOrThrow("SSL_set_verify"); + + public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); } /** - * {@snippet lang=c : - * void SSL_set_verify(SSL *s, int mode, SSL_verify_cb callback) + * Function descriptor for: + * {@snippet lang = c : * void SSL_set_verify(SSL *s, int mode, SSL_verify_cb callback) + * } + */ + public static FunctionDescriptor SSL_set_verify$descriptor() { + return SSL_set_verify.DESC; + } + + /** + * Downcall method handle for: + * {@snippet lang = c : * void SSL_set_verify(SSL *s, int mode, SSL_verify_cb callback) + * } + */ + public static MethodHandle SSL_set_verify$handle() { + return SSL_set_verify.HANDLE; + } + + /** + * Address for: + * {@snippet lang = c : * void SSL_set_verify(SSL *s, int mode, SSL_verify_cb callback) + * } + */ + public static MemorySegment SSL_set_verify$address() { + return SSL_set_verify.ADDR; + } + + /** + * {@snippet lang = c : * void SSL_set_verify(SSL *s, int mode, SSL_verify_cb callback) * } */ public static void SSL_set_verify(MemorySegment s, int mode, MemorySegment callback) { - var mh$ = SSL_set_verify$MH(); + var mh$ = SSL_set_verify.HANDLE; try { if (TRACE_DOWNCALLS) { traceDowncall("SSL_set_verify", s, mode, callback); } mh$.invokeExact(s, mode, callback); } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); + throw new AssertionError("should not reach here", ex$); } } - private static MethodHandle SSL_CTX_use_certificate_chain_file$MH() { - class Holder { - static final FunctionDescriptor DESC = FunctionDescriptor.of( - openssl_h.C_INT, - openssl_h.C_POINTER, - openssl_h.C_POINTER - ); - - static final MethodHandle MH = Linker.nativeLinker().downcallHandle( - openssl_h.findOrThrow("SSL_CTX_use_certificate_chain_file"), - DESC); - } - return Holder.MH; + private static class SSL_CTX_use_certificate_chain_file { + public static final FunctionDescriptor DESC = + FunctionDescriptor.of(openssl_h.C_INT, openssl_h.C_POINTER, openssl_h.C_POINTER); + + public static final MemorySegment ADDR = openssl_h.findOrThrow("SSL_CTX_use_certificate_chain_file"); + + public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); } /** - * {@snippet lang=c : - * int SSL_CTX_use_certificate_chain_file(SSL_CTX *ctx, const char *file) + * Function descriptor for: + * {@snippet lang = c : * int SSL_CTX_use_certificate_chain_file(SSL_CTX *ctx, const char *file) + * } + */ + public static FunctionDescriptor SSL_CTX_use_certificate_chain_file$descriptor() { + return SSL_CTX_use_certificate_chain_file.DESC; + } + + /** + * Downcall method handle for: + * {@snippet lang = c : * int SSL_CTX_use_certificate_chain_file(SSL_CTX *ctx, const char *file) + * } + */ + public static MethodHandle SSL_CTX_use_certificate_chain_file$handle() { + return SSL_CTX_use_certificate_chain_file.HANDLE; + } + + /** + * Address for: + * {@snippet lang = c : * int SSL_CTX_use_certificate_chain_file(SSL_CTX *ctx, const char *file) + * } + */ + public static MemorySegment SSL_CTX_use_certificate_chain_file$address() { + return SSL_CTX_use_certificate_chain_file.ADDR; + } + + /** + * {@snippet lang = c : * int SSL_CTX_use_certificate_chain_file(SSL_CTX *ctx, const char *file) * } */ public static int SSL_CTX_use_certificate_chain_file(MemorySegment ctx, MemorySegment file) { - var mh$ = SSL_CTX_use_certificate_chain_file$MH(); + var mh$ = SSL_CTX_use_certificate_chain_file.HANDLE; try { if (TRACE_DOWNCALLS) { traceDowncall("SSL_CTX_use_certificate_chain_file", ctx, file); } return (int) mh$.invokeExact(ctx, file); } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); + throw new AssertionError("should not reach here", ex$); } } - private static MethodHandle SSL_load_client_CA_file$MH() { - class Holder { - static final FunctionDescriptor DESC = FunctionDescriptor.of( - openssl_h.C_POINTER, - openssl_h.C_POINTER - ); - - static final MethodHandle MH = Linker.nativeLinker().downcallHandle( - openssl_h.findOrThrow("SSL_load_client_CA_file"), - DESC); - } - return Holder.MH; + private static class SSL_load_client_CA_file { + public static final FunctionDescriptor DESC = FunctionDescriptor.of(openssl_h.C_POINTER, openssl_h.C_POINTER); + + public static final MemorySegment ADDR = openssl_h.findOrThrow("SSL_load_client_CA_file"); + + public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); } /** - * {@snippet lang=c : - * struct stack_st_X509_NAME *SSL_load_client_CA_file(const char *file) + * Function descriptor for: + * {@snippet lang = c : * struct stack_st_X509_NAME *SSL_load_client_CA_file(const char *file) + * } + */ + public static FunctionDescriptor SSL_load_client_CA_file$descriptor() { + return SSL_load_client_CA_file.DESC; + } + + /** + * Downcall method handle for: + * {@snippet lang = c : * struct stack_st_X509_NAME *SSL_load_client_CA_file(const char *file) + * } + */ + public static MethodHandle SSL_load_client_CA_file$handle() { + return SSL_load_client_CA_file.HANDLE; + } + + /** + * Address for: + * {@snippet lang = c : * struct stack_st_X509_NAME *SSL_load_client_CA_file(const char *file) + * } + */ + public static MemorySegment SSL_load_client_CA_file$address() { + return SSL_load_client_CA_file.ADDR; + } + + /** + * {@snippet lang = c : * struct stack_st_X509_NAME *SSL_load_client_CA_file(const char *file) * } */ public static MemorySegment SSL_load_client_CA_file(MemorySegment file) { - var mh$ = SSL_load_client_CA_file$MH(); + var mh$ = SSL_load_client_CA_file.HANDLE; try { if (TRACE_DOWNCALLS) { traceDowncall("SSL_load_client_CA_file", file); } return (MemorySegment) mh$.invokeExact(file); } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); + throw new AssertionError("should not reach here", ex$); } } - private static MethodHandle SSL_add_file_cert_subjects_to_stack$MH() { - class Holder { - static final FunctionDescriptor DESC = FunctionDescriptor.of( - openssl_h.C_INT, - openssl_h.C_POINTER, - openssl_h.C_POINTER - ); - - static final MethodHandle MH = Linker.nativeLinker().downcallHandle( - openssl_h.findOrThrow("SSL_add_file_cert_subjects_to_stack"), - DESC); - } - return Holder.MH; + private static class SSL_add_file_cert_subjects_to_stack { + public static final FunctionDescriptor DESC = + FunctionDescriptor.of(openssl_h.C_INT, openssl_h.C_POINTER, openssl_h.C_POINTER); + + public static final MemorySegment ADDR = openssl_h.findOrThrow("SSL_add_file_cert_subjects_to_stack"); + + public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); } /** - * {@snippet lang=c : - * int SSL_add_file_cert_subjects_to_stack(struct stack_st_X509_NAME *stackCAs, const char *file) + * Function descriptor for: + * {@snippet lang = c + * : * int SSL_add_file_cert_subjects_to_stack(struct stack_st_X509_NAME *stackCAs, const char *file) + * } + */ + public static FunctionDescriptor SSL_add_file_cert_subjects_to_stack$descriptor() { + return SSL_add_file_cert_subjects_to_stack.DESC; + } + + /** + * Downcall method handle for: + * {@snippet lang = c + * : * int SSL_add_file_cert_subjects_to_stack(struct stack_st_X509_NAME *stackCAs, const char *file) + * } + */ + public static MethodHandle SSL_add_file_cert_subjects_to_stack$handle() { + return SSL_add_file_cert_subjects_to_stack.HANDLE; + } + + /** + * Address for: + * {@snippet lang = c + * : * int SSL_add_file_cert_subjects_to_stack(struct stack_st_X509_NAME *stackCAs, const char *file) + * } + */ + public static MemorySegment SSL_add_file_cert_subjects_to_stack$address() { + return SSL_add_file_cert_subjects_to_stack.ADDR; + } + + /** + * {@snippet lang = c + * : * int SSL_add_file_cert_subjects_to_stack(struct stack_st_X509_NAME *stackCAs, const char *file) * } */ public static int SSL_add_file_cert_subjects_to_stack(MemorySegment stackCAs, MemorySegment file) { - var mh$ = SSL_add_file_cert_subjects_to_stack$MH(); + var mh$ = SSL_add_file_cert_subjects_to_stack.HANDLE; try { if (TRACE_DOWNCALLS) { traceDowncall("SSL_add_file_cert_subjects_to_stack", stackCAs, file); } return (int) mh$.invokeExact(stackCAs, file); } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); + throw new AssertionError("should not reach here", ex$); } } - private static MethodHandle SSL_SESSION_get_time$MH() { - class Holder { - static final FunctionDescriptor DESC = FunctionDescriptor.of( - openssl_h.C_LONG, - openssl_h.C_POINTER - ); - - static final MethodHandle MH = Linker.nativeLinker().downcallHandle( - openssl_h.findOrThrow("SSL_SESSION_get_time"), - DESC); - } - return Holder.MH; + private static class SSL_SESSION_get_time { + public static final FunctionDescriptor DESC = FunctionDescriptor.of(openssl_h.C_LONG, openssl_h.C_POINTER); + + public static final MemorySegment ADDR = openssl_h.findOrThrow("SSL_SESSION_get_time"); + + public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); } /** - * {@snippet lang=c : - * long SSL_SESSION_get_time(const SSL_SESSION *s) + * Function descriptor for: + * {@snippet lang = c : * long SSL_SESSION_get_time(const SSL_SESSION *s) + * } + */ + public static FunctionDescriptor SSL_SESSION_get_time$descriptor() { + return SSL_SESSION_get_time.DESC; + } + + /** + * Downcall method handle for: + * {@snippet lang = c : * long SSL_SESSION_get_time(const SSL_SESSION *s) + * } + */ + public static MethodHandle SSL_SESSION_get_time$handle() { + return SSL_SESSION_get_time.HANDLE; + } + + /** + * Address for: + * {@snippet lang = c : * long SSL_SESSION_get_time(const SSL_SESSION *s) + * } + */ + public static MemorySegment SSL_SESSION_get_time$address() { + return SSL_SESSION_get_time.ADDR; + } + + /** + * {@snippet lang = c : * long SSL_SESSION_get_time(const SSL_SESSION *s) * } */ public static long SSL_SESSION_get_time(MemorySegment s) { - var mh$ = SSL_SESSION_get_time$MH(); + var mh$ = SSL_SESSION_get_time.HANDLE; try { if (TRACE_DOWNCALLS) { traceDowncall("SSL_SESSION_get_time", s); } return (long) mh$.invokeExact(s); } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); + throw new AssertionError("should not reach here", ex$); } } - private static MethodHandle SSL_SESSION_get_id$MH() { - class Holder { - static final FunctionDescriptor DESC = FunctionDescriptor.of( - openssl_h.C_POINTER, - openssl_h.C_POINTER, - openssl_h.C_POINTER - ); - - static final MethodHandle MH = Linker.nativeLinker().downcallHandle( - openssl_h.findOrThrow("SSL_SESSION_get_id"), - DESC); - } - return Holder.MH; + private static class SSL_SESSION_get_id { + public static final FunctionDescriptor DESC = + FunctionDescriptor.of(openssl_h.C_POINTER, openssl_h.C_POINTER, openssl_h.C_POINTER); + + public static final MemorySegment ADDR = openssl_h.findOrThrow("SSL_SESSION_get_id"); + + public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); } /** - * {@snippet lang=c : - * const unsigned char *SSL_SESSION_get_id(const SSL_SESSION *s, unsigned int *len) + * Function descriptor for: + * {@snippet lang = c : * const unsigned char *SSL_SESSION_get_id(const SSL_SESSION *s, unsigned int *len) + * } + */ + public static FunctionDescriptor SSL_SESSION_get_id$descriptor() { + return SSL_SESSION_get_id.DESC; + } + + /** + * Downcall method handle for: + * {@snippet lang = c : * const unsigned char *SSL_SESSION_get_id(const SSL_SESSION *s, unsigned int *len) + * } + */ + public static MethodHandle SSL_SESSION_get_id$handle() { + return SSL_SESSION_get_id.HANDLE; + } + + /** + * Address for: + * {@snippet lang = c : * const unsigned char *SSL_SESSION_get_id(const SSL_SESSION *s, unsigned int *len) + * } + */ + public static MemorySegment SSL_SESSION_get_id$address() { + return SSL_SESSION_get_id.ADDR; + } + + /** + * {@snippet lang = c : * const unsigned char *SSL_SESSION_get_id(const SSL_SESSION *s, unsigned int *len) * } */ public static MemorySegment SSL_SESSION_get_id(MemorySegment s, MemorySegment len) { - var mh$ = SSL_SESSION_get_id$MH(); + var mh$ = SSL_SESSION_get_id.HANDLE; try { if (TRACE_DOWNCALLS) { traceDowncall("SSL_SESSION_get_id", s, len); } return (MemorySegment) mh$.invokeExact(s, len); } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); + throw new AssertionError("should not reach here", ex$); } } - private static MethodHandle SSL_get1_peer_certificate$MH() { - class Holder { - static final FunctionDescriptor DESC = FunctionDescriptor.of( - openssl_h.C_POINTER, - openssl_h.C_POINTER - ); - - static final MethodHandle MH = Linker.nativeLinker().downcallHandle( - openssl_h.findOrThrow("SSL_get1_peer_certificate"), - DESC); - } - return Holder.MH; + private static class SSL_get1_peer_certificate { + public static final FunctionDescriptor DESC = FunctionDescriptor.of(openssl_h.C_POINTER, openssl_h.C_POINTER); + + public static final MemorySegment ADDR = openssl_h.findOrThrow("SSL_get1_peer_certificate"); + + public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); } /** - * {@snippet lang=c : - * X509 *SSL_get1_peer_certificate(const SSL *s) + * Function descriptor for: + * {@snippet lang = c : * X509 *SSL_get1_peer_certificate(const SSL *s) + * } + */ + public static FunctionDescriptor SSL_get1_peer_certificate$descriptor() { + return SSL_get1_peer_certificate.DESC; + } + + /** + * Downcall method handle for: + * {@snippet lang = c : * X509 *SSL_get1_peer_certificate(const SSL *s) + * } + */ + public static MethodHandle SSL_get1_peer_certificate$handle() { + return SSL_get1_peer_certificate.HANDLE; + } + + /** + * Address for: + * {@snippet lang = c : * X509 *SSL_get1_peer_certificate(const SSL *s) + * } + */ + public static MemorySegment SSL_get1_peer_certificate$address() { + return SSL_get1_peer_certificate.ADDR; + } + + /** + * {@snippet lang = c : * X509 *SSL_get1_peer_certificate(const SSL *s) * } */ public static MemorySegment SSL_get1_peer_certificate(MemorySegment s) { - var mh$ = SSL_get1_peer_certificate$MH(); + var mh$ = SSL_get1_peer_certificate.HANDLE; try { if (TRACE_DOWNCALLS) { traceDowncall("SSL_get1_peer_certificate", s); } return (MemorySegment) mh$.invokeExact(s); } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); + throw new AssertionError("should not reach here", ex$); } } - private static MethodHandle SSL_get_peer_cert_chain$MH() { - class Holder { - static final FunctionDescriptor DESC = FunctionDescriptor.of( - openssl_h.C_POINTER, - openssl_h.C_POINTER - ); - - static final MethodHandle MH = Linker.nativeLinker().downcallHandle( - openssl_h.findOrThrow("SSL_get_peer_cert_chain"), - DESC); - } - return Holder.MH; + private static class SSL_get_peer_cert_chain { + public static final FunctionDescriptor DESC = FunctionDescriptor.of(openssl_h.C_POINTER, openssl_h.C_POINTER); + + public static final MemorySegment ADDR = openssl_h.findOrThrow("SSL_get_peer_cert_chain"); + + public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); } /** - * {@snippet lang=c : - * struct stack_st_X509 *SSL_get_peer_cert_chain(const SSL *s) + * Function descriptor for: + * {@snippet lang = c : * struct stack_st_X509 *SSL_get_peer_cert_chain(const SSL *s) + * } + */ + public static FunctionDescriptor SSL_get_peer_cert_chain$descriptor() { + return SSL_get_peer_cert_chain.DESC; + } + + /** + * Downcall method handle for: + * {@snippet lang = c : * struct stack_st_X509 *SSL_get_peer_cert_chain(const SSL *s) + * } + */ + public static MethodHandle SSL_get_peer_cert_chain$handle() { + return SSL_get_peer_cert_chain.HANDLE; + } + + /** + * Address for: + * {@snippet lang = c : * struct stack_st_X509 *SSL_get_peer_cert_chain(const SSL *s) + * } + */ + public static MemorySegment SSL_get_peer_cert_chain$address() { + return SSL_get_peer_cert_chain.ADDR; + } + + /** + * {@snippet lang = c : * struct stack_st_X509 *SSL_get_peer_cert_chain(const SSL *s) * } */ public static MemorySegment SSL_get_peer_cert_chain(MemorySegment s) { - var mh$ = SSL_get_peer_cert_chain$MH(); + var mh$ = SSL_get_peer_cert_chain.HANDLE; try { if (TRACE_DOWNCALLS) { traceDowncall("SSL_get_peer_cert_chain", s); } return (MemorySegment) mh$.invokeExact(s); } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); + throw new AssertionError("should not reach here", ex$); } } - private static MethodHandle SSL_CTX_set_verify$MH() { - class Holder { - static final FunctionDescriptor DESC = FunctionDescriptor.ofVoid( - openssl_h.C_POINTER, - openssl_h.C_INT, - openssl_h.C_POINTER - ); - - static final MethodHandle MH = Linker.nativeLinker().downcallHandle( - openssl_h.findOrThrow("SSL_CTX_set_verify"), - DESC); - } - return Holder.MH; + private static class SSL_CTX_set_verify { + public static final FunctionDescriptor DESC = + FunctionDescriptor.ofVoid(openssl_h.C_POINTER, openssl_h.C_INT, openssl_h.C_POINTER); + + public static final MemorySegment ADDR = openssl_h.findOrThrow("SSL_CTX_set_verify"); + + public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); } /** - * {@snippet lang=c : - * void SSL_CTX_set_verify(SSL_CTX *ctx, int mode, SSL_verify_cb callback) + * Function descriptor for: + * {@snippet lang = c : * void SSL_CTX_set_verify(SSL_CTX *ctx, int mode, SSL_verify_cb callback) + * } + */ + public static FunctionDescriptor SSL_CTX_set_verify$descriptor() { + return SSL_CTX_set_verify.DESC; + } + + /** + * Downcall method handle for: + * {@snippet lang = c : * void SSL_CTX_set_verify(SSL_CTX *ctx, int mode, SSL_verify_cb callback) + * } + */ + public static MethodHandle SSL_CTX_set_verify$handle() { + return SSL_CTX_set_verify.HANDLE; + } + + /** + * Address for: + * {@snippet lang = c : * void SSL_CTX_set_verify(SSL_CTX *ctx, int mode, SSL_verify_cb callback) + * } + */ + public static MemorySegment SSL_CTX_set_verify$address() { + return SSL_CTX_set_verify.ADDR; + } + + /** + * {@snippet lang = c : * void SSL_CTX_set_verify(SSL_CTX *ctx, int mode, SSL_verify_cb callback) * } */ public static void SSL_CTX_set_verify(MemorySegment ctx, int mode, MemorySegment callback) { - var mh$ = SSL_CTX_set_verify$MH(); + var mh$ = SSL_CTX_set_verify.HANDLE; try { if (TRACE_DOWNCALLS) { traceDowncall("SSL_CTX_set_verify", ctx, mode, callback); } mh$.invokeExact(ctx, mode, callback); } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); + throw new AssertionError("should not reach here", ex$); } } - private static MethodHandle SSL_CTX_set_cert_verify_callback$MH() { - class Holder { - static final FunctionDescriptor DESC = FunctionDescriptor.ofVoid( - openssl_h.C_POINTER, - openssl_h.C_POINTER, - openssl_h.C_POINTER - ); - - static final MethodHandle MH = Linker.nativeLinker().downcallHandle( - openssl_h.findOrThrow("SSL_CTX_set_cert_verify_callback"), - DESC); - } - return Holder.MH; + private static class SSL_CTX_set_cert_verify_callback { + public static final FunctionDescriptor DESC = + FunctionDescriptor.ofVoid(openssl_h.C_POINTER, openssl_h.C_POINTER, openssl_h.C_POINTER); + + public static final MemorySegment ADDR = openssl_h.findOrThrow("SSL_CTX_set_cert_verify_callback"); + + public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); } /** - * {@snippet lang=c : - * void SSL_CTX_set_cert_verify_callback(SSL_CTX *ctx, int (*cb)(X509_STORE_CTX *, void *), void *arg) + * Function descriptor for: + * {@snippet lang = c + * : * void SSL_CTX_set_cert_verify_callback(SSL_CTX *ctx, int (*cb)(X509_STORE_CTX *, void *), void *arg) + * } + */ + public static FunctionDescriptor SSL_CTX_set_cert_verify_callback$descriptor() { + return SSL_CTX_set_cert_verify_callback.DESC; + } + + /** + * Downcall method handle for: + * {@snippet lang = c + * : * void SSL_CTX_set_cert_verify_callback(SSL_CTX *ctx, int (*cb)(X509_STORE_CTX *, void *), void *arg) + * } + */ + public static MethodHandle SSL_CTX_set_cert_verify_callback$handle() { + return SSL_CTX_set_cert_verify_callback.HANDLE; + } + + /** + * Address for: + * {@snippet lang = c + * : * void SSL_CTX_set_cert_verify_callback(SSL_CTX *ctx, int (*cb)(X509_STORE_CTX *, void *), void *arg) + * } + */ + public static MemorySegment SSL_CTX_set_cert_verify_callback$address() { + return SSL_CTX_set_cert_verify_callback.ADDR; + } + + /** + * {@snippet lang = c + * : * void SSL_CTX_set_cert_verify_callback(SSL_CTX *ctx, int (*cb)(X509_STORE_CTX *, void *), void *arg) * } */ public static void SSL_CTX_set_cert_verify_callback(MemorySegment ctx, MemorySegment cb, MemorySegment arg) { - var mh$ = SSL_CTX_set_cert_verify_callback$MH(); + var mh$ = SSL_CTX_set_cert_verify_callback.HANDLE; try { if (TRACE_DOWNCALLS) { traceDowncall("SSL_CTX_set_cert_verify_callback", ctx, cb, arg); } mh$.invokeExact(ctx, cb, arg); } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); + throw new AssertionError("should not reach here", ex$); } } - private static MethodHandle SSL_CTX_use_PrivateKey$MH() { - class Holder { - static final FunctionDescriptor DESC = FunctionDescriptor.of( - openssl_h.C_INT, - openssl_h.C_POINTER, - openssl_h.C_POINTER - ); - - static final MethodHandle MH = Linker.nativeLinker().downcallHandle( - openssl_h.findOrThrow("SSL_CTX_use_PrivateKey"), - DESC); - } - return Holder.MH; + private static class SSL_CTX_use_PrivateKey { + public static final FunctionDescriptor DESC = + FunctionDescriptor.of(openssl_h.C_INT, openssl_h.C_POINTER, openssl_h.C_POINTER); + + public static final MemorySegment ADDR = openssl_h.findOrThrow("SSL_CTX_use_PrivateKey"); + + public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); } /** - * {@snippet lang=c : - * int SSL_CTX_use_PrivateKey(SSL_CTX *ctx, EVP_PKEY *pkey) + * Function descriptor for: + * {@snippet lang = c : * int SSL_CTX_use_PrivateKey(SSL_CTX *ctx, EVP_PKEY *pkey) + * } + */ + public static FunctionDescriptor SSL_CTX_use_PrivateKey$descriptor() { + return SSL_CTX_use_PrivateKey.DESC; + } + + /** + * Downcall method handle for: + * {@snippet lang = c : * int SSL_CTX_use_PrivateKey(SSL_CTX *ctx, EVP_PKEY *pkey) + * } + */ + public static MethodHandle SSL_CTX_use_PrivateKey$handle() { + return SSL_CTX_use_PrivateKey.HANDLE; + } + + /** + * Address for: + * {@snippet lang = c : * int SSL_CTX_use_PrivateKey(SSL_CTX *ctx, EVP_PKEY *pkey) + * } + */ + public static MemorySegment SSL_CTX_use_PrivateKey$address() { + return SSL_CTX_use_PrivateKey.ADDR; + } + + /** + * {@snippet lang = c : * int SSL_CTX_use_PrivateKey(SSL_CTX *ctx, EVP_PKEY *pkey) * } */ public static int SSL_CTX_use_PrivateKey(MemorySegment ctx, MemorySegment pkey) { - var mh$ = SSL_CTX_use_PrivateKey$MH(); + var mh$ = SSL_CTX_use_PrivateKey.HANDLE; try { if (TRACE_DOWNCALLS) { traceDowncall("SSL_CTX_use_PrivateKey", ctx, pkey); } return (int) mh$.invokeExact(ctx, pkey); } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); + throw new AssertionError("should not reach here", ex$); } } - private static MethodHandle SSL_CTX_use_certificate$MH() { - class Holder { - static final FunctionDescriptor DESC = FunctionDescriptor.of( - openssl_h.C_INT, - openssl_h.C_POINTER, - openssl_h.C_POINTER - ); - - static final MethodHandle MH = Linker.nativeLinker().downcallHandle( - openssl_h.findOrThrow("SSL_CTX_use_certificate"), - DESC); - } - return Holder.MH; + private static class SSL_CTX_use_certificate { + public static final FunctionDescriptor DESC = + FunctionDescriptor.of(openssl_h.C_INT, openssl_h.C_POINTER, openssl_h.C_POINTER); + + public static final MemorySegment ADDR = openssl_h.findOrThrow("SSL_CTX_use_certificate"); + + public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); } /** - * {@snippet lang=c : - * int SSL_CTX_use_certificate(SSL_CTX *ctx, X509 *x) + * Function descriptor for: + * {@snippet lang = c : * int SSL_CTX_use_certificate(SSL_CTX *ctx, X509 *x) + * } + */ + public static FunctionDescriptor SSL_CTX_use_certificate$descriptor() { + return SSL_CTX_use_certificate.DESC; + } + + /** + * Downcall method handle for: + * {@snippet lang = c : * int SSL_CTX_use_certificate(SSL_CTX *ctx, X509 *x) + * } + */ + public static MethodHandle SSL_CTX_use_certificate$handle() { + return SSL_CTX_use_certificate.HANDLE; + } + + /** + * Address for: + * {@snippet lang = c : * int SSL_CTX_use_certificate(SSL_CTX *ctx, X509 *x) + * } + */ + public static MemorySegment SSL_CTX_use_certificate$address() { + return SSL_CTX_use_certificate.ADDR; + } + + /** + * {@snippet lang = c : * int SSL_CTX_use_certificate(SSL_CTX *ctx, X509 *x) * } */ public static int SSL_CTX_use_certificate(MemorySegment ctx, MemorySegment x) { - var mh$ = SSL_CTX_use_certificate$MH(); + var mh$ = SSL_CTX_use_certificate.HANDLE; try { if (TRACE_DOWNCALLS) { traceDowncall("SSL_CTX_use_certificate", ctx, x); } return (int) mh$.invokeExact(ctx, x); } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); + throw new AssertionError("should not reach here", ex$); } } - private static MethodHandle SSL_CTX_set_default_passwd_cb$MH() { - class Holder { - static final FunctionDescriptor DESC = FunctionDescriptor.ofVoid( - openssl_h.C_POINTER, - openssl_h.C_POINTER - ); - - static final MethodHandle MH = Linker.nativeLinker().downcallHandle( - openssl_h.findOrThrow("SSL_CTX_set_default_passwd_cb"), - DESC); - } - return Holder.MH; + private static class SSL_CTX_set_default_passwd_cb { + public static final FunctionDescriptor DESC = + FunctionDescriptor.ofVoid(openssl_h.C_POINTER, openssl_h.C_POINTER); + + public static final MemorySegment ADDR = openssl_h.findOrThrow("SSL_CTX_set_default_passwd_cb"); + + public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); } /** - * {@snippet lang=c : - * void SSL_CTX_set_default_passwd_cb(SSL_CTX *ctx, pem_password_cb *cb) + * Function descriptor for: + * {@snippet lang = c : * void SSL_CTX_set_default_passwd_cb(SSL_CTX *ctx, pem_password_cb *cb) + * } + */ + public static FunctionDescriptor SSL_CTX_set_default_passwd_cb$descriptor() { + return SSL_CTX_set_default_passwd_cb.DESC; + } + + /** + * Downcall method handle for: + * {@snippet lang = c : * void SSL_CTX_set_default_passwd_cb(SSL_CTX *ctx, pem_password_cb *cb) + * } + */ + public static MethodHandle SSL_CTX_set_default_passwd_cb$handle() { + return SSL_CTX_set_default_passwd_cb.HANDLE; + } + + /** + * Address for: + * {@snippet lang = c : * void SSL_CTX_set_default_passwd_cb(SSL_CTX *ctx, pem_password_cb *cb) + * } + */ + public static MemorySegment SSL_CTX_set_default_passwd_cb$address() { + return SSL_CTX_set_default_passwd_cb.ADDR; + } + + /** + * {@snippet lang = c : * void SSL_CTX_set_default_passwd_cb(SSL_CTX *ctx, pem_password_cb *cb) * } */ public static void SSL_CTX_set_default_passwd_cb(MemorySegment ctx, MemorySegment cb) { - var mh$ = SSL_CTX_set_default_passwd_cb$MH(); + var mh$ = SSL_CTX_set_default_passwd_cb.HANDLE; try { if (TRACE_DOWNCALLS) { traceDowncall("SSL_CTX_set_default_passwd_cb", ctx, cb); } mh$.invokeExact(ctx, cb); } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); + throw new AssertionError("should not reach here", ex$); } } - private static MethodHandle SSL_CTX_check_private_key$MH() { - class Holder { - static final FunctionDescriptor DESC = FunctionDescriptor.of( - openssl_h.C_INT, - openssl_h.C_POINTER - ); - - static final MethodHandle MH = Linker.nativeLinker().downcallHandle( - openssl_h.findOrThrow("SSL_CTX_check_private_key"), - DESC); - } - return Holder.MH; + private static class SSL_CTX_check_private_key { + public static final FunctionDescriptor DESC = FunctionDescriptor.of(openssl_h.C_INT, openssl_h.C_POINTER); + + public static final MemorySegment ADDR = openssl_h.findOrThrow("SSL_CTX_check_private_key"); + + public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); } /** - * {@snippet lang=c : - * int SSL_CTX_check_private_key(const SSL_CTX *ctx) + * Function descriptor for: + * {@snippet lang = c : * int SSL_CTX_check_private_key(const SSL_CTX *ctx) + * } + */ + public static FunctionDescriptor SSL_CTX_check_private_key$descriptor() { + return SSL_CTX_check_private_key.DESC; + } + + /** + * Downcall method handle for: + * {@snippet lang = c : * int SSL_CTX_check_private_key(const SSL_CTX *ctx) + * } + */ + public static MethodHandle SSL_CTX_check_private_key$handle() { + return SSL_CTX_check_private_key.HANDLE; + } + + /** + * Address for: + * {@snippet lang = c : * int SSL_CTX_check_private_key(const SSL_CTX *ctx) + * } + */ + public static MemorySegment SSL_CTX_check_private_key$address() { + return SSL_CTX_check_private_key.ADDR; + } + + /** + * {@snippet lang = c : * int SSL_CTX_check_private_key(const SSL_CTX *ctx) * } */ public static int SSL_CTX_check_private_key(MemorySegment ctx) { - var mh$ = SSL_CTX_check_private_key$MH(); + var mh$ = SSL_CTX_check_private_key.HANDLE; try { if (TRACE_DOWNCALLS) { traceDowncall("SSL_CTX_check_private_key", ctx); } return (int) mh$.invokeExact(ctx); } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); + throw new AssertionError("should not reach here", ex$); } } - private static MethodHandle SSL_CTX_set_session_id_context$MH() { - class Holder { - static final FunctionDescriptor DESC = FunctionDescriptor.of( - openssl_h.C_INT, - openssl_h.C_POINTER, - openssl_h.C_POINTER, - openssl_h.C_INT - ); - - static final MethodHandle MH = Linker.nativeLinker().downcallHandle( - openssl_h.findOrThrow("SSL_CTX_set_session_id_context"), - DESC); - } - return Holder.MH; + private static class SSL_CTX_set_session_id_context { + public static final FunctionDescriptor DESC = + FunctionDescriptor.of(openssl_h.C_INT, openssl_h.C_POINTER, openssl_h.C_POINTER, openssl_h.C_INT); + + public static final MemorySegment ADDR = openssl_h.findOrThrow("SSL_CTX_set_session_id_context"); + + public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); } /** - * {@snippet lang=c : - * int SSL_CTX_set_session_id_context(SSL_CTX *ctx, const unsigned char *sid_ctx, unsigned int sid_ctx_len) + * Function descriptor for: + * {@snippet lang = c + * : * int SSL_CTX_set_session_id_context(SSL_CTX *ctx, const unsigned char *sid_ctx, unsigned int sid_ctx_len) + * } + */ + public static FunctionDescriptor SSL_CTX_set_session_id_context$descriptor() { + return SSL_CTX_set_session_id_context.DESC; + } + + /** + * Downcall method handle for: + * {@snippet lang = c + * : * int SSL_CTX_set_session_id_context(SSL_CTX *ctx, const unsigned char *sid_ctx, unsigned int sid_ctx_len) + * } + */ + public static MethodHandle SSL_CTX_set_session_id_context$handle() { + return SSL_CTX_set_session_id_context.HANDLE; + } + + /** + * Address for: + * {@snippet lang = c + * : * int SSL_CTX_set_session_id_context(SSL_CTX *ctx, const unsigned char *sid_ctx, unsigned int sid_ctx_len) + * } + */ + public static MemorySegment SSL_CTX_set_session_id_context$address() { + return SSL_CTX_set_session_id_context.ADDR; + } + + /** + * {@snippet lang = c + * : * int SSL_CTX_set_session_id_context(SSL_CTX *ctx, const unsigned char *sid_ctx, unsigned int sid_ctx_len) * } */ public static int SSL_CTX_set_session_id_context(MemorySegment ctx, MemorySegment sid_ctx, int sid_ctx_len) { - var mh$ = SSL_CTX_set_session_id_context$MH(); + var mh$ = SSL_CTX_set_session_id_context.HANDLE; try { if (TRACE_DOWNCALLS) { traceDowncall("SSL_CTX_set_session_id_context", ctx, sid_ctx, sid_ctx_len); } return (int) mh$.invokeExact(ctx, sid_ctx, sid_ctx_len); } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); + throw new AssertionError("should not reach here", ex$); } } - private static MethodHandle SSL_new$MH() { - class Holder { - static final FunctionDescriptor DESC = FunctionDescriptor.of( - openssl_h.C_POINTER, - openssl_h.C_POINTER - ); - - static final MethodHandle MH = Linker.nativeLinker().downcallHandle( - openssl_h.findOrThrow("SSL_new"), - DESC); - } - return Holder.MH; + private static class SSL_new { + public static final FunctionDescriptor DESC = FunctionDescriptor.of(openssl_h.C_POINTER, openssl_h.C_POINTER); + + public static final MemorySegment ADDR = openssl_h.findOrThrow("SSL_new"); + + public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); } /** - * {@snippet lang=c : - * SSL *SSL_new(SSL_CTX *ctx) + * Function descriptor for: + * {@snippet lang = c : * SSL *SSL_new(SSL_CTX *ctx) + * } + */ + public static FunctionDescriptor SSL_new$descriptor() { + return SSL_new.DESC; + } + + /** + * Downcall method handle for: + * {@snippet lang = c : * SSL *SSL_new(SSL_CTX *ctx) + * } + */ + public static MethodHandle SSL_new$handle() { + return SSL_new.HANDLE; + } + + /** + * Address for: + * {@snippet lang = c : * SSL *SSL_new(SSL_CTX *ctx) + * } + */ + public static MemorySegment SSL_new$address() { + return SSL_new.ADDR; + } + + /** + * {@snippet lang = c : * SSL *SSL_new(SSL_CTX *ctx) * } */ public static MemorySegment SSL_new(MemorySegment ctx) { - var mh$ = SSL_new$MH(); + var mh$ = SSL_new.HANDLE; try { if (TRACE_DOWNCALLS) { traceDowncall("SSL_new", ctx); } return (MemorySegment) mh$.invokeExact(ctx); } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); + throw new AssertionError("should not reach here", ex$); } } - private static MethodHandle SSL_free$MH() { - class Holder { - static final FunctionDescriptor DESC = FunctionDescriptor.ofVoid( - openssl_h.C_POINTER - ); - - static final MethodHandle MH = Linker.nativeLinker().downcallHandle( - openssl_h.findOrThrow("SSL_free"), - DESC); - } - return Holder.MH; + private static class SSL_free { + public static final FunctionDescriptor DESC = FunctionDescriptor.ofVoid(openssl_h.C_POINTER); + + public static final MemorySegment ADDR = openssl_h.findOrThrow("SSL_free"); + + public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); } /** - * {@snippet lang=c : - * void SSL_free(SSL *ssl) + * Function descriptor for: + * {@snippet lang = c : * void SSL_free(SSL *ssl) + * } + */ + public static FunctionDescriptor SSL_free$descriptor() { + return SSL_free.DESC; + } + + /** + * Downcall method handle for: + * {@snippet lang = c : * void SSL_free(SSL *ssl) + * } + */ + public static MethodHandle SSL_free$handle() { + return SSL_free.HANDLE; + } + + /** + * Address for: + * {@snippet lang = c : * void SSL_free(SSL *ssl) + * } + */ + public static MemorySegment SSL_free$address() { + return SSL_free.ADDR; + } + + /** + * {@snippet lang = c : * void SSL_free(SSL *ssl) * } */ public static void SSL_free(MemorySegment ssl) { - var mh$ = SSL_free$MH(); + var mh$ = SSL_free.HANDLE; try { if (TRACE_DOWNCALLS) { traceDowncall("SSL_free", ssl); } mh$.invokeExact(ssl); } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); + throw new AssertionError("should not reach here", ex$); } } - private static MethodHandle SSL_read$MH() { - class Holder { - static final FunctionDescriptor DESC = FunctionDescriptor.of( - openssl_h.C_INT, - openssl_h.C_POINTER, - openssl_h.C_POINTER, - openssl_h.C_INT - ); - - static final MethodHandle MH = Linker.nativeLinker().downcallHandle( - openssl_h.findOrThrow("SSL_read"), - DESC); - } - return Holder.MH; + private static class SSL_read { + public static final FunctionDescriptor DESC = + FunctionDescriptor.of(openssl_h.C_INT, openssl_h.C_POINTER, openssl_h.C_POINTER, openssl_h.C_INT); + + public static final MemorySegment ADDR = openssl_h.findOrThrow("SSL_read"); + + public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); } /** - * {@snippet lang=c : - * int SSL_read(SSL *ssl, void *buf, int num) + * Function descriptor for: + * {@snippet lang = c : * int SSL_read(SSL *ssl, void *buf, int num) + * } + */ + public static FunctionDescriptor SSL_read$descriptor() { + return SSL_read.DESC; + } + + /** + * Downcall method handle for: + * {@snippet lang = c : * int SSL_read(SSL *ssl, void *buf, int num) + * } + */ + public static MethodHandle SSL_read$handle() { + return SSL_read.HANDLE; + } + + /** + * Address for: + * {@snippet lang = c : * int SSL_read(SSL *ssl, void *buf, int num) + * } + */ + public static MemorySegment SSL_read$address() { + return SSL_read.ADDR; + } + + /** + * {@snippet lang = c : * int SSL_read(SSL *ssl, void *buf, int num) * } */ public static int SSL_read(MemorySegment ssl, MemorySegment buf, int num) { - var mh$ = SSL_read$MH(); + var mh$ = SSL_read.HANDLE; try { if (TRACE_DOWNCALLS) { traceDowncall("SSL_read", ssl, buf, num); } return (int) mh$.invokeExact(ssl, buf, num); } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); + throw new AssertionError("should not reach here", ex$); } } - private static MethodHandle SSL_write$MH() { - class Holder { - static final FunctionDescriptor DESC = FunctionDescriptor.of( - openssl_h.C_INT, - openssl_h.C_POINTER, - openssl_h.C_POINTER, - openssl_h.C_INT - ); - - static final MethodHandle MH = Linker.nativeLinker().downcallHandle( - openssl_h.findOrThrow("SSL_write"), - DESC); - } - return Holder.MH; + private static class SSL_write { + public static final FunctionDescriptor DESC = + FunctionDescriptor.of(openssl_h.C_INT, openssl_h.C_POINTER, openssl_h.C_POINTER, openssl_h.C_INT); + + public static final MemorySegment ADDR = openssl_h.findOrThrow("SSL_write"); + + public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); } /** - * {@snippet lang=c : - * int SSL_write(SSL *ssl, const void *buf, int num) + * Function descriptor for: + * {@snippet lang = c : * int SSL_write(SSL *ssl, const void *buf, int num) + * } + */ + public static FunctionDescriptor SSL_write$descriptor() { + return SSL_write.DESC; + } + + /** + * Downcall method handle for: + * {@snippet lang = c : * int SSL_write(SSL *ssl, const void *buf, int num) + * } + */ + public static MethodHandle SSL_write$handle() { + return SSL_write.HANDLE; + } + + /** + * Address for: + * {@snippet lang = c : * int SSL_write(SSL *ssl, const void *buf, int num) + * } + */ + public static MemorySegment SSL_write$address() { + return SSL_write.ADDR; + } + + /** + * {@snippet lang = c : * int SSL_write(SSL *ssl, const void *buf, int num) * } */ public static int SSL_write(MemorySegment ssl, MemorySegment buf, int num) { - var mh$ = SSL_write$MH(); + var mh$ = SSL_write.HANDLE; try { if (TRACE_DOWNCALLS) { traceDowncall("SSL_write", ssl, buf, num); } return (int) mh$.invokeExact(ssl, buf, num); } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); + throw new AssertionError("should not reach here", ex$); } } - private static MethodHandle SSL_CTX_ctrl$MH() { - class Holder { - static final FunctionDescriptor DESC = FunctionDescriptor.of( - openssl_h.C_LONG, - openssl_h.C_POINTER, - openssl_h.C_INT, - openssl_h.C_LONG, - openssl_h.C_POINTER - ); - - static final MethodHandle MH = Linker.nativeLinker().downcallHandle( - openssl_h.findOrThrow("SSL_CTX_ctrl"), - DESC); - } - return Holder.MH; + private static class SSL_CTX_ctrl { + public static final FunctionDescriptor DESC = FunctionDescriptor.of(openssl_h.C_LONG, openssl_h.C_POINTER, + openssl_h.C_INT, openssl_h.C_LONG, openssl_h.C_POINTER); + + public static final MemorySegment ADDR = openssl_h.findOrThrow("SSL_CTX_ctrl"); + + public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); } /** - * {@snippet lang=c : - * long SSL_CTX_ctrl(SSL_CTX *ctx, int cmd, long larg, void *parg) + * Function descriptor for: + * {@snippet lang = c : * long SSL_CTX_ctrl(SSL_CTX *ctx, int cmd, long larg, void *parg) + * } + */ + public static FunctionDescriptor SSL_CTX_ctrl$descriptor() { + return SSL_CTX_ctrl.DESC; + } + + /** + * Downcall method handle for: + * {@snippet lang = c : * long SSL_CTX_ctrl(SSL_CTX *ctx, int cmd, long larg, void *parg) + * } + */ + public static MethodHandle SSL_CTX_ctrl$handle() { + return SSL_CTX_ctrl.HANDLE; + } + + /** + * Address for: + * {@snippet lang = c : * long SSL_CTX_ctrl(SSL_CTX *ctx, int cmd, long larg, void *parg) + * } + */ + public static MemorySegment SSL_CTX_ctrl$address() { + return SSL_CTX_ctrl.ADDR; + } + + /** + * {@snippet lang = c : * long SSL_CTX_ctrl(SSL_CTX *ctx, int cmd, long larg, void *parg) * } */ public static long SSL_CTX_ctrl(MemorySegment ctx, int cmd, long larg, MemorySegment parg) { - var mh$ = SSL_CTX_ctrl$MH(); + var mh$ = SSL_CTX_ctrl.HANDLE; try { if (TRACE_DOWNCALLS) { traceDowncall("SSL_CTX_ctrl", ctx, cmd, larg, parg); } return (long) mh$.invokeExact(ctx, cmd, larg, parg); } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); + throw new AssertionError("should not reach here", ex$); } } - private static MethodHandle SSL_ctrl$MH() { - class Holder { - static final FunctionDescriptor DESC = FunctionDescriptor.of( - openssl_h.C_LONG, - openssl_h.C_POINTER, - openssl_h.C_INT, - openssl_h.C_LONG, - openssl_h.C_POINTER - ); - - static final MethodHandle MH = Linker.nativeLinker().downcallHandle( - openssl_h.findOrThrow("SSL_ctrl"), - DESC); - } - return Holder.MH; + private static class SSL_get_version { + public static final FunctionDescriptor DESC = FunctionDescriptor.of(openssl_h.C_POINTER, openssl_h.C_POINTER); + + public static final MemorySegment ADDR = openssl_h.findOrThrow("SSL_get_version"); + + public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); } /** - * {@snippet lang=c : - * long SSL_ctrl(SSL *ssl, int cmd, long larg, void *parg) + * Function descriptor for: + * {@snippet lang = c : * const char *SSL_get_version(const SSL *s) * } */ - public static long SSL_ctrl(MemorySegment ssl, int cmd, long larg, MemorySegment parg) { - var mh$ = SSL_ctrl$MH(); - try { - if (TRACE_DOWNCALLS) { - traceDowncall("SSL_ctrl", ssl, cmd, larg, parg); - } - return (long) mh$.invokeExact(ssl, cmd, larg, parg); - } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); - } + public static FunctionDescriptor SSL_get_version$descriptor() { + return SSL_get_version.DESC; } - private static MethodHandle SSL_get_version$MH() { - class Holder { - static final FunctionDescriptor DESC = FunctionDescriptor.of( - openssl_h.C_POINTER, - openssl_h.C_POINTER - ); - - static final MethodHandle MH = Linker.nativeLinker().downcallHandle( - openssl_h.findOrThrow("SSL_get_version"), - DESC); - } - return Holder.MH; + /** + * Downcall method handle for: + * {@snippet lang = c : * const char *SSL_get_version(const SSL *s) + * } + */ + public static MethodHandle SSL_get_version$handle() { + return SSL_get_version.HANDLE; } /** - * {@snippet lang=c : - * const char *SSL_get_version(const SSL *s) + * Address for: + * {@snippet lang = c : * const char *SSL_get_version(const SSL *s) + * } + */ + public static MemorySegment SSL_get_version$address() { + return SSL_get_version.ADDR; + } + + /** + * {@snippet lang = c : * const char *SSL_get_version(const SSL *s) * } */ public static MemorySegment SSL_get_version(MemorySegment s) { - var mh$ = SSL_get_version$MH(); + var mh$ = SSL_get_version.HANDLE; try { if (TRACE_DOWNCALLS) { traceDowncall("SSL_get_version", s); } return (MemorySegment) mh$.invokeExact(s); } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); + throw new AssertionError("should not reach here", ex$); } } - private static MethodHandle TLS_server_method$MH() { - class Holder { - static final FunctionDescriptor DESC = FunctionDescriptor.of( - openssl_h.C_POINTER ); + private static class TLS_server_method { + public static final FunctionDescriptor DESC = FunctionDescriptor.of(openssl_h.C_POINTER); - static final MethodHandle MH = Linker.nativeLinker().downcallHandle( - openssl_h.findOrThrow("TLS_server_method"), - DESC); - } - return Holder.MH; + public static final MemorySegment ADDR = openssl_h.findOrThrow("TLS_server_method"); + + public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); } /** - * {@snippet lang=c : - * const SSL_METHOD *TLS_server_method(void) + * Function descriptor for: + * {@snippet lang = c : * const SSL_METHOD *TLS_server_method() + * } + */ + public static FunctionDescriptor TLS_server_method$descriptor() { + return TLS_server_method.DESC; + } + + /** + * Downcall method handle for: + * {@snippet lang = c : * const SSL_METHOD *TLS_server_method() + * } + */ + public static MethodHandle TLS_server_method$handle() { + return TLS_server_method.HANDLE; + } + + /** + * Address for: + * {@snippet lang = c : * const SSL_METHOD *TLS_server_method() + * } + */ + public static MemorySegment TLS_server_method$address() { + return TLS_server_method.ADDR; + } + + /** + * {@snippet lang = c : * const SSL_METHOD *TLS_server_method() * } */ public static MemorySegment TLS_server_method() { - var mh$ = TLS_server_method$MH(); + var mh$ = TLS_server_method.HANDLE; try { if (TRACE_DOWNCALLS) { traceDowncall("TLS_server_method"); } return (MemorySegment) mh$.invokeExact(); } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); + throw new AssertionError("should not reach here", ex$); } } - private static MethodHandle SSL_get_ciphers$MH() { - class Holder { - static final FunctionDescriptor DESC = FunctionDescriptor.of( - openssl_h.C_POINTER, - openssl_h.C_POINTER - ); - - static final MethodHandle MH = Linker.nativeLinker().downcallHandle( - openssl_h.findOrThrow("SSL_get_ciphers"), - DESC); - } - return Holder.MH; + private static class SSL_get_ciphers { + public static final FunctionDescriptor DESC = FunctionDescriptor.of(openssl_h.C_POINTER, openssl_h.C_POINTER); + + public static final MemorySegment ADDR = openssl_h.findOrThrow("SSL_get_ciphers"); + + public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); } /** - * {@snippet lang=c : - * struct stack_st_SSL_CIPHER *SSL_get_ciphers(const SSL *s) + * Function descriptor for: + * {@snippet lang = c : * struct stack_st_SSL_CIPHER *SSL_get_ciphers(const SSL *s) + * } + */ + public static FunctionDescriptor SSL_get_ciphers$descriptor() { + return SSL_get_ciphers.DESC; + } + + /** + * Downcall method handle for: + * {@snippet lang = c : * struct stack_st_SSL_CIPHER *SSL_get_ciphers(const SSL *s) + * } + */ + public static MethodHandle SSL_get_ciphers$handle() { + return SSL_get_ciphers.HANDLE; + } + + /** + * Address for: + * {@snippet lang = c : * struct stack_st_SSL_CIPHER *SSL_get_ciphers(const SSL *s) + * } + */ + public static MemorySegment SSL_get_ciphers$address() { + return SSL_get_ciphers.ADDR; + } + + /** + * {@snippet lang = c : * struct stack_st_SSL_CIPHER *SSL_get_ciphers(const SSL *s) * } */ public static MemorySegment SSL_get_ciphers(MemorySegment s) { - var mh$ = SSL_get_ciphers$MH(); + var mh$ = SSL_get_ciphers.HANDLE; try { if (TRACE_DOWNCALLS) { traceDowncall("SSL_get_ciphers", s); } return (MemorySegment) mh$.invokeExact(s); } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); + throw new AssertionError("should not reach here", ex$); } } - private static MethodHandle SSL_CTX_get_ciphers$MH() { - class Holder { - static final FunctionDescriptor DESC = FunctionDescriptor.of( - openssl_h.C_POINTER, - openssl_h.C_POINTER - ); - - static final MethodHandle MH = Linker.nativeLinker().downcallHandle( - openssl_h.findOrThrow("SSL_CTX_get_ciphers"), - DESC); - } - return Holder.MH; + private static class SSL_CTX_get_ciphers { + public static final FunctionDescriptor DESC = FunctionDescriptor.of(openssl_h.C_POINTER, openssl_h.C_POINTER); + + public static final MemorySegment ADDR = openssl_h.findOrThrow("SSL_CTX_get_ciphers"); + + public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); } /** - * {@snippet lang=c : - * struct stack_st_SSL_CIPHER *SSL_CTX_get_ciphers(const SSL_CTX *ctx) + * Function descriptor for: + * {@snippet lang = c : * struct stack_st_SSL_CIPHER *SSL_CTX_get_ciphers(const SSL_CTX *ctx) + * } + */ + public static FunctionDescriptor SSL_CTX_get_ciphers$descriptor() { + return SSL_CTX_get_ciphers.DESC; + } + + /** + * Downcall method handle for: + * {@snippet lang = c : * struct stack_st_SSL_CIPHER *SSL_CTX_get_ciphers(const SSL_CTX *ctx) + * } + */ + public static MethodHandle SSL_CTX_get_ciphers$handle() { + return SSL_CTX_get_ciphers.HANDLE; + } + + /** + * Address for: + * {@snippet lang = c : * struct stack_st_SSL_CIPHER *SSL_CTX_get_ciphers(const SSL_CTX *ctx) + * } + */ + public static MemorySegment SSL_CTX_get_ciphers$address() { + return SSL_CTX_get_ciphers.ADDR; + } + + /** + * {@snippet lang = c : * struct stack_st_SSL_CIPHER *SSL_CTX_get_ciphers(const SSL_CTX *ctx) * } */ public static MemorySegment SSL_CTX_get_ciphers(MemorySegment ctx) { - var mh$ = SSL_CTX_get_ciphers$MH(); + var mh$ = SSL_CTX_get_ciphers.HANDLE; try { if (TRACE_DOWNCALLS) { traceDowncall("SSL_CTX_get_ciphers", ctx); } return (MemorySegment) mh$.invokeExact(ctx); } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); + throw new AssertionError("should not reach here", ex$); } } - private static MethodHandle SSL_do_handshake$MH() { - class Holder { - static final FunctionDescriptor DESC = FunctionDescriptor.of( - openssl_h.C_INT, - openssl_h.C_POINTER - ); - - static final MethodHandle MH = Linker.nativeLinker().downcallHandle( - openssl_h.findOrThrow("SSL_do_handshake"), - DESC); - } - return Holder.MH; + private static class SSL_do_handshake { + public static final FunctionDescriptor DESC = FunctionDescriptor.of(openssl_h.C_INT, openssl_h.C_POINTER); + + public static final MemorySegment ADDR = openssl_h.findOrThrow("SSL_do_handshake"); + + public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); } /** - * {@snippet lang=c : - * int SSL_do_handshake(SSL *s) + * Function descriptor for: + * {@snippet lang = c : * int SSL_do_handshake(SSL *s) + * } + */ + public static FunctionDescriptor SSL_do_handshake$descriptor() { + return SSL_do_handshake.DESC; + } + + /** + * Downcall method handle for: + * {@snippet lang = c : * int SSL_do_handshake(SSL *s) + * } + */ + public static MethodHandle SSL_do_handshake$handle() { + return SSL_do_handshake.HANDLE; + } + + /** + * Address for: + * {@snippet lang = c : * int SSL_do_handshake(SSL *s) + * } + */ + public static MemorySegment SSL_do_handshake$address() { + return SSL_do_handshake.ADDR; + } + + /** + * {@snippet lang = c : * int SSL_do_handshake(SSL *s) * } */ public static int SSL_do_handshake(MemorySegment s) { - var mh$ = SSL_do_handshake$MH(); + var mh$ = SSL_do_handshake.HANDLE; try { if (TRACE_DOWNCALLS) { traceDowncall("SSL_do_handshake", s); } return (int) mh$.invokeExact(s); } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); + throw new AssertionError("should not reach here", ex$); } } - private static MethodHandle SSL_renegotiate$MH() { - class Holder { - static final FunctionDescriptor DESC = FunctionDescriptor.of( - openssl_h.C_INT, - openssl_h.C_POINTER - ); - - static final MethodHandle MH = Linker.nativeLinker().downcallHandle( - openssl_h.findOrThrow("SSL_renegotiate"), - DESC); - } - return Holder.MH; + private static class SSL_renegotiate { + public static final FunctionDescriptor DESC = FunctionDescriptor.of(openssl_h.C_INT, openssl_h.C_POINTER); + + public static final MemorySegment ADDR = openssl_h.findOrThrow("SSL_renegotiate"); + + public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); } /** - * {@snippet lang=c : - * int SSL_renegotiate(SSL *s) + * Function descriptor for: + * {@snippet lang = c : * int SSL_renegotiate(SSL *s) + * } + */ + public static FunctionDescriptor SSL_renegotiate$descriptor() { + return SSL_renegotiate.DESC; + } + + /** + * Downcall method handle for: + * {@snippet lang = c : * int SSL_renegotiate(SSL *s) + * } + */ + public static MethodHandle SSL_renegotiate$handle() { + return SSL_renegotiate.HANDLE; + } + + /** + * Address for: + * {@snippet lang = c : * int SSL_renegotiate(SSL *s) + * } + */ + public static MemorySegment SSL_renegotiate$address() { + return SSL_renegotiate.ADDR; + } + + /** + * {@snippet lang = c : * int SSL_renegotiate(SSL *s) * } */ public static int SSL_renegotiate(MemorySegment s) { - var mh$ = SSL_renegotiate$MH(); + var mh$ = SSL_renegotiate.HANDLE; try { if (TRACE_DOWNCALLS) { traceDowncall("SSL_renegotiate", s); } return (int) mh$.invokeExact(s); } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); + throw new AssertionError("should not reach here", ex$); } } - private static MethodHandle SSL_renegotiate_pending$MH() { - class Holder { - static final FunctionDescriptor DESC = FunctionDescriptor.of( - openssl_h.C_INT, - openssl_h.C_POINTER - ); - - static final MethodHandle MH = Linker.nativeLinker().downcallHandle( - openssl_h.findOrThrow("SSL_renegotiate_pending"), - DESC); - } - return Holder.MH; + private static class SSL_renegotiate_pending { + public static final FunctionDescriptor DESC = FunctionDescriptor.of(openssl_h.C_INT, openssl_h.C_POINTER); + + public static final MemorySegment ADDR = openssl_h.findOrThrow("SSL_renegotiate_pending"); + + public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); } /** - * {@snippet lang=c : - * int SSL_renegotiate_pending(const SSL *s) + * Function descriptor for: + * {@snippet lang = c : * int SSL_renegotiate_pending(const SSL *s) + * } + */ + public static FunctionDescriptor SSL_renegotiate_pending$descriptor() { + return SSL_renegotiate_pending.DESC; + } + + /** + * Downcall method handle for: + * {@snippet lang = c : * int SSL_renegotiate_pending(const SSL *s) + * } + */ + public static MethodHandle SSL_renegotiate_pending$handle() { + return SSL_renegotiate_pending.HANDLE; + } + + /** + * Address for: + * {@snippet lang = c : * int SSL_renegotiate_pending(const SSL *s) + * } + */ + public static MemorySegment SSL_renegotiate_pending$address() { + return SSL_renegotiate_pending.ADDR; + } + + /** + * {@snippet lang = c : * int SSL_renegotiate_pending(const SSL *s) * } */ public static int SSL_renegotiate_pending(MemorySegment s) { - var mh$ = SSL_renegotiate_pending$MH(); + var mh$ = SSL_renegotiate_pending.HANDLE; try { if (TRACE_DOWNCALLS) { traceDowncall("SSL_renegotiate_pending", s); } return (int) mh$.invokeExact(s); } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); + throw new AssertionError("should not reach here", ex$); } } - private static MethodHandle SSL_shutdown$MH() { - class Holder { - static final FunctionDescriptor DESC = FunctionDescriptor.of( - openssl_h.C_INT, - openssl_h.C_POINTER - ); - - static final MethodHandle MH = Linker.nativeLinker().downcallHandle( - openssl_h.findOrThrow("SSL_shutdown"), - DESC); - } - return Holder.MH; + private static class SSL_shutdown { + public static final FunctionDescriptor DESC = FunctionDescriptor.of(openssl_h.C_INT, openssl_h.C_POINTER); + + public static final MemorySegment ADDR = openssl_h.findOrThrow("SSL_shutdown"); + + public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); } /** - * {@snippet lang=c : - * int SSL_shutdown(SSL *s) + * Function descriptor for: + * {@snippet lang = c : * int SSL_shutdown(SSL *s) + * } + */ + public static FunctionDescriptor SSL_shutdown$descriptor() { + return SSL_shutdown.DESC; + } + + /** + * Downcall method handle for: + * {@snippet lang = c : * int SSL_shutdown(SSL *s) + * } + */ + public static MethodHandle SSL_shutdown$handle() { + return SSL_shutdown.HANDLE; + } + + /** + * Address for: + * {@snippet lang = c : * int SSL_shutdown(SSL *s) + * } + */ + public static MemorySegment SSL_shutdown$address() { + return SSL_shutdown.ADDR; + } + + /** + * {@snippet lang = c : * int SSL_shutdown(SSL *s) * } */ public static int SSL_shutdown(MemorySegment s) { - var mh$ = SSL_shutdown$MH(); + var mh$ = SSL_shutdown.HANDLE; try { if (TRACE_DOWNCALLS) { traceDowncall("SSL_shutdown", s); } return (int) mh$.invokeExact(s); } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); + throw new AssertionError("should not reach here", ex$); } } - private static MethodHandle SSL_verify_client_post_handshake$MH() { - class Holder { - static final FunctionDescriptor DESC = FunctionDescriptor.of( - openssl_h.C_INT, - openssl_h.C_POINTER - ); - - static final MethodHandle MH = Linker.nativeLinker().downcallHandle( - openssl_h.findOrThrow("SSL_verify_client_post_handshake"), - DESC); - } - return Holder.MH; + private static class SSL_verify_client_post_handshake { + public static final FunctionDescriptor DESC = FunctionDescriptor.of(openssl_h.C_INT, openssl_h.C_POINTER); + + public static final MemorySegment ADDR = openssl_h.findOrThrow("SSL_verify_client_post_handshake"); + + public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); } /** - * {@snippet lang=c : - * int SSL_verify_client_post_handshake(SSL *s) + * Function descriptor for: + * {@snippet lang = c : * int SSL_verify_client_post_handshake(SSL *s) + * } + */ + public static FunctionDescriptor SSL_verify_client_post_handshake$descriptor() { + return SSL_verify_client_post_handshake.DESC; + } + + /** + * Downcall method handle for: + * {@snippet lang = c : * int SSL_verify_client_post_handshake(SSL *s) + * } + */ + public static MethodHandle SSL_verify_client_post_handshake$handle() { + return SSL_verify_client_post_handshake.HANDLE; + } + + /** + * Address for: + * {@snippet lang = c : * int SSL_verify_client_post_handshake(SSL *s) + * } + */ + public static MemorySegment SSL_verify_client_post_handshake$address() { + return SSL_verify_client_post_handshake.ADDR; + } + + /** + * {@snippet lang = c : * int SSL_verify_client_post_handshake(SSL *s) * } */ public static int SSL_verify_client_post_handshake(MemorySegment s) { - var mh$ = SSL_verify_client_post_handshake$MH(); + var mh$ = SSL_verify_client_post_handshake.HANDLE; try { if (TRACE_DOWNCALLS) { traceDowncall("SSL_verify_client_post_handshake", s); } return (int) mh$.invokeExact(s); } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); + throw new AssertionError("should not reach here", ex$); } } - private static MethodHandle SSL_CTX_set_client_CA_list$MH() { - class Holder { - static final FunctionDescriptor DESC = FunctionDescriptor.ofVoid( - openssl_h.C_POINTER, - openssl_h.C_POINTER - ); - - static final MethodHandle MH = Linker.nativeLinker().downcallHandle( - openssl_h.findOrThrow("SSL_CTX_set_client_CA_list"), - DESC); - } - return Holder.MH; + private static class SSL_CTX_set_client_CA_list { + public static final FunctionDescriptor DESC = + FunctionDescriptor.ofVoid(openssl_h.C_POINTER, openssl_h.C_POINTER); + + public static final MemorySegment ADDR = openssl_h.findOrThrow("SSL_CTX_set_client_CA_list"); + + public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); } /** - * {@snippet lang=c : - * void SSL_CTX_set_client_CA_list(SSL_CTX *ctx, struct stack_st_X509_NAME *name_list) + * Function descriptor for: + * {@snippet lang = c : * void SSL_CTX_set_client_CA_list(SSL_CTX *ctx, struct stack_st_X509_NAME *name_list) + * } + */ + public static FunctionDescriptor SSL_CTX_set_client_CA_list$descriptor() { + return SSL_CTX_set_client_CA_list.DESC; + } + + /** + * Downcall method handle for: + * {@snippet lang = c : * void SSL_CTX_set_client_CA_list(SSL_CTX *ctx, struct stack_st_X509_NAME *name_list) + * } + */ + public static MethodHandle SSL_CTX_set_client_CA_list$handle() { + return SSL_CTX_set_client_CA_list.HANDLE; + } + + /** + * Address for: + * {@snippet lang = c : * void SSL_CTX_set_client_CA_list(SSL_CTX *ctx, struct stack_st_X509_NAME *name_list) + * } + */ + public static MemorySegment SSL_CTX_set_client_CA_list$address() { + return SSL_CTX_set_client_CA_list.ADDR; + } + + /** + * {@snippet lang = c : * void SSL_CTX_set_client_CA_list(SSL_CTX *ctx, struct stack_st_X509_NAME *name_list) * } */ public static void SSL_CTX_set_client_CA_list(MemorySegment ctx, MemorySegment name_list) { - var mh$ = SSL_CTX_set_client_CA_list$MH(); + var mh$ = SSL_CTX_set_client_CA_list.HANDLE; try { if (TRACE_DOWNCALLS) { traceDowncall("SSL_CTX_set_client_CA_list", ctx, name_list); } mh$.invokeExact(ctx, name_list); } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); + throw new AssertionError("should not reach here", ex$); } } - private static MethodHandle SSL_CTX_get_client_CA_list$MH() { - class Holder { - static final FunctionDescriptor DESC = FunctionDescriptor.of( - openssl_h.C_POINTER, - openssl_h.C_POINTER - ); - - static final MethodHandle MH = Linker.nativeLinker().downcallHandle( - openssl_h.findOrThrow("SSL_CTX_get_client_CA_list"), - DESC); - } - return Holder.MH; + private static class SSL_CTX_get_client_CA_list { + public static final FunctionDescriptor DESC = FunctionDescriptor.of(openssl_h.C_POINTER, openssl_h.C_POINTER); + + public static final MemorySegment ADDR = openssl_h.findOrThrow("SSL_CTX_get_client_CA_list"); + + public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); } /** - * {@snippet lang=c : - * struct stack_st_X509_NAME *SSL_CTX_get_client_CA_list(const SSL_CTX *s) + * Function descriptor for: + * {@snippet lang = c : * struct stack_st_X509_NAME *SSL_CTX_get_client_CA_list(const SSL_CTX *s) + * } + */ + public static FunctionDescriptor SSL_CTX_get_client_CA_list$descriptor() { + return SSL_CTX_get_client_CA_list.DESC; + } + + /** + * Downcall method handle for: + * {@snippet lang = c : * struct stack_st_X509_NAME *SSL_CTX_get_client_CA_list(const SSL_CTX *s) + * } + */ + public static MethodHandle SSL_CTX_get_client_CA_list$handle() { + return SSL_CTX_get_client_CA_list.HANDLE; + } + + /** + * Address for: + * {@snippet lang = c : * struct stack_st_X509_NAME *SSL_CTX_get_client_CA_list(const SSL_CTX *s) + * } + */ + public static MemorySegment SSL_CTX_get_client_CA_list$address() { + return SSL_CTX_get_client_CA_list.ADDR; + } + + /** + * {@snippet lang = c : * struct stack_st_X509_NAME *SSL_CTX_get_client_CA_list(const SSL_CTX *s) * } */ public static MemorySegment SSL_CTX_get_client_CA_list(MemorySegment s) { - var mh$ = SSL_CTX_get_client_CA_list$MH(); + var mh$ = SSL_CTX_get_client_CA_list.HANDLE; try { if (TRACE_DOWNCALLS) { traceDowncall("SSL_CTX_get_client_CA_list", s); } return (MemorySegment) mh$.invokeExact(s); } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); + throw new AssertionError("should not reach here", ex$); } } - private static MethodHandle SSL_CTX_add_client_CA$MH() { - class Holder { - static final FunctionDescriptor DESC = FunctionDescriptor.of( - openssl_h.C_INT, - openssl_h.C_POINTER, - openssl_h.C_POINTER - ); - - static final MethodHandle MH = Linker.nativeLinker().downcallHandle( - openssl_h.findOrThrow("SSL_CTX_add_client_CA"), - DESC); - } - return Holder.MH; + private static class SSL_CTX_add_client_CA { + public static final FunctionDescriptor DESC = + FunctionDescriptor.of(openssl_h.C_INT, openssl_h.C_POINTER, openssl_h.C_POINTER); + + public static final MemorySegment ADDR = openssl_h.findOrThrow("SSL_CTX_add_client_CA"); + + public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); } /** - * {@snippet lang=c : - * int SSL_CTX_add_client_CA(SSL_CTX *ctx, X509 *x) + * Function descriptor for: + * {@snippet lang = c : * int SSL_CTX_add_client_CA(SSL_CTX *ctx, X509 *x) + * } + */ + public static FunctionDescriptor SSL_CTX_add_client_CA$descriptor() { + return SSL_CTX_add_client_CA.DESC; + } + + /** + * Downcall method handle for: + * {@snippet lang = c : * int SSL_CTX_add_client_CA(SSL_CTX *ctx, X509 *x) + * } + */ + public static MethodHandle SSL_CTX_add_client_CA$handle() { + return SSL_CTX_add_client_CA.HANDLE; + } + + /** + * Address for: + * {@snippet lang = c : * int SSL_CTX_add_client_CA(SSL_CTX *ctx, X509 *x) + * } + */ + public static MemorySegment SSL_CTX_add_client_CA$address() { + return SSL_CTX_add_client_CA.ADDR; + } + + /** + * {@snippet lang = c : * int SSL_CTX_add_client_CA(SSL_CTX *ctx, X509 *x) * } */ public static int SSL_CTX_add_client_CA(MemorySegment ctx, MemorySegment x) { - var mh$ = SSL_CTX_add_client_CA$MH(); + var mh$ = SSL_CTX_add_client_CA.HANDLE; try { if (TRACE_DOWNCALLS) { traceDowncall("SSL_CTX_add_client_CA", ctx, x); } return (int) mh$.invokeExact(ctx, x); } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); + throw new AssertionError("should not reach here", ex$); } } - private static MethodHandle SSL_set_connect_state$MH() { - class Holder { - static final FunctionDescriptor DESC = FunctionDescriptor.ofVoid( - openssl_h.C_POINTER - ); - - static final MethodHandle MH = Linker.nativeLinker().downcallHandle( - openssl_h.findOrThrow("SSL_set_connect_state"), - DESC); - } - return Holder.MH; + private static class SSL_set_connect_state { + public static final FunctionDescriptor DESC = FunctionDescriptor.ofVoid(openssl_h.C_POINTER); + + public static final MemorySegment ADDR = openssl_h.findOrThrow("SSL_set_connect_state"); + + public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); } /** - * {@snippet lang=c : - * void SSL_set_connect_state(SSL *s) + * Function descriptor for: + * {@snippet lang = c : * void SSL_set_connect_state(SSL *s) + * } + */ + public static FunctionDescriptor SSL_set_connect_state$descriptor() { + return SSL_set_connect_state.DESC; + } + + /** + * Downcall method handle for: + * {@snippet lang = c : * void SSL_set_connect_state(SSL *s) + * } + */ + public static MethodHandle SSL_set_connect_state$handle() { + return SSL_set_connect_state.HANDLE; + } + + /** + * Address for: + * {@snippet lang = c : * void SSL_set_connect_state(SSL *s) + * } + */ + public static MemorySegment SSL_set_connect_state$address() { + return SSL_set_connect_state.ADDR; + } + + /** + * {@snippet lang = c : * void SSL_set_connect_state(SSL *s) * } */ public static void SSL_set_connect_state(MemorySegment s) { - var mh$ = SSL_set_connect_state$MH(); + var mh$ = SSL_set_connect_state.HANDLE; try { if (TRACE_DOWNCALLS) { traceDowncall("SSL_set_connect_state", s); } mh$.invokeExact(s); } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); + throw new AssertionError("should not reach here", ex$); } } - private static MethodHandle SSL_set_accept_state$MH() { - class Holder { - static final FunctionDescriptor DESC = FunctionDescriptor.ofVoid( - openssl_h.C_POINTER - ); - - static final MethodHandle MH = Linker.nativeLinker().downcallHandle( - openssl_h.findOrThrow("SSL_set_accept_state"), - DESC); - } - return Holder.MH; + private static class SSL_set_accept_state { + public static final FunctionDescriptor DESC = FunctionDescriptor.ofVoid(openssl_h.C_POINTER); + + public static final MemorySegment ADDR = openssl_h.findOrThrow("SSL_set_accept_state"); + + public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); } /** - * {@snippet lang=c : - * void SSL_set_accept_state(SSL *s) + * Function descriptor for: + * {@snippet lang = c : * void SSL_set_accept_state(SSL *s) + * } + */ + public static FunctionDescriptor SSL_set_accept_state$descriptor() { + return SSL_set_accept_state.DESC; + } + + /** + * Downcall method handle for: + * {@snippet lang = c : * void SSL_set_accept_state(SSL *s) + * } + */ + public static MethodHandle SSL_set_accept_state$handle() { + return SSL_set_accept_state.HANDLE; + } + + /** + * Address for: + * {@snippet lang = c : * void SSL_set_accept_state(SSL *s) + * } + */ + public static MemorySegment SSL_set_accept_state$address() { + return SSL_set_accept_state.ADDR; + } + + /** + * {@snippet lang = c : * void SSL_set_accept_state(SSL *s) * } */ public static void SSL_set_accept_state(MemorySegment s) { - var mh$ = SSL_set_accept_state$MH(); + var mh$ = SSL_set_accept_state.HANDLE; try { if (TRACE_DOWNCALLS) { traceDowncall("SSL_set_accept_state", s); } mh$.invokeExact(s); } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); + throw new AssertionError("should not reach here", ex$); } } - private static MethodHandle SSL_get_privatekey$MH() { - class Holder { - static final FunctionDescriptor DESC = FunctionDescriptor.of( - openssl_h.C_POINTER, - openssl_h.C_POINTER - ); - - static final MethodHandle MH = Linker.nativeLinker().downcallHandle( - openssl_h.findOrThrow("SSL_get_privatekey"), - DESC); - } - return Holder.MH; + private static class SSL_get_privatekey { + public static final FunctionDescriptor DESC = FunctionDescriptor.of(openssl_h.C_POINTER, openssl_h.C_POINTER); + + public static final MemorySegment ADDR = openssl_h.findOrThrow("SSL_get_privatekey"); + + public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); } /** - * {@snippet lang=c : - * struct evp_pkey_st *SSL_get_privatekey(const SSL *ssl) + * Function descriptor for: + * {@snippet lang = c : * struct evp_pkey_st *SSL_get_privatekey(const SSL *ssl) + * } + */ + public static FunctionDescriptor SSL_get_privatekey$descriptor() { + return SSL_get_privatekey.DESC; + } + + /** + * Downcall method handle for: + * {@snippet lang = c : * struct evp_pkey_st *SSL_get_privatekey(const SSL *ssl) + * } + */ + public static MethodHandle SSL_get_privatekey$handle() { + return SSL_get_privatekey.HANDLE; + } + + /** + * Address for: + * {@snippet lang = c : * struct evp_pkey_st *SSL_get_privatekey(const SSL *ssl) + * } + */ + public static MemorySegment SSL_get_privatekey$address() { + return SSL_get_privatekey.ADDR; + } + + /** + * {@snippet lang = c : * struct evp_pkey_st *SSL_get_privatekey(const SSL *ssl) * } */ public static MemorySegment SSL_get_privatekey(MemorySegment ssl) { - var mh$ = SSL_get_privatekey$MH(); + var mh$ = SSL_get_privatekey.HANDLE; try { if (TRACE_DOWNCALLS) { traceDowncall("SSL_get_privatekey", ssl); } return (MemorySegment) mh$.invokeExact(ssl); } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); + throw new AssertionError("should not reach here", ex$); } } - private static MethodHandle SSL_get_shutdown$MH() { - class Holder { - static final FunctionDescriptor DESC = FunctionDescriptor.of( - openssl_h.C_INT, - openssl_h.C_POINTER - ); - - static final MethodHandle MH = Linker.nativeLinker().downcallHandle( - openssl_h.findOrThrow("SSL_get_shutdown"), - DESC); - } - return Holder.MH; + private static class SSL_get_shutdown { + public static final FunctionDescriptor DESC = FunctionDescriptor.of(openssl_h.C_INT, openssl_h.C_POINTER); + + public static final MemorySegment ADDR = openssl_h.findOrThrow("SSL_get_shutdown"); + + public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); } /** - * {@snippet lang=c : - * int SSL_get_shutdown(const SSL *ssl) + * Function descriptor for: + * {@snippet lang = c : * int SSL_get_shutdown(const SSL *ssl) + * } + */ + public static FunctionDescriptor SSL_get_shutdown$descriptor() { + return SSL_get_shutdown.DESC; + } + + /** + * Downcall method handle for: + * {@snippet lang = c : * int SSL_get_shutdown(const SSL *ssl) + * } + */ + public static MethodHandle SSL_get_shutdown$handle() { + return SSL_get_shutdown.HANDLE; + } + + /** + * Address for: + * {@snippet lang = c : * int SSL_get_shutdown(const SSL *ssl) + * } + */ + public static MemorySegment SSL_get_shutdown$address() { + return SSL_get_shutdown.ADDR; + } + + /** + * {@snippet lang = c : * int SSL_get_shutdown(const SSL *ssl) * } */ public static int SSL_get_shutdown(MemorySegment ssl) { - var mh$ = SSL_get_shutdown$MH(); + var mh$ = SSL_get_shutdown.HANDLE; try { if (TRACE_DOWNCALLS) { traceDowncall("SSL_get_shutdown", ssl); } return (int) mh$.invokeExact(ssl); } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); + throw new AssertionError("should not reach here", ex$); } } - private static MethodHandle SSL_CTX_set_default_verify_paths$MH() { - class Holder { - static final FunctionDescriptor DESC = FunctionDescriptor.of( - openssl_h.C_INT, - openssl_h.C_POINTER - ); - - static final MethodHandle MH = Linker.nativeLinker().downcallHandle( - openssl_h.findOrThrow("SSL_CTX_set_default_verify_paths"), - DESC); - } - return Holder.MH; + private static class SSL_CTX_set_default_verify_paths { + public static final FunctionDescriptor DESC = FunctionDescriptor.of(openssl_h.C_INT, openssl_h.C_POINTER); + + public static final MemorySegment ADDR = openssl_h.findOrThrow("SSL_CTX_set_default_verify_paths"); + + public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); } /** - * {@snippet lang=c : - * int SSL_CTX_set_default_verify_paths(SSL_CTX *ctx) + * Function descriptor for: + * {@snippet lang = c : * int SSL_CTX_set_default_verify_paths(SSL_CTX *ctx) + * } + */ + public static FunctionDescriptor SSL_CTX_set_default_verify_paths$descriptor() { + return SSL_CTX_set_default_verify_paths.DESC; + } + + /** + * Downcall method handle for: + * {@snippet lang = c : * int SSL_CTX_set_default_verify_paths(SSL_CTX *ctx) + * } + */ + public static MethodHandle SSL_CTX_set_default_verify_paths$handle() { + return SSL_CTX_set_default_verify_paths.HANDLE; + } + + /** + * Address for: + * {@snippet lang = c : * int SSL_CTX_set_default_verify_paths(SSL_CTX *ctx) + * } + */ + public static MemorySegment SSL_CTX_set_default_verify_paths$address() { + return SSL_CTX_set_default_verify_paths.ADDR; + } + + /** + * {@snippet lang = c : * int SSL_CTX_set_default_verify_paths(SSL_CTX *ctx) * } */ public static int SSL_CTX_set_default_verify_paths(MemorySegment ctx) { - var mh$ = SSL_CTX_set_default_verify_paths$MH(); + var mh$ = SSL_CTX_set_default_verify_paths.HANDLE; try { if (TRACE_DOWNCALLS) { traceDowncall("SSL_CTX_set_default_verify_paths", ctx); } return (int) mh$.invokeExact(ctx); } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); + throw new AssertionError("should not reach here", ex$); } } - private static MethodHandle SSL_CTX_load_verify_locations$MH() { - class Holder { - static final FunctionDescriptor DESC = FunctionDescriptor.of( - openssl_h.C_INT, - openssl_h.C_POINTER, - openssl_h.C_POINTER, - openssl_h.C_POINTER - ); - - static final MethodHandle MH = Linker.nativeLinker().downcallHandle( - openssl_h.findOrThrow("SSL_CTX_load_verify_locations"), - DESC); - } - return Holder.MH; + private static class SSL_CTX_load_verify_locations { + public static final FunctionDescriptor DESC = + FunctionDescriptor.of(openssl_h.C_INT, openssl_h.C_POINTER, openssl_h.C_POINTER, openssl_h.C_POINTER); + + public static final MemorySegment ADDR = openssl_h.findOrThrow("SSL_CTX_load_verify_locations"); + + public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); } /** - * {@snippet lang=c : - * int SSL_CTX_load_verify_locations(SSL_CTX *ctx, const char *CAfile, const char *CApath) + * Function descriptor for: + * {@snippet lang = c : * int SSL_CTX_load_verify_locations(SSL_CTX *ctx, const char *CAfile, const char *CApath) + * } + */ + public static FunctionDescriptor SSL_CTX_load_verify_locations$descriptor() { + return SSL_CTX_load_verify_locations.DESC; + } + + /** + * Downcall method handle for: + * {@snippet lang = c : * int SSL_CTX_load_verify_locations(SSL_CTX *ctx, const char *CAfile, const char *CApath) + * } + */ + public static MethodHandle SSL_CTX_load_verify_locations$handle() { + return SSL_CTX_load_verify_locations.HANDLE; + } + + /** + * Address for: + * {@snippet lang = c : * int SSL_CTX_load_verify_locations(SSL_CTX *ctx, const char *CAfile, const char *CApath) + * } + */ + public static MemorySegment SSL_CTX_load_verify_locations$address() { + return SSL_CTX_load_verify_locations.ADDR; + } + + /** + * {@snippet lang = c : * int SSL_CTX_load_verify_locations(SSL_CTX *ctx, const char *CAfile, const char *CApath) * } */ public static int SSL_CTX_load_verify_locations(MemorySegment ctx, MemorySegment CAfile, MemorySegment CApath) { - var mh$ = SSL_CTX_load_verify_locations$MH(); + var mh$ = SSL_CTX_load_verify_locations.HANDLE; try { if (TRACE_DOWNCALLS) { traceDowncall("SSL_CTX_load_verify_locations", ctx, CAfile, CApath); } return (int) mh$.invokeExact(ctx, CAfile, CApath); } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); + throw new AssertionError("should not reach here", ex$); } } - private static MethodHandle SSL_get_session$MH() { - class Holder { - static final FunctionDescriptor DESC = FunctionDescriptor.of( - openssl_h.C_POINTER, - openssl_h.C_POINTER - ); - - static final MethodHandle MH = Linker.nativeLinker().downcallHandle( - openssl_h.findOrThrow("SSL_get_session"), - DESC); - } - return Holder.MH; + private static class SSL_get_session { + public static final FunctionDescriptor DESC = FunctionDescriptor.of(openssl_h.C_POINTER, openssl_h.C_POINTER); + + public static final MemorySegment ADDR = openssl_h.findOrThrow("SSL_get_session"); + + public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); } /** - * {@snippet lang=c : - * SSL_SESSION *SSL_get_session(const SSL *ssl) + * Function descriptor for: + * {@snippet lang = c : * SSL_SESSION *SSL_get_session(const SSL *ssl) + * } + */ + public static FunctionDescriptor SSL_get_session$descriptor() { + return SSL_get_session.DESC; + } + + /** + * Downcall method handle for: + * {@snippet lang = c : * SSL_SESSION *SSL_get_session(const SSL *ssl) + * } + */ + public static MethodHandle SSL_get_session$handle() { + return SSL_get_session.HANDLE; + } + + /** + * Address for: + * {@snippet lang = c : * SSL_SESSION *SSL_get_session(const SSL *ssl) + * } + */ + public static MemorySegment SSL_get_session$address() { + return SSL_get_session.ADDR; + } + + /** + * {@snippet lang = c : * SSL_SESSION *SSL_get_session(const SSL *ssl) * } */ public static MemorySegment SSL_get_session(MemorySegment ssl) { - var mh$ = SSL_get_session$MH(); + var mh$ = SSL_get_session.HANDLE; try { if (TRACE_DOWNCALLS) { traceDowncall("SSL_get_session", ssl); } return (MemorySegment) mh$.invokeExact(ssl); } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); + throw new AssertionError("should not reach here", ex$); } } - private static MethodHandle SSL_set_info_callback$MH() { - class Holder { - static final FunctionDescriptor DESC = FunctionDescriptor.ofVoid( - openssl_h.C_POINTER, - openssl_h.C_POINTER - ); - - static final MethodHandle MH = Linker.nativeLinker().downcallHandle( - openssl_h.findOrThrow("SSL_set_info_callback"), - DESC); - } - return Holder.MH; + private static class SSL_set_info_callback { + public static final FunctionDescriptor DESC = + FunctionDescriptor.ofVoid(openssl_h.C_POINTER, openssl_h.C_POINTER); + + public static final MemorySegment ADDR = openssl_h.findOrThrow("SSL_set_info_callback"); + + public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); } /** - * {@snippet lang=c : - * void SSL_set_info_callback(SSL *ssl, void (*cb)(const SSL *, int, int)) + * Function descriptor for: + * {@snippet lang = c : * void SSL_set_info_callback(SSL *ssl, void (*cb)(const SSL *, int, int)) + * } + */ + public static FunctionDescriptor SSL_set_info_callback$descriptor() { + return SSL_set_info_callback.DESC; + } + + /** + * Downcall method handle for: + * {@snippet lang = c : * void SSL_set_info_callback(SSL *ssl, void (*cb)(const SSL *, int, int)) + * } + */ + public static MethodHandle SSL_set_info_callback$handle() { + return SSL_set_info_callback.HANDLE; + } + + /** + * Address for: + * {@snippet lang = c : * void SSL_set_info_callback(SSL *ssl, void (*cb)(const SSL *, int, int)) + * } + */ + public static MemorySegment SSL_set_info_callback$address() { + return SSL_set_info_callback.ADDR; + } + + /** + * {@snippet lang = c : * void SSL_set_info_callback(SSL *ssl, void (*cb)(const SSL *, int, int)) * } */ public static void SSL_set_info_callback(MemorySegment ssl, MemorySegment cb) { - var mh$ = SSL_set_info_callback$MH(); + var mh$ = SSL_set_info_callback.HANDLE; try { if (TRACE_DOWNCALLS) { traceDowncall("SSL_set_info_callback", ssl, cb); } mh$.invokeExact(ssl, cb); } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); + throw new AssertionError("should not reach here", ex$); } } - private static MethodHandle SSL_set_verify_result$MH() { - class Holder { - static final FunctionDescriptor DESC = FunctionDescriptor.ofVoid( - openssl_h.C_POINTER, - openssl_h.C_LONG - ); - - static final MethodHandle MH = Linker.nativeLinker().downcallHandle( - openssl_h.findOrThrow("SSL_set_verify_result"), - DESC); - } - return Holder.MH; + private static class SSL_set_verify_result { + public static final FunctionDescriptor DESC = FunctionDescriptor.ofVoid(openssl_h.C_POINTER, openssl_h.C_LONG); + + public static final MemorySegment ADDR = openssl_h.findOrThrow("SSL_set_verify_result"); + + public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); } /** - * {@snippet lang=c : - * void SSL_set_verify_result(SSL *ssl, long v) + * Function descriptor for: + * {@snippet lang = c : * void SSL_set_verify_result(SSL *ssl, long v) + * } + */ + public static FunctionDescriptor SSL_set_verify_result$descriptor() { + return SSL_set_verify_result.DESC; + } + + /** + * Downcall method handle for: + * {@snippet lang = c : * void SSL_set_verify_result(SSL *ssl, long v) + * } + */ + public static MethodHandle SSL_set_verify_result$handle() { + return SSL_set_verify_result.HANDLE; + } + + /** + * Address for: + * {@snippet lang = c : * void SSL_set_verify_result(SSL *ssl, long v) + * } + */ + public static MemorySegment SSL_set_verify_result$address() { + return SSL_set_verify_result.ADDR; + } + + /** + * {@snippet lang = c : * void SSL_set_verify_result(SSL *ssl, long v) * } */ public static void SSL_set_verify_result(MemorySegment ssl, long v) { - var mh$ = SSL_set_verify_result$MH(); + var mh$ = SSL_set_verify_result.HANDLE; try { if (TRACE_DOWNCALLS) { traceDowncall("SSL_set_verify_result", ssl, v); } mh$.invokeExact(ssl, v); } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); + throw new AssertionError("should not reach here", ex$); } } - private static MethodHandle SSL_get_ex_data_X509_STORE_CTX_idx$MH() { - class Holder { - static final FunctionDescriptor DESC = FunctionDescriptor.of( - openssl_h.C_INT ); + private static class SSL_get_ex_data_X509_STORE_CTX_idx { + public static final FunctionDescriptor DESC = FunctionDescriptor.of(openssl_h.C_INT); - static final MethodHandle MH = Linker.nativeLinker().downcallHandle( - openssl_h.findOrThrow("SSL_get_ex_data_X509_STORE_CTX_idx"), - DESC); - } - return Holder.MH; + public static final MemorySegment ADDR = openssl_h.findOrThrow("SSL_get_ex_data_X509_STORE_CTX_idx"); + + public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); } /** - * {@snippet lang=c : - * int SSL_get_ex_data_X509_STORE_CTX_idx(void) + * Function descriptor for: + * {@snippet lang = c : * int SSL_get_ex_data_X509_STORE_CTX_idx() + * } + */ + public static FunctionDescriptor SSL_get_ex_data_X509_STORE_CTX_idx$descriptor() { + return SSL_get_ex_data_X509_STORE_CTX_idx.DESC; + } + + /** + * Downcall method handle for: + * {@snippet lang = c : * int SSL_get_ex_data_X509_STORE_CTX_idx() + * } + */ + public static MethodHandle SSL_get_ex_data_X509_STORE_CTX_idx$handle() { + return SSL_get_ex_data_X509_STORE_CTX_idx.HANDLE; + } + + /** + * Address for: + * {@snippet lang = c : * int SSL_get_ex_data_X509_STORE_CTX_idx() + * } + */ + public static MemorySegment SSL_get_ex_data_X509_STORE_CTX_idx$address() { + return SSL_get_ex_data_X509_STORE_CTX_idx.ADDR; + } + + /** + * {@snippet lang = c : * int SSL_get_ex_data_X509_STORE_CTX_idx() * } */ public static int SSL_get_ex_data_X509_STORE_CTX_idx() { - var mh$ = SSL_get_ex_data_X509_STORE_CTX_idx$MH(); + var mh$ = SSL_get_ex_data_X509_STORE_CTX_idx.HANDLE; try { if (TRACE_DOWNCALLS) { traceDowncall("SSL_get_ex_data_X509_STORE_CTX_idx"); } return (int) mh$.invokeExact(); } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); + throw new AssertionError("should not reach here", ex$); } } - private static MethodHandle SSL_CTX_set_tmp_dh_callback$MH() { - class Holder { - static final FunctionDescriptor DESC = FunctionDescriptor.ofVoid( - openssl_h.C_POINTER, - openssl_h.C_POINTER - ); - - static final MethodHandle MH = Linker.nativeLinker().downcallHandle( - openssl_h.findOrThrow("SSL_CTX_set_tmp_dh_callback"), - DESC); - } - return Holder.MH; + private static class SSL_CTX_set_tmp_dh_callback { + public static final FunctionDescriptor DESC = + FunctionDescriptor.ofVoid(openssl_h.C_POINTER, openssl_h.C_POINTER); + + public static final MemorySegment ADDR = openssl_h.findOrThrow("SSL_CTX_set_tmp_dh_callback"); + + public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); } /** - * {@snippet lang=c : - * void SSL_CTX_set_tmp_dh_callback(SSL_CTX *ctx, DH *(*dh)(SSL *, int, int)) + * Function descriptor for: + * {@snippet lang = c : * void SSL_CTX_set_tmp_dh_callback(SSL_CTX *ctx, DH *(*dh)(SSL *, int, int)) + * } + */ + public static FunctionDescriptor SSL_CTX_set_tmp_dh_callback$descriptor() { + return SSL_CTX_set_tmp_dh_callback.DESC; + } + + /** + * Downcall method handle for: + * {@snippet lang = c : * void SSL_CTX_set_tmp_dh_callback(SSL_CTX *ctx, DH *(*dh)(SSL *, int, int)) + * } + */ + public static MethodHandle SSL_CTX_set_tmp_dh_callback$handle() { + return SSL_CTX_set_tmp_dh_callback.HANDLE; + } + + /** + * Address for: + * {@snippet lang = c : * void SSL_CTX_set_tmp_dh_callback(SSL_CTX *ctx, DH *(*dh)(SSL *, int, int)) + * } + */ + public static MemorySegment SSL_CTX_set_tmp_dh_callback$address() { + return SSL_CTX_set_tmp_dh_callback.ADDR; + } + + /** + * {@snippet lang = c : * void SSL_CTX_set_tmp_dh_callback(SSL_CTX *ctx, DH *(*dh)(SSL *, int, int)) * } */ public static void SSL_CTX_set_tmp_dh_callback(MemorySegment ctx, MemorySegment dh) { - var mh$ = SSL_CTX_set_tmp_dh_callback$MH(); + var mh$ = SSL_CTX_set_tmp_dh_callback.HANDLE; try { if (TRACE_DOWNCALLS) { traceDowncall("SSL_CTX_set_tmp_dh_callback", ctx, dh); } mh$.invokeExact(ctx, dh); } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); + throw new AssertionError("should not reach here", ex$); } } - private static MethodHandle SSL_CONF_CTX_new$MH() { - class Holder { - static final FunctionDescriptor DESC = FunctionDescriptor.of( - openssl_h.C_POINTER ); + private static class SSL_CONF_CTX_new { + public static final FunctionDescriptor DESC = FunctionDescriptor.of(openssl_h.C_POINTER); - static final MethodHandle MH = Linker.nativeLinker().downcallHandle( - openssl_h.findOrThrow("SSL_CONF_CTX_new"), - DESC); - } - return Holder.MH; + public static final MemorySegment ADDR = openssl_h.findOrThrow("SSL_CONF_CTX_new"); + + public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); } /** - * {@snippet lang=c : - * SSL_CONF_CTX *SSL_CONF_CTX_new(void) + * Function descriptor for: + * {@snippet lang = c : * SSL_CONF_CTX *SSL_CONF_CTX_new() + * } + */ + public static FunctionDescriptor SSL_CONF_CTX_new$descriptor() { + return SSL_CONF_CTX_new.DESC; + } + + /** + * Downcall method handle for: + * {@snippet lang = c : * SSL_CONF_CTX *SSL_CONF_CTX_new() + * } + */ + public static MethodHandle SSL_CONF_CTX_new$handle() { + return SSL_CONF_CTX_new.HANDLE; + } + + /** + * Address for: + * {@snippet lang = c : * SSL_CONF_CTX *SSL_CONF_CTX_new() + * } + */ + public static MemorySegment SSL_CONF_CTX_new$address() { + return SSL_CONF_CTX_new.ADDR; + } + + /** + * {@snippet lang = c : * SSL_CONF_CTX *SSL_CONF_CTX_new() * } */ public static MemorySegment SSL_CONF_CTX_new() { - var mh$ = SSL_CONF_CTX_new$MH(); + var mh$ = SSL_CONF_CTX_new.HANDLE; try { if (TRACE_DOWNCALLS) { traceDowncall("SSL_CONF_CTX_new"); } return (MemorySegment) mh$.invokeExact(); } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); + throw new AssertionError("should not reach here", ex$); } } - private static MethodHandle SSL_CONF_CTX_finish$MH() { - class Holder { - static final FunctionDescriptor DESC = FunctionDescriptor.of( - openssl_h.C_INT, - openssl_h.C_POINTER - ); - - static final MethodHandle MH = Linker.nativeLinker().downcallHandle( - openssl_h.findOrThrow("SSL_CONF_CTX_finish"), - DESC); - } - return Holder.MH; + private static class SSL_CONF_CTX_finish { + public static final FunctionDescriptor DESC = FunctionDescriptor.of(openssl_h.C_INT, openssl_h.C_POINTER); + + public static final MemorySegment ADDR = openssl_h.findOrThrow("SSL_CONF_CTX_finish"); + + public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); } /** - * {@snippet lang=c : - * int SSL_CONF_CTX_finish(SSL_CONF_CTX *cctx) + * Function descriptor for: + * {@snippet lang = c : * int SSL_CONF_CTX_finish(SSL_CONF_CTX *cctx) + * } + */ + public static FunctionDescriptor SSL_CONF_CTX_finish$descriptor() { + return SSL_CONF_CTX_finish.DESC; + } + + /** + * Downcall method handle for: + * {@snippet lang = c : * int SSL_CONF_CTX_finish(SSL_CONF_CTX *cctx) + * } + */ + public static MethodHandle SSL_CONF_CTX_finish$handle() { + return SSL_CONF_CTX_finish.HANDLE; + } + + /** + * Address for: + * {@snippet lang = c : * int SSL_CONF_CTX_finish(SSL_CONF_CTX *cctx) + * } + */ + public static MemorySegment SSL_CONF_CTX_finish$address() { + return SSL_CONF_CTX_finish.ADDR; + } + + /** + * {@snippet lang = c : * int SSL_CONF_CTX_finish(SSL_CONF_CTX *cctx) * } */ public static int SSL_CONF_CTX_finish(MemorySegment cctx) { - var mh$ = SSL_CONF_CTX_finish$MH(); + var mh$ = SSL_CONF_CTX_finish.HANDLE; try { if (TRACE_DOWNCALLS) { traceDowncall("SSL_CONF_CTX_finish", cctx); } return (int) mh$.invokeExact(cctx); } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); + throw new AssertionError("should not reach here", ex$); } } - private static MethodHandle SSL_CONF_CTX_free$MH() { - class Holder { - static final FunctionDescriptor DESC = FunctionDescriptor.ofVoid( - openssl_h.C_POINTER - ); - - static final MethodHandle MH = Linker.nativeLinker().downcallHandle( - openssl_h.findOrThrow("SSL_CONF_CTX_free"), - DESC); - } - return Holder.MH; + private static class SSL_CONF_CTX_free { + public static final FunctionDescriptor DESC = FunctionDescriptor.ofVoid(openssl_h.C_POINTER); + + public static final MemorySegment ADDR = openssl_h.findOrThrow("SSL_CONF_CTX_free"); + + public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); } /** - * {@snippet lang=c : - * void SSL_CONF_CTX_free(SSL_CONF_CTX *cctx) + * Function descriptor for: + * {@snippet lang = c : * void SSL_CONF_CTX_free(SSL_CONF_CTX *cctx) + * } + */ + public static FunctionDescriptor SSL_CONF_CTX_free$descriptor() { + return SSL_CONF_CTX_free.DESC; + } + + /** + * Downcall method handle for: + * {@snippet lang = c : * void SSL_CONF_CTX_free(SSL_CONF_CTX *cctx) + * } + */ + public static MethodHandle SSL_CONF_CTX_free$handle() { + return SSL_CONF_CTX_free.HANDLE; + } + + /** + * Address for: + * {@snippet lang = c : * void SSL_CONF_CTX_free(SSL_CONF_CTX *cctx) + * } + */ + public static MemorySegment SSL_CONF_CTX_free$address() { + return SSL_CONF_CTX_free.ADDR; + } + + /** + * {@snippet lang = c : * void SSL_CONF_CTX_free(SSL_CONF_CTX *cctx) * } */ public static void SSL_CONF_CTX_free(MemorySegment cctx) { - var mh$ = SSL_CONF_CTX_free$MH(); + var mh$ = SSL_CONF_CTX_free.HANDLE; try { if (TRACE_DOWNCALLS) { traceDowncall("SSL_CONF_CTX_free", cctx); } mh$.invokeExact(cctx); } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); + throw new AssertionError("should not reach here", ex$); } } - private static MethodHandle SSL_CONF_CTX_set_flags$MH() { - class Holder { - static final FunctionDescriptor DESC = FunctionDescriptor.of( - openssl_h.C_INT, - openssl_h.C_POINTER, - openssl_h.C_INT - ); - - static final MethodHandle MH = Linker.nativeLinker().downcallHandle( - openssl_h.findOrThrow("SSL_CONF_CTX_set_flags"), - DESC); - } - return Holder.MH; + private static class SSL_CONF_CTX_set_flags { + public static final FunctionDescriptor DESC = + FunctionDescriptor.of(openssl_h.C_INT, openssl_h.C_POINTER, openssl_h.C_INT); + + public static final MemorySegment ADDR = openssl_h.findOrThrow("SSL_CONF_CTX_set_flags"); + + public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); } /** - * {@snippet lang=c : - * unsigned int SSL_CONF_CTX_set_flags(SSL_CONF_CTX *cctx, unsigned int flags) + * Function descriptor for: + * {@snippet lang = c : * unsigned int SSL_CONF_CTX_set_flags(SSL_CONF_CTX *cctx, unsigned int flags) + * } + */ + public static FunctionDescriptor SSL_CONF_CTX_set_flags$descriptor() { + return SSL_CONF_CTX_set_flags.DESC; + } + + /** + * Downcall method handle for: + * {@snippet lang = c : * unsigned int SSL_CONF_CTX_set_flags(SSL_CONF_CTX *cctx, unsigned int flags) + * } + */ + public static MethodHandle SSL_CONF_CTX_set_flags$handle() { + return SSL_CONF_CTX_set_flags.HANDLE; + } + + /** + * Address for: + * {@snippet lang = c : * unsigned int SSL_CONF_CTX_set_flags(SSL_CONF_CTX *cctx, unsigned int flags) + * } + */ + public static MemorySegment SSL_CONF_CTX_set_flags$address() { + return SSL_CONF_CTX_set_flags.ADDR; + } + + /** + * {@snippet lang = c : * unsigned int SSL_CONF_CTX_set_flags(SSL_CONF_CTX *cctx, unsigned int flags) * } */ public static int SSL_CONF_CTX_set_flags(MemorySegment cctx, int flags) { - var mh$ = SSL_CONF_CTX_set_flags$MH(); + var mh$ = SSL_CONF_CTX_set_flags.HANDLE; try { if (TRACE_DOWNCALLS) { traceDowncall("SSL_CONF_CTX_set_flags", cctx, flags); } return (int) mh$.invokeExact(cctx, flags); } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); + throw new AssertionError("should not reach here", ex$); } } - private static MethodHandle SSL_CONF_CTX_set_ssl_ctx$MH() { - class Holder { - static final FunctionDescriptor DESC = FunctionDescriptor.ofVoid( - openssl_h.C_POINTER, - openssl_h.C_POINTER - ); - - static final MethodHandle MH = Linker.nativeLinker().downcallHandle( - openssl_h.findOrThrow("SSL_CONF_CTX_set_ssl_ctx"), - DESC); - } - return Holder.MH; + private static class SSL_CONF_CTX_set_ssl_ctx { + public static final FunctionDescriptor DESC = + FunctionDescriptor.ofVoid(openssl_h.C_POINTER, openssl_h.C_POINTER); + + public static final MemorySegment ADDR = openssl_h.findOrThrow("SSL_CONF_CTX_set_ssl_ctx"); + + public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); } /** - * {@snippet lang=c : - * void SSL_CONF_CTX_set_ssl_ctx(SSL_CONF_CTX *cctx, SSL_CTX *ctx) + * Function descriptor for: + * {@snippet lang = c : * void SSL_CONF_CTX_set_ssl_ctx(SSL_CONF_CTX *cctx, SSL_CTX *ctx) + * } + */ + public static FunctionDescriptor SSL_CONF_CTX_set_ssl_ctx$descriptor() { + return SSL_CONF_CTX_set_ssl_ctx.DESC; + } + + /** + * Downcall method handle for: + * {@snippet lang = c : * void SSL_CONF_CTX_set_ssl_ctx(SSL_CONF_CTX *cctx, SSL_CTX *ctx) + * } + */ + public static MethodHandle SSL_CONF_CTX_set_ssl_ctx$handle() { + return SSL_CONF_CTX_set_ssl_ctx.HANDLE; + } + + /** + * Address for: + * {@snippet lang = c : * void SSL_CONF_CTX_set_ssl_ctx(SSL_CONF_CTX *cctx, SSL_CTX *ctx) + * } + */ + public static MemorySegment SSL_CONF_CTX_set_ssl_ctx$address() { + return SSL_CONF_CTX_set_ssl_ctx.ADDR; + } + + /** + * {@snippet lang = c : * void SSL_CONF_CTX_set_ssl_ctx(SSL_CONF_CTX *cctx, SSL_CTX *ctx) * } */ public static void SSL_CONF_CTX_set_ssl_ctx(MemorySegment cctx, MemorySegment ctx) { - var mh$ = SSL_CONF_CTX_set_ssl_ctx$MH(); + var mh$ = SSL_CONF_CTX_set_ssl_ctx.HANDLE; try { if (TRACE_DOWNCALLS) { traceDowncall("SSL_CONF_CTX_set_ssl_ctx", cctx, ctx); } mh$.invokeExact(cctx, ctx); } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); + throw new AssertionError("should not reach here", ex$); } } - private static MethodHandle SSL_CONF_cmd$MH() { - class Holder { - static final FunctionDescriptor DESC = FunctionDescriptor.of( - openssl_h.C_INT, - openssl_h.C_POINTER, - openssl_h.C_POINTER, - openssl_h.C_POINTER - ); - - static final MethodHandle MH = Linker.nativeLinker().downcallHandle( - openssl_h.findOrThrow("SSL_CONF_cmd"), - DESC); - } - return Holder.MH; + private static class SSL_CONF_cmd { + public static final FunctionDescriptor DESC = + FunctionDescriptor.of(openssl_h.C_INT, openssl_h.C_POINTER, openssl_h.C_POINTER, openssl_h.C_POINTER); + + public static final MemorySegment ADDR = openssl_h.findOrThrow("SSL_CONF_cmd"); + + public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); } /** - * {@snippet lang=c : - * int SSL_CONF_cmd(SSL_CONF_CTX *cctx, const char *cmd, const char *value) + * Function descriptor for: + * {@snippet lang = c : * int SSL_CONF_cmd(SSL_CONF_CTX *cctx, const char *cmd, const char *value) + * } + */ + public static FunctionDescriptor SSL_CONF_cmd$descriptor() { + return SSL_CONF_cmd.DESC; + } + + /** + * Downcall method handle for: + * {@snippet lang = c : * int SSL_CONF_cmd(SSL_CONF_CTX *cctx, const char *cmd, const char *value) + * } + */ + public static MethodHandle SSL_CONF_cmd$handle() { + return SSL_CONF_cmd.HANDLE; + } + + /** + * Address for: + * {@snippet lang = c : * int SSL_CONF_cmd(SSL_CONF_CTX *cctx, const char *cmd, const char *value) + * } + */ + public static MemorySegment SSL_CONF_cmd$address() { + return SSL_CONF_cmd.ADDR; + } + + /** + * {@snippet lang = c : * int SSL_CONF_cmd(SSL_CONF_CTX *cctx, const char *cmd, const char *value) * } */ public static int SSL_CONF_cmd(MemorySegment cctx, MemorySegment cmd, MemorySegment value) { - var mh$ = SSL_CONF_cmd$MH(); + var mh$ = SSL_CONF_cmd.HANDLE; try { if (TRACE_DOWNCALLS) { traceDowncall("SSL_CONF_cmd", cctx, cmd, value); } return (int) mh$.invokeExact(cctx, cmd, value); } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); + throw new AssertionError("should not reach here", ex$); } } - private static MethodHandle SSL_CONF_cmd_value_type$MH() { - class Holder { - static final FunctionDescriptor DESC = FunctionDescriptor.of( - openssl_h.C_INT, - openssl_h.C_POINTER, - openssl_h.C_POINTER - ); - - static final MethodHandle MH = Linker.nativeLinker().downcallHandle( - openssl_h.findOrThrow("SSL_CONF_cmd_value_type"), - DESC); - } - return Holder.MH; + private static class SSL_CONF_cmd_value_type { + public static final FunctionDescriptor DESC = + FunctionDescriptor.of(openssl_h.C_INT, openssl_h.C_POINTER, openssl_h.C_POINTER); + + public static final MemorySegment ADDR = openssl_h.findOrThrow("SSL_CONF_cmd_value_type"); + + public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); } /** - * {@snippet lang=c : - * int SSL_CONF_cmd_value_type(SSL_CONF_CTX *cctx, const char *cmd) + * Function descriptor for: + * {@snippet lang = c : * int SSL_CONF_cmd_value_type(SSL_CONF_CTX *cctx, const char *cmd) + * } + */ + public static FunctionDescriptor SSL_CONF_cmd_value_type$descriptor() { + return SSL_CONF_cmd_value_type.DESC; + } + + /** + * Downcall method handle for: + * {@snippet lang = c : * int SSL_CONF_cmd_value_type(SSL_CONF_CTX *cctx, const char *cmd) + * } + */ + public static MethodHandle SSL_CONF_cmd_value_type$handle() { + return SSL_CONF_cmd_value_type.HANDLE; + } + + /** + * Address for: + * {@snippet lang = c : * int SSL_CONF_cmd_value_type(SSL_CONF_CTX *cctx, const char *cmd) + * } + */ + public static MemorySegment SSL_CONF_cmd_value_type$address() { + return SSL_CONF_cmd_value_type.ADDR; + } + + /** + * {@snippet lang = c : * int SSL_CONF_cmd_value_type(SSL_CONF_CTX *cctx, const char *cmd) * } */ public static int SSL_CONF_cmd_value_type(MemorySegment cctx, MemorySegment cmd) { - var mh$ = SSL_CONF_cmd_value_type$MH(); + var mh$ = SSL_CONF_cmd_value_type.HANDLE; try { if (TRACE_DOWNCALLS) { traceDowncall("SSL_CONF_cmd_value_type", cctx, cmd); } return (int) mh$.invokeExact(cctx, cmd); } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); + throw new AssertionError("should not reach here", ex$); } } - private static MethodHandle OPENSSL_init_ssl$MH() { - class Holder { - static final FunctionDescriptor DESC = FunctionDescriptor.of( - openssl_h.C_INT, - openssl_h.C_LONG, - openssl_h.C_POINTER - ); - - static final MethodHandle MH = Linker.nativeLinker().downcallHandle( - openssl_h.findOrThrow("OPENSSL_init_ssl"), - DESC); - } - return Holder.MH; + private static class OPENSSL_init_ssl { + public static final FunctionDescriptor DESC = + FunctionDescriptor.of(openssl_h.C_INT, openssl_h.C_LONG, openssl_h.C_POINTER); + + public static final MemorySegment ADDR = openssl_h.findOrThrow("OPENSSL_init_ssl"); + + public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); } /** - * {@snippet lang=c : - * int OPENSSL_init_ssl(uint64_t opts, const OPENSSL_INIT_SETTINGS *settings) + * Function descriptor for: + * {@snippet lang = c : * int OPENSSL_init_ssl(uint64_t opts, const OPENSSL_INIT_SETTINGS *settings) + * } + */ + public static FunctionDescriptor OPENSSL_init_ssl$descriptor() { + return OPENSSL_init_ssl.DESC; + } + + /** + * Downcall method handle for: + * {@snippet lang = c : * int OPENSSL_init_ssl(uint64_t opts, const OPENSSL_INIT_SETTINGS *settings) + * } + */ + public static MethodHandle OPENSSL_init_ssl$handle() { + return OPENSSL_init_ssl.HANDLE; + } + + /** + * Address for: + * {@snippet lang = c : * int OPENSSL_init_ssl(uint64_t opts, const OPENSSL_INIT_SETTINGS *settings) + * } + */ + public static MemorySegment OPENSSL_init_ssl$address() { + return OPENSSL_init_ssl.ADDR; + } + + /** + * {@snippet lang = c : * int OPENSSL_init_ssl(uint64_t opts, const OPENSSL_INIT_SETTINGS *settings) * } */ public static int OPENSSL_init_ssl(long opts, MemorySegment settings) { - var mh$ = OPENSSL_init_ssl$MH(); + var mh$ = OPENSSL_init_ssl.HANDLE; try { if (TRACE_DOWNCALLS) { traceDowncall("OPENSSL_init_ssl", opts, settings); } return (int) mh$.invokeExact(opts, settings); } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); + throw new AssertionError("should not reach here", ex$); } } - private static MethodHandle ERR_get_error$MH() { - class Holder { - static final FunctionDescriptor DESC = FunctionDescriptor.of( - openssl_h.C_LONG ); + private static class ERR_get_error { + public static final FunctionDescriptor DESC = FunctionDescriptor.of(openssl_h.C_LONG); - static final MethodHandle MH = Linker.nativeLinker().downcallHandle( - openssl_h.findOrThrow("ERR_get_error"), - DESC); - } - return Holder.MH; + public static final MemorySegment ADDR = openssl_h.findOrThrow("ERR_get_error"); + + public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); } /** - * {@snippet lang=c : - * unsigned long ERR_get_error(void) + * Function descriptor for: + * {@snippet lang = c : * unsigned long ERR_get_error() + * } + */ + public static FunctionDescriptor ERR_get_error$descriptor() { + return ERR_get_error.DESC; + } + + /** + * Downcall method handle for: + * {@snippet lang = c : * unsigned long ERR_get_error() + * } + */ + public static MethodHandle ERR_get_error$handle() { + return ERR_get_error.HANDLE; + } + + /** + * Address for: + * {@snippet lang = c : * unsigned long ERR_get_error() + * } + */ + public static MemorySegment ERR_get_error$address() { + return ERR_get_error.ADDR; + } + + /** + * {@snippet lang = c : * unsigned long ERR_get_error() * } */ public static long ERR_get_error() { - var mh$ = ERR_get_error$MH(); + var mh$ = ERR_get_error.HANDLE; try { if (TRACE_DOWNCALLS) { traceDowncall("ERR_get_error"); } return (long) mh$.invokeExact(); } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); + throw new AssertionError("should not reach here", ex$); } } - private static MethodHandle ERR_peek_last_error$MH() { - class Holder { - static final FunctionDescriptor DESC = FunctionDescriptor.of( - openssl_h.C_LONG ); + private static class ERR_peek_last_error { + public static final FunctionDescriptor DESC = FunctionDescriptor.of(openssl_h.C_LONG); - static final MethodHandle MH = Linker.nativeLinker().downcallHandle( - openssl_h.findOrThrow("ERR_peek_last_error"), - DESC); - } - return Holder.MH; + public static final MemorySegment ADDR = openssl_h.findOrThrow("ERR_peek_last_error"); + + public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); } /** - * {@snippet lang=c : - * unsigned long ERR_peek_last_error(void) + * Function descriptor for: + * {@snippet lang = c : * unsigned long ERR_peek_last_error() + * } + */ + public static FunctionDescriptor ERR_peek_last_error$descriptor() { + return ERR_peek_last_error.DESC; + } + + /** + * Downcall method handle for: + * {@snippet lang = c : * unsigned long ERR_peek_last_error() + * } + */ + public static MethodHandle ERR_peek_last_error$handle() { + return ERR_peek_last_error.HANDLE; + } + + /** + * Address for: + * {@snippet lang = c : * unsigned long ERR_peek_last_error() + * } + */ + public static MemorySegment ERR_peek_last_error$address() { + return ERR_peek_last_error.ADDR; + } + + /** + * {@snippet lang = c : * unsigned long ERR_peek_last_error() * } */ public static long ERR_peek_last_error() { - var mh$ = ERR_peek_last_error$MH(); + var mh$ = ERR_peek_last_error.HANDLE; try { if (TRACE_DOWNCALLS) { traceDowncall("ERR_peek_last_error"); } return (long) mh$.invokeExact(); } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); + throw new AssertionError("should not reach here", ex$); } } - private static MethodHandle ERR_clear_error$MH() { - class Holder { - static final FunctionDescriptor DESC = FunctionDescriptor.ofVoid( ); + private static class ERR_clear_error { + public static final FunctionDescriptor DESC = FunctionDescriptor.ofVoid(); - static final MethodHandle MH = Linker.nativeLinker().downcallHandle( - openssl_h.findOrThrow("ERR_clear_error"), - DESC); - } - return Holder.MH; + public static final MemorySegment ADDR = openssl_h.findOrThrow("ERR_clear_error"); + + public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); } /** - * {@snippet lang=c : - * void ERR_clear_error(void) + * Function descriptor for: + * {@snippet lang = c : * void ERR_clear_error() + * } + */ + public static FunctionDescriptor ERR_clear_error$descriptor() { + return ERR_clear_error.DESC; + } + + /** + * Downcall method handle for: + * {@snippet lang = c : * void ERR_clear_error() + * } + */ + public static MethodHandle ERR_clear_error$handle() { + return ERR_clear_error.HANDLE; + } + + /** + * Address for: + * {@snippet lang = c : * void ERR_clear_error() + * } + */ + public static MemorySegment ERR_clear_error$address() { + return ERR_clear_error.ADDR; + } + + /** + * {@snippet lang = c : * void ERR_clear_error() * } */ public static void ERR_clear_error() { - var mh$ = ERR_clear_error$MH(); + var mh$ = ERR_clear_error.HANDLE; try { if (TRACE_DOWNCALLS) { traceDowncall("ERR_clear_error"); } mh$.invokeExact(); } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); + throw new AssertionError("should not reach here", ex$); } } - private static MethodHandle ERR_error_string$MH() { - class Holder { - static final FunctionDescriptor DESC = FunctionDescriptor.of( - openssl_h.C_POINTER, - openssl_h.C_LONG, - openssl_h.C_POINTER - ); - - static final MethodHandle MH = Linker.nativeLinker().downcallHandle( - openssl_h.findOrThrow("ERR_error_string"), - DESC); - } - return Holder.MH; + private static class ERR_error_string { + public static final FunctionDescriptor DESC = + FunctionDescriptor.of(openssl_h.C_POINTER, openssl_h.C_LONG, openssl_h.C_POINTER); + + public static final MemorySegment ADDR = openssl_h.findOrThrow("ERR_error_string"); + + public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); } /** - * {@snippet lang=c : - * char *ERR_error_string(unsigned long e, char *buf) + * Function descriptor for: + * {@snippet lang = c : * char *ERR_error_string(unsigned long e, char *buf) + * } + */ + public static FunctionDescriptor ERR_error_string$descriptor() { + return ERR_error_string.DESC; + } + + /** + * Downcall method handle for: + * {@snippet lang = c : * char *ERR_error_string(unsigned long e, char *buf) + * } + */ + public static MethodHandle ERR_error_string$handle() { + return ERR_error_string.HANDLE; + } + + /** + * Address for: + * {@snippet lang = c : * char *ERR_error_string(unsigned long e, char *buf) + * } + */ + public static MemorySegment ERR_error_string$address() { + return ERR_error_string.ADDR; + } + + /** + * {@snippet lang = c : * char *ERR_error_string(unsigned long e, char *buf) * } */ public static MemorySegment ERR_error_string(long e, MemorySegment buf) { - var mh$ = ERR_error_string$MH(); + var mh$ = ERR_error_string.HANDLE; try { if (TRACE_DOWNCALLS) { traceDowncall("ERR_error_string", e, buf); } return (MemorySegment) mh$.invokeExact(e, buf); } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); + throw new AssertionError("should not reach here", ex$); } } - private static MethodHandle ERR_error_string_n$MH() { - class Holder { - static final FunctionDescriptor DESC = FunctionDescriptor.of( - openssl_h.C_POINTER, - openssl_h.C_LONG, - openssl_h.C_POINTER, - openssl_h.C_INT - ); - - static final MethodHandle MH = Linker.nativeLinker().downcallHandle( - openssl_h.findOrThrow("ERR_error_string_n"), - DESC); - } - return Holder.MH; + private static class ERR_error_string_n { + public static final FunctionDescriptor DESC = + FunctionDescriptor.ofVoid(openssl_h.C_LONG, openssl_h.C_POINTER, openssl_h.C_LONG); + + public static final MemorySegment ADDR = openssl_h.findOrThrow("ERR_error_string_n"); + + public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); } /** - * {@snippet lang=c : - * char *ERR_error_string_n(unsigned long e, char *buf, size_t len) + * Function descriptor for: + * {@snippet lang = c : * void ERR_error_string_n(unsigned long e, char *buf, size_t len) + * } + */ + public static FunctionDescriptor ERR_error_string_n$descriptor() { + return ERR_error_string_n.DESC; + } + + /** + * Downcall method handle for: + * {@snippet lang = c : * void ERR_error_string_n(unsigned long e, char *buf, size_t len) + * } + */ + public static MethodHandle ERR_error_string_n$handle() { + return ERR_error_string_n.HANDLE; + } + + /** + * Address for: + * {@snippet lang = c : * void ERR_error_string_n(unsigned long e, char *buf, size_t len) + * } + */ + public static MemorySegment ERR_error_string_n$address() { + return ERR_error_string_n.ADDR; + } + + /** + * {@snippet lang = c : * void ERR_error_string_n(unsigned long e, char *buf, size_t len) * } */ - public static MemorySegment ERR_error_string_n(long e, MemorySegment buf, int len) { - var mh$ = ERR_error_string_n$MH(); + public static void ERR_error_string_n(long e, MemorySegment buf, long len) { + var mh$ = ERR_error_string_n.HANDLE; try { if (TRACE_DOWNCALLS) { traceDowncall("ERR_error_string_n", e, buf, len); } - return (MemorySegment) mh$.invokeExact(e, buf, len); + mh$.invokeExact(e, buf, len); } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); + throw new AssertionError("should not reach here", ex$); } } - private static MethodHandle PKCS12_verify_mac$MH() { - class Holder { - static final FunctionDescriptor DESC = FunctionDescriptor.of( - openssl_h.C_INT, - openssl_h.C_POINTER, - openssl_h.C_POINTER, - openssl_h.C_INT - ); - - static final MethodHandle MH = Linker.nativeLinker().downcallHandle( - openssl_h.findOrThrow("PKCS12_verify_mac"), - DESC); - } - return Holder.MH; + private static class PKCS12_verify_mac { + public static final FunctionDescriptor DESC = + FunctionDescriptor.of(openssl_h.C_INT, openssl_h.C_POINTER, openssl_h.C_POINTER, openssl_h.C_INT); + + public static final MemorySegment ADDR = openssl_h.findOrThrow("PKCS12_verify_mac"); + + public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); } /** - * {@snippet lang=c : - * int PKCS12_verify_mac(PKCS12 *p12, const char *pass, int passlen) + * Function descriptor for: + * {@snippet lang = c : * int PKCS12_verify_mac(PKCS12 *p12, const char *pass, int passlen) + * } + */ + public static FunctionDescriptor PKCS12_verify_mac$descriptor() { + return PKCS12_verify_mac.DESC; + } + + /** + * Downcall method handle for: + * {@snippet lang = c : * int PKCS12_verify_mac(PKCS12 *p12, const char *pass, int passlen) + * } + */ + public static MethodHandle PKCS12_verify_mac$handle() { + return PKCS12_verify_mac.HANDLE; + } + + /** + * Address for: + * {@snippet lang = c : * int PKCS12_verify_mac(PKCS12 *p12, const char *pass, int passlen) + * } + */ + public static MemorySegment PKCS12_verify_mac$address() { + return PKCS12_verify_mac.ADDR; + } + + /** + * {@snippet lang = c : * int PKCS12_verify_mac(PKCS12 *p12, const char *pass, int passlen) * } */ public static int PKCS12_verify_mac(MemorySegment p12, MemorySegment pass, int passlen) { - var mh$ = PKCS12_verify_mac$MH(); + var mh$ = PKCS12_verify_mac.HANDLE; try { if (TRACE_DOWNCALLS) { traceDowncall("PKCS12_verify_mac", p12, pass, passlen); } return (int) mh$.invokeExact(p12, pass, passlen); } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); + throw new AssertionError("should not reach here", ex$); } } - private static MethodHandle PKCS12_free$MH() { - class Holder { - static final FunctionDescriptor DESC = FunctionDescriptor.ofVoid( - openssl_h.C_POINTER - ); - - static final MethodHandle MH = Linker.nativeLinker().downcallHandle( - openssl_h.findOrThrow("PKCS12_free"), - DESC); - } - return Holder.MH; + private static class PKCS12_free { + public static final FunctionDescriptor DESC = FunctionDescriptor.ofVoid(openssl_h.C_POINTER); + + public static final MemorySegment ADDR = openssl_h.findOrThrow("PKCS12_free"); + + public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); } /** - * {@snippet lang=c : - * extern void PKCS12_free(PKCS12 *a) + * Function descriptor for: + * {@snippet lang = c : * extern void PKCS12_free(PKCS12 *a) + * } + */ + public static FunctionDescriptor PKCS12_free$descriptor() { + return PKCS12_free.DESC; + } + + /** + * Downcall method handle for: + * {@snippet lang = c : * extern void PKCS12_free(PKCS12 *a) + * } + */ + public static MethodHandle PKCS12_free$handle() { + return PKCS12_free.HANDLE; + } + + /** + * Address for: + * {@snippet lang = c : * extern void PKCS12_free(PKCS12 *a) + * } + */ + public static MemorySegment PKCS12_free$address() { + return PKCS12_free.ADDR; + } + + /** + * {@snippet lang = c : * extern void PKCS12_free(PKCS12 *a) * } */ public static void PKCS12_free(MemorySegment a) { - var mh$ = PKCS12_free$MH(); + var mh$ = PKCS12_free.HANDLE; try { if (TRACE_DOWNCALLS) { traceDowncall("PKCS12_free", a); } mh$.invokeExact(a); } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); + throw new AssertionError("should not reach here", ex$); } } - private static MethodHandle PKCS12_parse$MH() { - class Holder { - static final FunctionDescriptor DESC = FunctionDescriptor.of( - openssl_h.C_INT, - openssl_h.C_POINTER, - openssl_h.C_POINTER, - openssl_h.C_POINTER, - openssl_h.C_POINTER, - openssl_h.C_POINTER - ); - - static final MethodHandle MH = Linker.nativeLinker().downcallHandle( - openssl_h.findOrThrow("PKCS12_parse"), - DESC); - } - return Holder.MH; + private static class PKCS12_parse { + public static final FunctionDescriptor DESC = FunctionDescriptor.of(openssl_h.C_INT, openssl_h.C_POINTER, + openssl_h.C_POINTER, openssl_h.C_POINTER, openssl_h.C_POINTER, openssl_h.C_POINTER); + + public static final MemorySegment ADDR = openssl_h.findOrThrow("PKCS12_parse"); + + public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); } /** - * {@snippet lang=c : - * int PKCS12_parse(PKCS12 *p12, const char *pass, EVP_PKEY **pkey, X509 **cert, struct stack_st_X509 **ca) + * Function descriptor for: + * {@snippet lang = c + * : * int PKCS12_parse(PKCS12 *p12, const char *pass, EVP_PKEY **pkey, X509 **cert, struct stack_st_X509 **ca) + * } + */ + public static FunctionDescriptor PKCS12_parse$descriptor() { + return PKCS12_parse.DESC; + } + + /** + * Downcall method handle for: + * {@snippet lang = c + * : * int PKCS12_parse(PKCS12 *p12, const char *pass, EVP_PKEY **pkey, X509 **cert, struct stack_st_X509 **ca) + * } + */ + public static MethodHandle PKCS12_parse$handle() { + return PKCS12_parse.HANDLE; + } + + /** + * Address for: + * {@snippet lang = c + * : * int PKCS12_parse(PKCS12 *p12, const char *pass, EVP_PKEY **pkey, X509 **cert, struct stack_st_X509 **ca) + * } + */ + public static MemorySegment PKCS12_parse$address() { + return PKCS12_parse.ADDR; + } + + /** + * {@snippet lang = c + * : * int PKCS12_parse(PKCS12 *p12, const char *pass, EVP_PKEY **pkey, X509 **cert, struct stack_st_X509 **ca) * } */ - public static int PKCS12_parse(MemorySegment p12, MemorySegment pass, MemorySegment pkey, MemorySegment cert, MemorySegment ca) { - var mh$ = PKCS12_parse$MH(); + public static int PKCS12_parse(MemorySegment p12, MemorySegment pass, MemorySegment pkey, MemorySegment cert, + MemorySegment ca) { + var mh$ = PKCS12_parse.HANDLE; try { if (TRACE_DOWNCALLS) { traceDowncall("PKCS12_parse", p12, pass, pkey, cert, ca); } return (int) mh$.invokeExact(p12, pass, pkey, cert, ca); } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); + throw new AssertionError("should not reach here", ex$); } } - private static MethodHandle d2i_PKCS12_bio$MH() { - class Holder { - static final FunctionDescriptor DESC = FunctionDescriptor.of( - openssl_h.C_POINTER, - openssl_h.C_POINTER, - openssl_h.C_POINTER - ); - - static final MethodHandle MH = Linker.nativeLinker().downcallHandle( - openssl_h.findOrThrow("d2i_PKCS12_bio"), - DESC); - } - return Holder.MH; + private static class d2i_PKCS12_bio { + public static final FunctionDescriptor DESC = + FunctionDescriptor.of(openssl_h.C_POINTER, openssl_h.C_POINTER, openssl_h.C_POINTER); + + public static final MemorySegment ADDR = openssl_h.findOrThrow("d2i_PKCS12_bio"); + + public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); } /** - * {@snippet lang=c : - * PKCS12 *d2i_PKCS12_bio(BIO *bp, PKCS12 **p12) + * Function descriptor for: + * {@snippet lang = c : * PKCS12 *d2i_PKCS12_bio(BIO *bp, PKCS12 **p12) + * } + */ + public static FunctionDescriptor d2i_PKCS12_bio$descriptor() { + return d2i_PKCS12_bio.DESC; + } + + /** + * Downcall method handle for: + * {@snippet lang = c : * PKCS12 *d2i_PKCS12_bio(BIO *bp, PKCS12 **p12) + * } + */ + public static MethodHandle d2i_PKCS12_bio$handle() { + return d2i_PKCS12_bio.HANDLE; + } + + /** + * Address for: + * {@snippet lang = c : * PKCS12 *d2i_PKCS12_bio(BIO *bp, PKCS12 **p12) + * } + */ + public static MemorySegment d2i_PKCS12_bio$address() { + return d2i_PKCS12_bio.ADDR; + } + + /** + * {@snippet lang = c : * PKCS12 *d2i_PKCS12_bio(BIO *bp, PKCS12 **p12) * } */ public static MemorySegment d2i_PKCS12_bio(MemorySegment bp, MemorySegment p12) { - var mh$ = d2i_PKCS12_bio$MH(); + var mh$ = d2i_PKCS12_bio.HANDLE; try { if (TRACE_DOWNCALLS) { traceDowncall("d2i_PKCS12_bio", bp, p12); } return (MemorySegment) mh$.invokeExact(bp, p12); } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); + throw new AssertionError("should not reach here", ex$); } } - private static MethodHandle RAND_seed$MH() { - class Holder { - static final FunctionDescriptor DESC = FunctionDescriptor.ofVoid( - openssl_h.C_POINTER, - openssl_h.C_INT - ); - - static final MethodHandle MH = Linker.nativeLinker().downcallHandle( - openssl_h.findOrThrow("RAND_seed"), - DESC); - } - return Holder.MH; + private static class RAND_seed { + public static final FunctionDescriptor DESC = FunctionDescriptor.ofVoid(openssl_h.C_POINTER, openssl_h.C_INT); + + public static final MemorySegment ADDR = openssl_h.findOrThrow("RAND_seed"); + + public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); } /** - * {@snippet lang=c : - * void RAND_seed(const void *buf, int num) + * Function descriptor for: + * {@snippet lang = c : * void RAND_seed(const void *buf, int num) + * } + */ + public static FunctionDescriptor RAND_seed$descriptor() { + return RAND_seed.DESC; + } + + /** + * Downcall method handle for: + * {@snippet lang = c : * void RAND_seed(const void *buf, int num) + * } + */ + public static MethodHandle RAND_seed$handle() { + return RAND_seed.HANDLE; + } + + /** + * Address for: + * {@snippet lang = c : * void RAND_seed(const void *buf, int num) + * } + */ + public static MemorySegment RAND_seed$address() { + return RAND_seed.ADDR; + } + + /** + * {@snippet lang = c : * void RAND_seed(const void *buf, int num) * } */ public static void RAND_seed(MemorySegment buf, int num) { - var mh$ = RAND_seed$MH(); + var mh$ = RAND_seed.HANDLE; try { if (TRACE_DOWNCALLS) { traceDowncall("RAND_seed", buf, num); } mh$.invokeExact(buf, num); } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); + throw new AssertionError("should not reach here", ex$); } } - private static MethodHandle RAND_load_file$MH() { - class Holder { - static final FunctionDescriptor DESC = FunctionDescriptor.of( - openssl_h.C_INT, - openssl_h.C_POINTER, - openssl_h.C_LONG - ); - - static final MethodHandle MH = Linker.nativeLinker().downcallHandle( - openssl_h.findOrThrow("RAND_load_file"), - DESC); - } - return Holder.MH; + private static class RAND_load_file { + public static final FunctionDescriptor DESC = + FunctionDescriptor.of(openssl_h.C_INT, openssl_h.C_POINTER, openssl_h.C_LONG); + + public static final MemorySegment ADDR = openssl_h.findOrThrow("RAND_load_file"); + + public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); } /** - * {@snippet lang=c : - * int RAND_load_file(const char *file, long max_bytes) + * Function descriptor for: + * {@snippet lang = c : * int RAND_load_file(const char *file, long max_bytes) + * } + */ + public static FunctionDescriptor RAND_load_file$descriptor() { + return RAND_load_file.DESC; + } + + /** + * Downcall method handle for: + * {@snippet lang = c : * int RAND_load_file(const char *file, long max_bytes) + * } + */ + public static MethodHandle RAND_load_file$handle() { + return RAND_load_file.HANDLE; + } + + /** + * Address for: + * {@snippet lang = c : * int RAND_load_file(const char *file, long max_bytes) + * } + */ + public static MemorySegment RAND_load_file$address() { + return RAND_load_file.ADDR; + } + + /** + * {@snippet lang = c : * int RAND_load_file(const char *file, long max_bytes) * } */ public static int RAND_load_file(MemorySegment file, long max_bytes) { - var mh$ = RAND_load_file$MH(); + var mh$ = RAND_load_file.HANDLE; try { if (TRACE_DOWNCALLS) { traceDowncall("RAND_load_file", file, max_bytes); } return (int) mh$.invokeExact(file, max_bytes); } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); + throw new AssertionError("should not reach here", ex$); } } - private static MethodHandle X509_check_issued$MH() { - class Holder { - static final FunctionDescriptor DESC = FunctionDescriptor.of( - openssl_h.C_INT, - openssl_h.C_POINTER, - openssl_h.C_POINTER - ); - - static final MethodHandle MH = Linker.nativeLinker().downcallHandle( - openssl_h.findOrThrow("X509_check_issued"), - DESC); - } - return Holder.MH; + private static class X509_check_issued { + public static final FunctionDescriptor DESC = + FunctionDescriptor.of(openssl_h.C_INT, openssl_h.C_POINTER, openssl_h.C_POINTER); + + public static final MemorySegment ADDR = openssl_h.findOrThrow("X509_check_issued"); + + public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); } /** - * {@snippet lang=c : - * int X509_check_issued(X509 *issuer, X509 *subject) + * Function descriptor for: + * {@snippet lang = c : * int X509_check_issued(X509 *issuer, X509 *subject) + * } + */ + public static FunctionDescriptor X509_check_issued$descriptor() { + return X509_check_issued.DESC; + } + + /** + * Downcall method handle for: + * {@snippet lang = c : * int X509_check_issued(X509 *issuer, X509 *subject) + * } + */ + public static MethodHandle X509_check_issued$handle() { + return X509_check_issued.HANDLE; + } + + /** + * Address for: + * {@snippet lang = c : * int X509_check_issued(X509 *issuer, X509 *subject) + * } + */ + public static MemorySegment X509_check_issued$address() { + return X509_check_issued.ADDR; + } + + /** + * {@snippet lang = c : * int X509_check_issued(X509 *issuer, X509 *subject) * } */ public static int X509_check_issued(MemorySegment issuer, MemorySegment subject) { - var mh$ = X509_check_issued$MH(); + var mh$ = X509_check_issued.HANDLE; try { if (TRACE_DOWNCALLS) { traceDowncall("X509_check_issued", issuer, subject); } return (int) mh$.invokeExact(issuer, subject); } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); + throw new AssertionError("should not reach here", ex$); } } - private static MethodHandle ENGINE_by_id$MH() { - class Holder { - static final FunctionDescriptor DESC = FunctionDescriptor.of( - openssl_h.C_POINTER, - openssl_h.C_POINTER - ); - - static final MethodHandle MH = Linker.nativeLinker().downcallHandle( - openssl_h.findOrThrow("ENGINE_by_id"), - DESC); - } - return Holder.MH; + private static class OCSP_resp_get0_certs { + public static final FunctionDescriptor DESC = FunctionDescriptor.of( + openssl_h.C_POINTER, + openssl_h.C_POINTER + ); + + public static final MemorySegment ADDR = openssl_h.findOrThrow("OCSP_resp_get0_certs"); + + public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); } /** + * Function descriptor for: * {@snippet lang=c : - * ENGINE *ENGINE_by_id(const char *id) + * const struct stack_st_X509 *OCSP_resp_get0_certs(const OCSP_BASICRESP *bs) * } */ - public static MemorySegment ENGINE_by_id(MemorySegment id) { - var mh$ = ENGINE_by_id$MH(); - try { - if (TRACE_DOWNCALLS) { - traceDowncall("ENGINE_by_id", id); - } - return (MemorySegment) mh$.invokeExact(id); - } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); - } + public static FunctionDescriptor OCSP_resp_get0_certs$descriptor() { + return OCSP_resp_get0_certs.DESC; } - private static MethodHandle ENGINE_register_all_complete$MH() { - class Holder { - static final FunctionDescriptor DESC = FunctionDescriptor.of( - openssl_h.C_INT ); + /** + * Downcall method handle for: + * {@snippet lang=c : + * const struct stack_st_X509 *OCSP_resp_get0_certs(const OCSP_BASICRESP *bs) + * } + */ + public static MethodHandle OCSP_resp_get0_certs$handle() { + return OCSP_resp_get0_certs.HANDLE; + } - static final MethodHandle MH = Linker.nativeLinker().downcallHandle( - openssl_h.findOrThrow("ENGINE_register_all_complete"), - DESC); - } - return Holder.MH; + /** + * Address for: + * {@snippet lang=c : + * const struct stack_st_X509 *OCSP_resp_get0_certs(const OCSP_BASICRESP *bs) + * } + */ + public static MemorySegment OCSP_resp_get0_certs$address() { + return OCSP_resp_get0_certs.ADDR; } /** * {@snippet lang=c : - * int ENGINE_register_all_complete(void) + * const struct stack_st_X509 *OCSP_resp_get0_certs(const OCSP_BASICRESP *bs) * } */ - public static int ENGINE_register_all_complete() { - var mh$ = ENGINE_register_all_complete$MH(); + public static MemorySegment OCSP_resp_get0_certs(MemorySegment bs) { + var mh$ = OCSP_resp_get0_certs.HANDLE; try { if (TRACE_DOWNCALLS) { - traceDowncall("ENGINE_register_all_complete"); + traceDowncall("OCSP_resp_get0_certs", bs); } - return (int) mh$.invokeExact(); + return (MemorySegment)mh$.invokeExact(bs); + } catch (Error | RuntimeException ex) { + throw ex; } catch (Throwable ex$) { throw new AssertionError("should not reach here", ex$); } } - private static MethodHandle ENGINE_ctrl_cmd_string$MH() { - class Holder { - static final FunctionDescriptor DESC = FunctionDescriptor.of( - openssl_h.C_INT, - openssl_h.C_POINTER, - openssl_h.C_POINTER, - openssl_h.C_POINTER, - openssl_h.C_INT - ); - - static final MethodHandle MH = Linker.nativeLinker().downcallHandle( - openssl_h.findOrThrow("ENGINE_ctrl_cmd_string"), - DESC); - } - return Holder.MH; + private static class OCSP_basic_verify { + public static final FunctionDescriptor DESC = FunctionDescriptor.of( + openssl_h.C_INT, + openssl_h.C_POINTER, + openssl_h.C_POINTER, + openssl_h.C_POINTER, + openssl_h.C_LONG + ); + + public static final MemorySegment ADDR = openssl_h.findOrThrow("OCSP_basic_verify"); + + public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); + } + + /** + * Function descriptor for: + * {@snippet lang=c : + * int OCSP_basic_verify(OCSP_BASICRESP *bs, struct stack_st_X509 *certs, X509_STORE *st, unsigned long flags) + * } + */ + public static FunctionDescriptor OCSP_basic_verify$descriptor() { + return OCSP_basic_verify.DESC; + } + + /** + * Downcall method handle for: + * {@snippet lang=c : + * int OCSP_basic_verify(OCSP_BASICRESP *bs, struct stack_st_X509 *certs, X509_STORE *st, unsigned long flags) + * } + */ + public static MethodHandle OCSP_basic_verify$handle() { + return OCSP_basic_verify.HANDLE; + } + + /** + * Address for: + * {@snippet lang=c : + * int OCSP_basic_verify(OCSP_BASICRESP *bs, struct stack_st_X509 *certs, X509_STORE *st, unsigned long flags) + * } + */ + public static MemorySegment OCSP_basic_verify$address() { + return OCSP_basic_verify.ADDR; } /** * {@snippet lang=c : - * int ENGINE_ctrl_cmd_string(ENGINE *e, const char *cmd_name, const char *arg, int cmd_optional) + * int OCSP_basic_verify(OCSP_BASICRESP *bs, struct stack_st_X509 *certs, X509_STORE *st, unsigned long flags) * } */ - public static int ENGINE_ctrl_cmd_string(MemorySegment e, MemorySegment cmd_name, MemorySegment arg, int cmd_optional) { - var mh$ = ENGINE_ctrl_cmd_string$MH(); + public static int OCSP_basic_verify(MemorySegment bs, MemorySegment certs, MemorySegment st, long flags) { + var mh$ = OCSP_basic_verify.HANDLE; try { if (TRACE_DOWNCALLS) { - traceDowncall("ENGINE_ctrl_cmd_string", e, cmd_name, arg, cmd_optional); + traceDowncall("OCSP_basic_verify", bs, certs, st, flags); } - return (int) mh$.invokeExact(e, cmd_name, arg, cmd_optional); + return (int)mh$.invokeExact(bs, certs, st, flags); + } catch (Error | RuntimeException ex) { + throw ex; } catch (Throwable ex$) { throw new AssertionError("should not reach here", ex$); } } - private static MethodHandle ENGINE_free$MH() { - class Holder { - static final FunctionDescriptor DESC = FunctionDescriptor.of( - openssl_h.C_INT, - openssl_h.C_POINTER - ); - - static final MethodHandle MH = Linker.nativeLinker().downcallHandle( - openssl_h.findOrThrow("ENGINE_free"), - DESC); - } - return Holder.MH; + private static class OCSP_check_validity { + public static final FunctionDescriptor DESC = FunctionDescriptor.of( + openssl_h.C_INT, + openssl_h.C_POINTER, + openssl_h.C_POINTER, + openssl_h.C_LONG, + openssl_h.C_LONG + ); + + public static final MemorySegment ADDR = openssl_h.findOrThrow("OCSP_check_validity"); + + public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); + } + + /** + * Function descriptor for: + * {@snippet lang=c : + * int OCSP_check_validity(ASN1_GENERALIZEDTIME *thisupd, ASN1_GENERALIZEDTIME *nextupd, long sec, long maxsec) + * } + */ + public static FunctionDescriptor OCSP_check_validity$descriptor() { + return OCSP_check_validity.DESC; + } + + /** + * Downcall method handle for: + * {@snippet lang=c : + * int OCSP_check_validity(ASN1_GENERALIZEDTIME *thisupd, ASN1_GENERALIZEDTIME *nextupd, long sec, long maxsec) + * } + */ + public static MethodHandle OCSP_check_validity$handle() { + return OCSP_check_validity.HANDLE; + } + + /** + * Address for: + * {@snippet lang=c : + * int OCSP_check_validity(ASN1_GENERALIZEDTIME *thisupd, ASN1_GENERALIZEDTIME *nextupd, long sec, long maxsec) + * } + */ + public static MemorySegment OCSP_check_validity$address() { + return OCSP_check_validity.ADDR; } /** * {@snippet lang=c : - * int ENGINE_free(ENGINE *e) + * int OCSP_check_validity(ASN1_GENERALIZEDTIME *thisupd, ASN1_GENERALIZEDTIME *nextupd, long sec, long maxsec) * } */ - public static int ENGINE_free(MemorySegment e) { - var mh$ = ENGINE_free$MH(); + public static int OCSP_check_validity(MemorySegment thisupd, MemorySegment nextupd, long sec, long maxsec) { + var mh$ = OCSP_check_validity.HANDLE; try { if (TRACE_DOWNCALLS) { - traceDowncall("ENGINE_free", e); + traceDowncall("OCSP_check_validity", thisupd, nextupd, sec, maxsec); } - return (int) mh$.invokeExact(e); + return (int)mh$.invokeExact(thisupd, nextupd, sec, maxsec); + } catch (Error | RuntimeException ex) { + throw ex; } catch (Throwable ex$) { throw new AssertionError("should not reach here", ex$); } } - private static MethodHandle ENGINE_load_private_key$MH() { - class Holder { - static final FunctionDescriptor DESC = FunctionDescriptor.of( - openssl_h.C_POINTER, - openssl_h.C_POINTER, - openssl_h.C_POINTER, - openssl_h.C_POINTER, - openssl_h.C_POINTER - ); - - static final MethodHandle MH = Linker.nativeLinker().downcallHandle( - openssl_h.findOrThrow("ENGINE_load_private_key"), - DESC); - } - return Holder.MH; + private static class OCSP_request_add1_nonce { + public static final FunctionDescriptor DESC = FunctionDescriptor.of( + openssl_h.C_INT, + openssl_h.C_POINTER, + ValueLayout.JAVA_CHAR, + openssl_h.C_INT + ); + + public static final MemorySegment ADDR = openssl_h.findOrThrow("OCSP_request_add1_nonce"); + + public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); } /** + * Function descriptor for: * {@snippet lang=c : - * EVP_PKEY *ENGINE_load_private_key(ENGINE *e, const char *key_id, UI_METHOD *ui_method, void *callback_data) + * int OCSP_request_add1_nonce(OCSP_REQUEST *req, unsigned char *val, int len) * } */ - public static MemorySegment ENGINE_load_private_key(MemorySegment e, MemorySegment key_id, MemorySegment ui_method, MemorySegment callback_data) { - var mh$ = ENGINE_load_private_key$MH(); + public static FunctionDescriptor OCSP_request_add1_nonce$descriptor() { + return OCSP_request_add1_nonce.DESC; + } + + /** + * Downcall method handle for: + * {@snippet lang=c : + * int OCSP_request_add1_nonce(OCSP_REQUEST *req, unsigned char *val, int len) + * } + */ + public static MethodHandle OCSP_request_add1_nonce$handle() { + return OCSP_request_add1_nonce.HANDLE; + } + + /** + * Address for: + * {@snippet lang=c : + * int OCSP_request_add1_nonce(OCSP_REQUEST *req, unsigned char *val, int len) + * } + */ + public static MemorySegment OCSP_request_add1_nonce$address() { + return OCSP_request_add1_nonce.ADDR; + } + + /** + * {@snippet lang=c : + * int OCSP_request_add1_nonce(OCSP_REQUEST *req, unsigned char *val, int len) + * } + */ + public static int OCSP_request_add1_nonce(MemorySegment req, char val, int len) { + var mh$ = OCSP_request_add1_nonce.HANDLE; try { if (TRACE_DOWNCALLS) { - traceDowncall("ENGINE_load_private_key", e, key_id, ui_method, callback_data); + traceDowncall("OCSP_request_add1_nonce", req, val, len); } - return (MemorySegment) mh$.invokeExact(e, key_id, ui_method, callback_data); + return (int)mh$.invokeExact(req, val, len); + } catch (Error | RuntimeException ex) { + throw ex; } catch (Throwable ex$) { throw new AssertionError("should not reach here", ex$); } } - private static MethodHandle ENGINE_set_default$MH() { - class Holder { - static final FunctionDescriptor DESC = FunctionDescriptor.of( - openssl_h.C_INT, - openssl_h.C_POINTER, - openssl_h.C_INT - ); - - static final MethodHandle MH = Linker.nativeLinker().downcallHandle( - openssl_h.findOrThrow("ENGINE_set_default"), - DESC); - } - return Holder.MH; + private static class OCSP_check_nonce { + public static final FunctionDescriptor DESC = FunctionDescriptor.of( + openssl_h.C_INT, + openssl_h.C_POINTER, + openssl_h.C_POINTER + ); + + public static final MemorySegment ADDR = openssl_h.findOrThrow("OCSP_check_nonce"); + + public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); + } + + /** + * Function descriptor for: + * {@snippet lang=c : + * int OCSP_check_nonce(OCSP_REQUEST *req, OCSP_BASICRESP *bs) + * } + */ + public static FunctionDescriptor OCSP_check_nonce$descriptor() { + return OCSP_check_nonce.DESC; + } + + /** + * Downcall method handle for: + * {@snippet lang=c : + * int OCSP_check_nonce(OCSP_REQUEST *req, OCSP_BASICRESP *bs) + * } + */ + public static MethodHandle OCSP_check_nonce$handle() { + return OCSP_check_nonce.HANDLE; + } + + /** + * Address for: + * {@snippet lang=c : + * int OCSP_check_nonce(OCSP_REQUEST *req, OCSP_BASICRESP *bs) + * } + */ + public static MemorySegment OCSP_check_nonce$address() { + return OCSP_check_nonce.ADDR; } /** * {@snippet lang=c : - * int ENGINE_set_default(ENGINE *e, unsigned int flags) + * int OCSP_check_nonce(OCSP_REQUEST *req, OCSP_BASICRESP *bs) * } */ - public static int ENGINE_set_default(MemorySegment e, int flags) { - var mh$ = ENGINE_set_default$MH(); + public static int OCSP_check_nonce(MemorySegment req, MemorySegment bs) { + var mh$ = OCSP_check_nonce.HANDLE; try { if (TRACE_DOWNCALLS) { - traceDowncall("ENGINE_set_default", e, flags); + traceDowncall("OCSP_check_nonce", req, bs); } - return (int) mh$.invokeExact(e, flags); + return (int)mh$.invokeExact(req, bs); + } catch (Error | RuntimeException ex) { + throw ex; } catch (Throwable ex$) { throw new AssertionError("should not reach here", ex$); } } - private static MethodHandle OCSP_cert_to_id$MH() { - class Holder { - static final FunctionDescriptor DESC = FunctionDescriptor.of( - openssl_h.C_POINTER, - openssl_h.C_POINTER, - openssl_h.C_POINTER, - openssl_h.C_POINTER - ); - - static final MethodHandle MH = Linker.nativeLinker().downcallHandle( - openssl_h.findOrThrow("OCSP_cert_to_id"), - DESC); - } - return Holder.MH; + private static class OCSP_cert_to_id { + public static final FunctionDescriptor DESC = FunctionDescriptor.of(openssl_h.C_POINTER, openssl_h.C_POINTER, + openssl_h.C_POINTER, openssl_h.C_POINTER); + + public static final MemorySegment ADDR = openssl_h.findOrThrow("OCSP_cert_to_id"); + + public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); } /** - * {@snippet lang=c : - * OCSP_CERTID *OCSP_cert_to_id(const EVP_MD *dgst, const X509 *subject, const X509 *issuer) + * Function descriptor for: + * {@snippet lang = c : * OCSP_CERTID *OCSP_cert_to_id(const EVP_MD *dgst, const X509 *subject, const X509 *issuer) + * } + */ + public static FunctionDescriptor OCSP_cert_to_id$descriptor() { + return OCSP_cert_to_id.DESC; + } + + /** + * Downcall method handle for: + * {@snippet lang = c : * OCSP_CERTID *OCSP_cert_to_id(const EVP_MD *dgst, const X509 *subject, const X509 *issuer) + * } + */ + public static MethodHandle OCSP_cert_to_id$handle() { + return OCSP_cert_to_id.HANDLE; + } + + /** + * Address for: + * {@snippet lang = c : * OCSP_CERTID *OCSP_cert_to_id(const EVP_MD *dgst, const X509 *subject, const X509 *issuer) + * } + */ + public static MemorySegment OCSP_cert_to_id$address() { + return OCSP_cert_to_id.ADDR; + } + + /** + * {@snippet lang = c : * OCSP_CERTID *OCSP_cert_to_id(const EVP_MD *dgst, const X509 *subject, const X509 *issuer) * } */ public static MemorySegment OCSP_cert_to_id(MemorySegment dgst, MemorySegment subject, MemorySegment issuer) { - var mh$ = OCSP_cert_to_id$MH(); + var mh$ = OCSP_cert_to_id.HANDLE; try { if (TRACE_DOWNCALLS) { traceDowncall("OCSP_cert_to_id", dgst, subject, issuer); } return (MemorySegment) mh$.invokeExact(dgst, subject, issuer); } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); + throw new AssertionError("should not reach here", ex$); } } - private static MethodHandle OCSP_request_add0_id$MH() { - class Holder { - static final FunctionDescriptor DESC = FunctionDescriptor.of( - openssl_h.C_POINTER, - openssl_h.C_POINTER, - openssl_h.C_POINTER - ); - - static final MethodHandle MH = Linker.nativeLinker().downcallHandle( - openssl_h.findOrThrow("OCSP_request_add0_id"), - DESC); - } - return Holder.MH; + private static class OCSP_request_add0_id { + public static final FunctionDescriptor DESC = + FunctionDescriptor.of(openssl_h.C_POINTER, openssl_h.C_POINTER, openssl_h.C_POINTER); + + public static final MemorySegment ADDR = openssl_h.findOrThrow("OCSP_request_add0_id"); + + public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); } /** - * {@snippet lang=c : - * OCSP_ONEREQ *OCSP_request_add0_id(OCSP_REQUEST *req, OCSP_CERTID *cid) + * Function descriptor for: + * {@snippet lang = c : * OCSP_ONEREQ *OCSP_request_add0_id(OCSP_REQUEST *req, OCSP_CERTID *cid) + * } + */ + public static FunctionDescriptor OCSP_request_add0_id$descriptor() { + return OCSP_request_add0_id.DESC; + } + + /** + * Downcall method handle for: + * {@snippet lang = c : * OCSP_ONEREQ *OCSP_request_add0_id(OCSP_REQUEST *req, OCSP_CERTID *cid) + * } + */ + public static MethodHandle OCSP_request_add0_id$handle() { + return OCSP_request_add0_id.HANDLE; + } + + /** + * Address for: + * {@snippet lang = c : * OCSP_ONEREQ *OCSP_request_add0_id(OCSP_REQUEST *req, OCSP_CERTID *cid) + * } + */ + public static MemorySegment OCSP_request_add0_id$address() { + return OCSP_request_add0_id.ADDR; + } + + /** + * {@snippet lang = c : * OCSP_ONEREQ *OCSP_request_add0_id(OCSP_REQUEST *req, OCSP_CERTID *cid) * } */ public static MemorySegment OCSP_request_add0_id(MemorySegment req, MemorySegment cid) { - var mh$ = OCSP_request_add0_id$MH(); + var mh$ = OCSP_request_add0_id.HANDLE; try { if (TRACE_DOWNCALLS) { traceDowncall("OCSP_request_add0_id", req, cid); } return (MemorySegment) mh$.invokeExact(req, cid); } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); + throw new AssertionError("should not reach here", ex$); } } - private static MethodHandle OCSP_response_status$MH() { - class Holder { - static final FunctionDescriptor DESC = FunctionDescriptor.of( - openssl_h.C_INT, - openssl_h.C_POINTER - ); - - static final MethodHandle MH = Linker.nativeLinker().downcallHandle( - openssl_h.findOrThrow("OCSP_response_status"), - DESC); - } - return Holder.MH; + private static class OCSP_response_status { + public static final FunctionDescriptor DESC = FunctionDescriptor.of(openssl_h.C_INT, openssl_h.C_POINTER); + + public static final MemorySegment ADDR = openssl_h.findOrThrow("OCSP_response_status"); + + public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); } /** - * {@snippet lang=c : - * int OCSP_response_status(OCSP_RESPONSE *resp) + * Function descriptor for: + * {@snippet lang = c : * int OCSP_response_status(OCSP_RESPONSE *resp) + * } + */ + public static FunctionDescriptor OCSP_response_status$descriptor() { + return OCSP_response_status.DESC; + } + + /** + * Downcall method handle for: + * {@snippet lang = c : * int OCSP_response_status(OCSP_RESPONSE *resp) + * } + */ + public static MethodHandle OCSP_response_status$handle() { + return OCSP_response_status.HANDLE; + } + + /** + * Address for: + * {@snippet lang = c : * int OCSP_response_status(OCSP_RESPONSE *resp) + * } + */ + public static MemorySegment OCSP_response_status$address() { + return OCSP_response_status.ADDR; + } + + /** + * {@snippet lang = c : * int OCSP_response_status(OCSP_RESPONSE *resp) * } */ public static int OCSP_response_status(MemorySegment resp) { - var mh$ = OCSP_response_status$MH(); + var mh$ = OCSP_response_status.HANDLE; try { if (TRACE_DOWNCALLS) { traceDowncall("OCSP_response_status", resp); } return (int) mh$.invokeExact(resp); } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); + throw new AssertionError("should not reach here", ex$); } } - private static MethodHandle OCSP_response_get1_basic$MH() { - class Holder { - static final FunctionDescriptor DESC = FunctionDescriptor.of( - openssl_h.C_POINTER, - openssl_h.C_POINTER - ); - - static final MethodHandle MH = Linker.nativeLinker().downcallHandle( - openssl_h.findOrThrow("OCSP_response_get1_basic"), - DESC); - } - return Holder.MH; + private static class OCSP_response_get1_basic { + public static final FunctionDescriptor DESC = FunctionDescriptor.of(openssl_h.C_POINTER, openssl_h.C_POINTER); + + public static final MemorySegment ADDR = openssl_h.findOrThrow("OCSP_response_get1_basic"); + + public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); } /** - * {@snippet lang=c : - * OCSP_BASICRESP *OCSP_response_get1_basic(OCSP_RESPONSE *resp) + * Function descriptor for: + * {@snippet lang = c : * OCSP_BASICRESP *OCSP_response_get1_basic(OCSP_RESPONSE *resp) + * } + */ + public static FunctionDescriptor OCSP_response_get1_basic$descriptor() { + return OCSP_response_get1_basic.DESC; + } + + /** + * Downcall method handle for: + * {@snippet lang = c : * OCSP_BASICRESP *OCSP_response_get1_basic(OCSP_RESPONSE *resp) + * } + */ + public static MethodHandle OCSP_response_get1_basic$handle() { + return OCSP_response_get1_basic.HANDLE; + } + + /** + * Address for: + * {@snippet lang = c : * OCSP_BASICRESP *OCSP_response_get1_basic(OCSP_RESPONSE *resp) + * } + */ + public static MemorySegment OCSP_response_get1_basic$address() { + return OCSP_response_get1_basic.ADDR; + } + + /** + * {@snippet lang = c : * OCSP_BASICRESP *OCSP_response_get1_basic(OCSP_RESPONSE *resp) * } */ public static MemorySegment OCSP_response_get1_basic(MemorySegment resp) { - var mh$ = OCSP_response_get1_basic$MH(); + var mh$ = OCSP_response_get1_basic.HANDLE; try { if (TRACE_DOWNCALLS) { traceDowncall("OCSP_response_get1_basic", resp); } return (MemorySegment) mh$.invokeExact(resp); } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); + throw new AssertionError("should not reach here", ex$); } } - private static MethodHandle OCSP_resp_get0$MH() { - class Holder { - static final FunctionDescriptor DESC = FunctionDescriptor.of( - openssl_h.C_POINTER, - openssl_h.C_POINTER, - openssl_h.C_INT - ); - - static final MethodHandle MH = Linker.nativeLinker().downcallHandle( - openssl_h.findOrThrow("OCSP_resp_get0"), - DESC); - } - return Holder.MH; + private static class OCSP_resp_get0 { + public static final FunctionDescriptor DESC = + FunctionDescriptor.of(openssl_h.C_POINTER, openssl_h.C_POINTER, openssl_h.C_INT); + + public static final MemorySegment ADDR = openssl_h.findOrThrow("OCSP_resp_get0"); + + public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); } /** - * {@snippet lang=c : - * OCSP_SINGLERESP *OCSP_resp_get0(OCSP_BASICRESP *bs, int idx) + * Function descriptor for: + * {@snippet lang = c : * OCSP_SINGLERESP *OCSP_resp_get0(OCSP_BASICRESP *bs, int idx) + * } + */ + public static FunctionDescriptor OCSP_resp_get0$descriptor() { + return OCSP_resp_get0.DESC; + } + + /** + * Downcall method handle for: + * {@snippet lang = c : * OCSP_SINGLERESP *OCSP_resp_get0(OCSP_BASICRESP *bs, int idx) + * } + */ + public static MethodHandle OCSP_resp_get0$handle() { + return OCSP_resp_get0.HANDLE; + } + + /** + * Address for: + * {@snippet lang = c : * OCSP_SINGLERESP *OCSP_resp_get0(OCSP_BASICRESP *bs, int idx) + * } + */ + public static MemorySegment OCSP_resp_get0$address() { + return OCSP_resp_get0.ADDR; + } + + /** + * {@snippet lang = c : * OCSP_SINGLERESP *OCSP_resp_get0(OCSP_BASICRESP *bs, int idx) * } */ public static MemorySegment OCSP_resp_get0(MemorySegment bs, int idx) { - var mh$ = OCSP_resp_get0$MH(); + var mh$ = OCSP_resp_get0.HANDLE; try { if (TRACE_DOWNCALLS) { traceDowncall("OCSP_resp_get0", bs, idx); } return (MemorySegment) mh$.invokeExact(bs, idx); } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); + throw new AssertionError("should not reach here", ex$); } } - private static MethodHandle OCSP_resp_find$MH() { - class Holder { - static final FunctionDescriptor DESC = FunctionDescriptor.of( - openssl_h.C_INT, - openssl_h.C_POINTER, - openssl_h.C_POINTER, - openssl_h.C_INT - ); - - static final MethodHandle MH = Linker.nativeLinker().downcallHandle( - openssl_h.findOrThrow("OCSP_resp_find"), - DESC); - } - return Holder.MH; + private static class OCSP_resp_find { + public static final FunctionDescriptor DESC = + FunctionDescriptor.of(openssl_h.C_INT, openssl_h.C_POINTER, openssl_h.C_POINTER, openssl_h.C_INT); + + public static final MemorySegment ADDR = openssl_h.findOrThrow("OCSP_resp_find"); + + public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); } /** - * {@snippet lang=c : - * int OCSP_resp_find(OCSP_BASICRESP *bs, OCSP_CERTID *id, int last) + * Function descriptor for: + * {@snippet lang = c : * int OCSP_resp_find(OCSP_BASICRESP *bs, OCSP_CERTID *id, int last) + * } + */ + public static FunctionDescriptor OCSP_resp_find$descriptor() { + return OCSP_resp_find.DESC; + } + + /** + * Downcall method handle for: + * {@snippet lang = c : * int OCSP_resp_find(OCSP_BASICRESP *bs, OCSP_CERTID *id, int last) + * } + */ + public static MethodHandle OCSP_resp_find$handle() { + return OCSP_resp_find.HANDLE; + } + + /** + * Address for: + * {@snippet lang = c : * int OCSP_resp_find(OCSP_BASICRESP *bs, OCSP_CERTID *id, int last) + * } + */ + public static MemorySegment OCSP_resp_find$address() { + return OCSP_resp_find.ADDR; + } + + /** + * {@snippet lang = c : * int OCSP_resp_find(OCSP_BASICRESP *bs, OCSP_CERTID *id, int last) * } */ public static int OCSP_resp_find(MemorySegment bs, MemorySegment id, int last) { - var mh$ = OCSP_resp_find$MH(); + var mh$ = OCSP_resp_find.HANDLE; try { if (TRACE_DOWNCALLS) { traceDowncall("OCSP_resp_find", bs, id, last); } return (int) mh$.invokeExact(bs, id, last); } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); + throw new AssertionError("should not reach here", ex$); } } - private static MethodHandle OCSP_single_get0_status$MH() { - class Holder { - static final FunctionDescriptor DESC = FunctionDescriptor.of( - openssl_h.C_INT, - openssl_h.C_POINTER, - openssl_h.C_POINTER, - openssl_h.C_POINTER, - openssl_h.C_POINTER, - openssl_h.C_POINTER - ); - - static final MethodHandle MH = Linker.nativeLinker().downcallHandle( - openssl_h.findOrThrow("OCSP_single_get0_status"), - DESC); - } - return Holder.MH; + private static class OCSP_single_get0_status { + public static final FunctionDescriptor DESC = FunctionDescriptor.of(openssl_h.C_INT, openssl_h.C_POINTER, + openssl_h.C_POINTER, openssl_h.C_POINTER, openssl_h.C_POINTER, openssl_h.C_POINTER); + + public static final MemorySegment ADDR = openssl_h.findOrThrow("OCSP_single_get0_status"); + + public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); } /** - * {@snippet lang=c : - * int OCSP_single_get0_status(OCSP_SINGLERESP *single, int *reason, ASN1_GENERALIZEDTIME **revtime, ASN1_GENERALIZEDTIME **thisupd, ASN1_GENERALIZEDTIME **nextupd) + * Function descriptor for: + * {@snippet lang = c + * : * int OCSP_single_get0_status(OCSP_SINGLERESP *single, int *reason, ASN1_GENERALIZEDTIME **revtime, ASN1_GENERALIZEDTIME **thisupd, ASN1_GENERALIZEDTIME **nextupd) + * } + */ + public static FunctionDescriptor OCSP_single_get0_status$descriptor() { + return OCSP_single_get0_status.DESC; + } + + /** + * Downcall method handle for: + * {@snippet lang = c + * : * int OCSP_single_get0_status(OCSP_SINGLERESP *single, int *reason, ASN1_GENERALIZEDTIME **revtime, ASN1_GENERALIZEDTIME **thisupd, ASN1_GENERALIZEDTIME **nextupd) + * } + */ + public static MethodHandle OCSP_single_get0_status$handle() { + return OCSP_single_get0_status.HANDLE; + } + + /** + * Address for: + * {@snippet lang = c + * : * int OCSP_single_get0_status(OCSP_SINGLERESP *single, int *reason, ASN1_GENERALIZEDTIME **revtime, ASN1_GENERALIZEDTIME **thisupd, ASN1_GENERALIZEDTIME **nextupd) + * } + */ + public static MemorySegment OCSP_single_get0_status$address() { + return OCSP_single_get0_status.ADDR; + } + + /** + * {@snippet lang = c + * : * int OCSP_single_get0_status(OCSP_SINGLERESP *single, int *reason, ASN1_GENERALIZEDTIME **revtime, ASN1_GENERALIZEDTIME **thisupd, ASN1_GENERALIZEDTIME **nextupd) * } */ - public static int OCSP_single_get0_status(MemorySegment single, MemorySegment reason, MemorySegment revtime, MemorySegment thisupd, MemorySegment nextupd) { - var mh$ = OCSP_single_get0_status$MH(); + public static int OCSP_single_get0_status(MemorySegment single, MemorySegment reason, MemorySegment revtime, + MemorySegment thisupd, MemorySegment nextupd) { + var mh$ = OCSP_single_get0_status.HANDLE; try { if (TRACE_DOWNCALLS) { traceDowncall("OCSP_single_get0_status", single, reason, revtime, thisupd, nextupd); } return (int) mh$.invokeExact(single, reason, revtime, thisupd, nextupd); } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); + throw new AssertionError("should not reach here", ex$); } } - private static MethodHandle OCSP_BASICRESP_free$MH() { - class Holder { - static final FunctionDescriptor DESC = FunctionDescriptor.ofVoid( - openssl_h.C_POINTER - ); - - static final MethodHandle MH = Linker.nativeLinker().downcallHandle( - openssl_h.findOrThrow("OCSP_BASICRESP_free"), - DESC); - } - return Holder.MH; + private static class OCSP_BASICRESP_free { + public static final FunctionDescriptor DESC = FunctionDescriptor.ofVoid(openssl_h.C_POINTER); + + public static final MemorySegment ADDR = openssl_h.findOrThrow("OCSP_BASICRESP_free"); + + public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); } /** - * {@snippet lang=c : - * extern void OCSP_BASICRESP_free(OCSP_BASICRESP *a) + * Function descriptor for: + * {@snippet lang = c : * extern void OCSP_BASICRESP_free(OCSP_BASICRESP *a) + * } + */ + public static FunctionDescriptor OCSP_BASICRESP_free$descriptor() { + return OCSP_BASICRESP_free.DESC; + } + + /** + * Downcall method handle for: + * {@snippet lang = c : * extern void OCSP_BASICRESP_free(OCSP_BASICRESP *a) + * } + */ + public static MethodHandle OCSP_BASICRESP_free$handle() { + return OCSP_BASICRESP_free.HANDLE; + } + + /** + * Address for: + * {@snippet lang = c : * extern void OCSP_BASICRESP_free(OCSP_BASICRESP *a) + * } + */ + public static MemorySegment OCSP_BASICRESP_free$address() { + return OCSP_BASICRESP_free.ADDR; + } + + /** + * {@snippet lang = c : * extern void OCSP_BASICRESP_free(OCSP_BASICRESP *a) * } */ public static void OCSP_BASICRESP_free(MemorySegment a) { - var mh$ = OCSP_BASICRESP_free$MH(); + var mh$ = OCSP_BASICRESP_free.HANDLE; try { if (TRACE_DOWNCALLS) { traceDowncall("OCSP_BASICRESP_free", a); } mh$.invokeExact(a); } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); + throw new AssertionError("should not reach here", ex$); } } - private static MethodHandle OCSP_RESPONSE_free$MH() { - class Holder { - static final FunctionDescriptor DESC = FunctionDescriptor.ofVoid( - openssl_h.C_POINTER - ); - - static final MethodHandle MH = Linker.nativeLinker().downcallHandle( - openssl_h.findOrThrow("OCSP_RESPONSE_free"), - DESC); - } - return Holder.MH; + private static class OCSP_RESPONSE_free { + public static final FunctionDescriptor DESC = FunctionDescriptor.ofVoid(openssl_h.C_POINTER); + + public static final MemorySegment ADDR = openssl_h.findOrThrow("OCSP_RESPONSE_free"); + + public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); } /** - * {@snippet lang=c : - * extern void OCSP_RESPONSE_free(OCSP_RESPONSE *a) + * Function descriptor for: + * {@snippet lang = c : * extern void OCSP_RESPONSE_free(OCSP_RESPONSE *a) + * } + */ + public static FunctionDescriptor OCSP_RESPONSE_free$descriptor() { + return OCSP_RESPONSE_free.DESC; + } + + /** + * Downcall method handle for: + * {@snippet lang = c : * extern void OCSP_RESPONSE_free(OCSP_RESPONSE *a) + * } + */ + public static MethodHandle OCSP_RESPONSE_free$handle() { + return OCSP_RESPONSE_free.HANDLE; + } + + /** + * Address for: + * {@snippet lang = c : * extern void OCSP_RESPONSE_free(OCSP_RESPONSE *a) + * } + */ + public static MemorySegment OCSP_RESPONSE_free$address() { + return OCSP_RESPONSE_free.ADDR; + } + + /** + * {@snippet lang = c : * extern void OCSP_RESPONSE_free(OCSP_RESPONSE *a) * } */ public static void OCSP_RESPONSE_free(MemorySegment a) { - var mh$ = OCSP_RESPONSE_free$MH(); + var mh$ = OCSP_RESPONSE_free.HANDLE; try { if (TRACE_DOWNCALLS) { traceDowncall("OCSP_RESPONSE_free", a); } mh$.invokeExact(a); } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); + throw new AssertionError("should not reach here", ex$); } } - private static MethodHandle d2i_OCSP_RESPONSE$MH() { - class Holder { - static final FunctionDescriptor DESC = FunctionDescriptor.of( - openssl_h.C_POINTER, - openssl_h.C_POINTER, - openssl_h.C_POINTER, - openssl_h.C_LONG - ); - - static final MethodHandle MH = Linker.nativeLinker().downcallHandle( - openssl_h.findOrThrow("d2i_OCSP_RESPONSE"), - DESC); - } - return Holder.MH; + private static class d2i_OCSP_RESPONSE { + public static final FunctionDescriptor DESC = + FunctionDescriptor.of(openssl_h.C_POINTER, openssl_h.C_POINTER, openssl_h.C_POINTER, openssl_h.C_LONG); + + public static final MemorySegment ADDR = openssl_h.findOrThrow("d2i_OCSP_RESPONSE"); + + public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); } /** - * {@snippet lang=c : - * extern OCSP_RESPONSE *d2i_OCSP_RESPONSE(OCSP_RESPONSE **a, const unsigned char **in, long len) + * Function descriptor for: + * {@snippet lang = c + * : * extern OCSP_RESPONSE *d2i_OCSP_RESPONSE(OCSP_RESPONSE **a, const unsigned char **in, long len) + * } + */ + public static FunctionDescriptor d2i_OCSP_RESPONSE$descriptor() { + return d2i_OCSP_RESPONSE.DESC; + } + + /** + * Downcall method handle for: + * {@snippet lang = c + * : * extern OCSP_RESPONSE *d2i_OCSP_RESPONSE(OCSP_RESPONSE **a, const unsigned char **in, long len) + * } + */ + public static MethodHandle d2i_OCSP_RESPONSE$handle() { + return d2i_OCSP_RESPONSE.HANDLE; + } + + /** + * Address for: + * {@snippet lang = c + * : * extern OCSP_RESPONSE *d2i_OCSP_RESPONSE(OCSP_RESPONSE **a, const unsigned char **in, long len) + * } + */ + public static MemorySegment d2i_OCSP_RESPONSE$address() { + return d2i_OCSP_RESPONSE.ADDR; + } + + /** + * {@snippet lang = c + * : * extern OCSP_RESPONSE *d2i_OCSP_RESPONSE(OCSP_RESPONSE **a, const unsigned char **in, long len) * } */ public static MemorySegment d2i_OCSP_RESPONSE(MemorySegment a, MemorySegment in, long len) { - var mh$ = d2i_OCSP_RESPONSE$MH(); + var mh$ = d2i_OCSP_RESPONSE.HANDLE; try { if (TRACE_DOWNCALLS) { traceDowncall("d2i_OCSP_RESPONSE", a, in, len); } return (MemorySegment) mh$.invokeExact(a, in, len); } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); + throw new AssertionError("should not reach here", ex$); } } - private static MethodHandle OCSP_CERTID_free$MH() { - class Holder { - static final FunctionDescriptor DESC = FunctionDescriptor.ofVoid( - openssl_h.C_POINTER - ); - - static final MethodHandle MH = Linker.nativeLinker().downcallHandle( - openssl_h.findOrThrow("OCSP_CERTID_free"), - DESC); - } - return Holder.MH; + private static class OCSP_CERTID_free { + public static final FunctionDescriptor DESC = FunctionDescriptor.ofVoid(openssl_h.C_POINTER); + + public static final MemorySegment ADDR = openssl_h.findOrThrow("OCSP_CERTID_free"); + + public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); } /** - * {@snippet lang=c : - * extern void OCSP_CERTID_free(OCSP_CERTID *a) + * Function descriptor for: + * {@snippet lang = c : * extern void OCSP_CERTID_free(OCSP_CERTID *a) + * } + */ + public static FunctionDescriptor OCSP_CERTID_free$descriptor() { + return OCSP_CERTID_free.DESC; + } + + /** + * Downcall method handle for: + * {@snippet lang = c : * extern void OCSP_CERTID_free(OCSP_CERTID *a) + * } + */ + public static MethodHandle OCSP_CERTID_free$handle() { + return OCSP_CERTID_free.HANDLE; + } + + /** + * Address for: + * {@snippet lang = c : * extern void OCSP_CERTID_free(OCSP_CERTID *a) + * } + */ + public static MemorySegment OCSP_CERTID_free$address() { + return OCSP_CERTID_free.ADDR; + } + + /** + * {@snippet lang = c : * extern void OCSP_CERTID_free(OCSP_CERTID *a) * } */ public static void OCSP_CERTID_free(MemorySegment a) { - var mh$ = OCSP_CERTID_free$MH(); + var mh$ = OCSP_CERTID_free.HANDLE; try { if (TRACE_DOWNCALLS) { traceDowncall("OCSP_CERTID_free", a); } mh$.invokeExact(a); } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); + throw new AssertionError("should not reach here", ex$); } } - private static MethodHandle OCSP_REQUEST_new$MH() { - class Holder { - static final FunctionDescriptor DESC = FunctionDescriptor.of( - openssl_h.C_POINTER ); + private static class OCSP_REQUEST_new { + public static final FunctionDescriptor DESC = FunctionDescriptor.of(openssl_h.C_POINTER); - static final MethodHandle MH = Linker.nativeLinker().downcallHandle( - openssl_h.findOrThrow("OCSP_REQUEST_new"), - DESC); - } - return Holder.MH; + public static final MemorySegment ADDR = openssl_h.findOrThrow("OCSP_REQUEST_new"); + + public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); } /** - * {@snippet lang=c : - * extern OCSP_REQUEST *OCSP_REQUEST_new(void) + * Function descriptor for: + * {@snippet lang = c : * extern OCSP_REQUEST *OCSP_REQUEST_new() + * } + */ + public static FunctionDescriptor OCSP_REQUEST_new$descriptor() { + return OCSP_REQUEST_new.DESC; + } + + /** + * Downcall method handle for: + * {@snippet lang = c : * extern OCSP_REQUEST *OCSP_REQUEST_new() + * } + */ + public static MethodHandle OCSP_REQUEST_new$handle() { + return OCSP_REQUEST_new.HANDLE; + } + + /** + * Address for: + * {@snippet lang = c : * extern OCSP_REQUEST *OCSP_REQUEST_new() + * } + */ + public static MemorySegment OCSP_REQUEST_new$address() { + return OCSP_REQUEST_new.ADDR; + } + + /** + * {@snippet lang = c : * extern OCSP_REQUEST *OCSP_REQUEST_new() * } */ public static MemorySegment OCSP_REQUEST_new() { - var mh$ = OCSP_REQUEST_new$MH(); + var mh$ = OCSP_REQUEST_new.HANDLE; try { if (TRACE_DOWNCALLS) { traceDowncall("OCSP_REQUEST_new"); } return (MemorySegment) mh$.invokeExact(); } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); + throw new AssertionError("should not reach here", ex$); } } - private static MethodHandle OCSP_REQUEST_free$MH() { - class Holder { - static final FunctionDescriptor DESC = FunctionDescriptor.ofVoid( - openssl_h.C_POINTER - ); - - static final MethodHandle MH = Linker.nativeLinker().downcallHandle( - openssl_h.findOrThrow("OCSP_REQUEST_free"), - DESC); - } - return Holder.MH; + private static class OCSP_REQUEST_free { + public static final FunctionDescriptor DESC = FunctionDescriptor.ofVoid(openssl_h.C_POINTER); + + public static final MemorySegment ADDR = openssl_h.findOrThrow("OCSP_REQUEST_free"); + + public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); } /** - * {@snippet lang=c : - * extern void OCSP_REQUEST_free(OCSP_REQUEST *a) + * Function descriptor for: + * {@snippet lang = c : * extern void OCSP_REQUEST_free(OCSP_REQUEST *a) + * } + */ + public static FunctionDescriptor OCSP_REQUEST_free$descriptor() { + return OCSP_REQUEST_free.DESC; + } + + /** + * Downcall method handle for: + * {@snippet lang = c : * extern void OCSP_REQUEST_free(OCSP_REQUEST *a) + * } + */ + public static MethodHandle OCSP_REQUEST_free$handle() { + return OCSP_REQUEST_free.HANDLE; + } + + /** + * Address for: + * {@snippet lang = c : * extern void OCSP_REQUEST_free(OCSP_REQUEST *a) + * } + */ + public static MemorySegment OCSP_REQUEST_free$address() { + return OCSP_REQUEST_free.ADDR; + } + + /** + * {@snippet lang = c : * extern void OCSP_REQUEST_free(OCSP_REQUEST *a) * } */ public static void OCSP_REQUEST_free(MemorySegment a) { - var mh$ = OCSP_REQUEST_free$MH(); + var mh$ = OCSP_REQUEST_free.HANDLE; try { if (TRACE_DOWNCALLS) { traceDowncall("OCSP_REQUEST_free", a); } mh$.invokeExact(a); } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); + throw new AssertionError("should not reach here", ex$); } } - private static MethodHandle i2d_OCSP_REQUEST$MH() { - class Holder { - static final FunctionDescriptor DESC = FunctionDescriptor.of( - openssl_h.C_INT, - openssl_h.C_POINTER, - openssl_h.C_POINTER - ); - - static final MethodHandle MH = Linker.nativeLinker().downcallHandle( - openssl_h.findOrThrow("i2d_OCSP_REQUEST"), - DESC); - } - return Holder.MH; + private static class i2d_OCSP_REQUEST { + public static final FunctionDescriptor DESC = + FunctionDescriptor.of(openssl_h.C_INT, openssl_h.C_POINTER, openssl_h.C_POINTER); + + public static final MemorySegment ADDR = openssl_h.findOrThrow("i2d_OCSP_REQUEST"); + + public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); } /** - * {@snippet lang=c : - * extern int i2d_OCSP_REQUEST(const OCSP_REQUEST *a, unsigned char **out) + * Function descriptor for: + * {@snippet lang = c : * extern int i2d_OCSP_REQUEST(const OCSP_REQUEST *a, unsigned char **out) + * } + */ + public static FunctionDescriptor i2d_OCSP_REQUEST$descriptor() { + return i2d_OCSP_REQUEST.DESC; + } + + /** + * Downcall method handle for: + * {@snippet lang = c : * extern int i2d_OCSP_REQUEST(const OCSP_REQUEST *a, unsigned char **out) + * } + */ + public static MethodHandle i2d_OCSP_REQUEST$handle() { + return i2d_OCSP_REQUEST.HANDLE; + } + + /** + * Address for: + * {@snippet lang = c : * extern int i2d_OCSP_REQUEST(const OCSP_REQUEST *a, unsigned char **out) + * } + */ + public static MemorySegment i2d_OCSP_REQUEST$address() { + return i2d_OCSP_REQUEST.ADDR; + } + + /** + * {@snippet lang = c : * extern int i2d_OCSP_REQUEST(const OCSP_REQUEST *a, unsigned char **out) * } */ public static int i2d_OCSP_REQUEST(MemorySegment a, MemorySegment out) { - var mh$ = i2d_OCSP_REQUEST$MH(); + var mh$ = i2d_OCSP_REQUEST.HANDLE; try { if (TRACE_DOWNCALLS) { traceDowncall("i2d_OCSP_REQUEST", a, out); } return (int) mh$.invokeExact(a, out); } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); + throw new AssertionError("should not reach here", ex$); } } - private static MethodHandle OSSL_PROVIDER_get0_name$MH() { - class Holder { - static final FunctionDescriptor DESC = FunctionDescriptor.of( - openssl_h.C_POINTER, - openssl_h.C_POINTER - ); - - static final MethodHandle MH = Linker.nativeLinker().downcallHandle( - openssl_h.findOrThrow("OSSL_PROVIDER_get0_name"), - DESC); - } - return Holder.MH; + private static class OSSL_PROVIDER_get0_name { + public static final FunctionDescriptor DESC = FunctionDescriptor.of(openssl_h.C_POINTER, openssl_h.C_POINTER); + + public static final MemorySegment ADDR = openssl_h.findOrThrow("OSSL_PROVIDER_get0_name"); + + public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); } /** - * {@snippet lang=c : - * const char *OSSL_PROVIDER_get0_name(const OSSL_PROVIDER *prov) + * Function descriptor for: + * {@snippet lang = c : * const char *OSSL_PROVIDER_get0_name(const OSSL_PROVIDER *prov) + * } + */ + public static FunctionDescriptor OSSL_PROVIDER_get0_name$descriptor() { + return OSSL_PROVIDER_get0_name.DESC; + } + + /** + * Downcall method handle for: + * {@snippet lang = c : * const char *OSSL_PROVIDER_get0_name(const OSSL_PROVIDER *prov) + * } + */ + public static MethodHandle OSSL_PROVIDER_get0_name$handle() { + return OSSL_PROVIDER_get0_name.HANDLE; + } + + /** + * Address for: + * {@snippet lang = c : * const char *OSSL_PROVIDER_get0_name(const OSSL_PROVIDER *prov) + * } + */ + public static MemorySegment OSSL_PROVIDER_get0_name$address() { + return OSSL_PROVIDER_get0_name.ADDR; + } + + /** + * {@snippet lang = c : * const char *OSSL_PROVIDER_get0_name(const OSSL_PROVIDER *prov) * } */ public static MemorySegment OSSL_PROVIDER_get0_name(MemorySegment prov) { - var mh$ = OSSL_PROVIDER_get0_name$MH(); + var mh$ = OSSL_PROVIDER_get0_name.HANDLE; try { if (TRACE_DOWNCALLS) { traceDowncall("OSSL_PROVIDER_get0_name", prov); } return (MemorySegment) mh$.invokeExact(prov); } catch (Throwable ex$) { - throw new AssertionError("should not reach here", ex$); + throw new AssertionError("should not reach here", ex$); } } + /** - * {@snippet lang=c : - * #define OPENSSL_FILE "/tmp/jextract$7967504926277577155.h" + * {@snippet lang = c : * #define OPENSSL_FILE "jextract$macro.h" * } */ public static MemorySegment OPENSSL_FILE() { class Holder { - static final MemorySegment OPENSSL_FILE - = openssl_h.LIBRARY_ARENA.allocateFrom("/tmp/jextract$7967504926277577155.h"); + static final MemorySegment OPENSSL_FILE = openssl_h.LIBRARY_ARENA.allocateFrom("jextract$macro.h"); } return Holder.OPENSSL_FILE; } - private static final int OPENSSL_LINE = (int)50L; + + private static final int OPENSSL_LINE = (int) 58L; + /** - * {@snippet lang=c : - * #define OPENSSL_LINE 50 + * {@snippet lang = c : * #define OPENSSL_LINE 58 * } */ public static int OPENSSL_LINE() { return OPENSSL_LINE; } + private static final long OPENSSL_INIT_ENGINE_ALL_BUILTIN = 30208L; + /** - * {@snippet lang=c : - * #define OPENSSL_INIT_ENGINE_ALL_BUILTIN 30208 + * {@snippet lang = c : * #define OPENSSL_INIT_ENGINE_ALL_BUILTIN 30208 * } */ public static long OPENSSL_INIT_ENGINE_ALL_BUILTIN() { return OPENSSL_INIT_ENGINE_ALL_BUILTIN; } - private static final int EVP_PKEY_NONE = (int)0L; + + private static final int EVP_PKEY_NONE = (int) 0L; + /** - * {@snippet lang=c : - * #define EVP_PKEY_NONE 0 + * {@snippet lang = c : * #define EVP_PKEY_NONE 0 * } */ public static int EVP_PKEY_NONE() { return EVP_PKEY_NONE; } - private static final int EVP_PKEY_RSA = (int)6L; + + private static final int EVP_PKEY_RSA = (int) 6L; + /** - * {@snippet lang=c : - * #define EVP_PKEY_RSA 6 + * {@snippet lang = c : * #define EVP_PKEY_RSA 6 * } */ public static int EVP_PKEY_RSA() { return EVP_PKEY_RSA; } - private static final int EVP_PKEY_DSA = (int)116L; + + private static final int EVP_PKEY_DSA = (int) 116L; + /** - * {@snippet lang=c : - * #define EVP_PKEY_DSA 116 + * {@snippet lang = c : * #define EVP_PKEY_DSA 116 * } */ public static int EVP_PKEY_DSA() { return EVP_PKEY_DSA; } + /** - * {@snippet lang=c : - * #define PEM_STRING_ECPARAMETERS "EC PARAMETERS" + * {@snippet lang = c : * #define PEM_STRING_ECPARAMETERS "EC PARAMETERS" * } */ public static MemorySegment PEM_STRING_ECPARAMETERS() { class Holder { - static final MemorySegment PEM_STRING_ECPARAMETERS - = openssl_h.LIBRARY_ARENA.allocateFrom("EC PARAMETERS"); + static final MemorySegment PEM_STRING_ECPARAMETERS = openssl_h.LIBRARY_ARENA.allocateFrom("EC PARAMETERS"); } return Holder.PEM_STRING_ECPARAMETERS; } + private static final long SSL_OP_NO_TICKET = 16384L; + /** - * {@snippet lang=c : - * #define SSL_OP_NO_TICKET 16384 + * {@snippet lang = c : * #define SSL_OP_NO_TICKET 16384 * } */ public static long SSL_OP_NO_TICKET() { return SSL_OP_NO_TICKET; } + private static final long SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION = 65536L; + /** - * {@snippet lang=c : - * #define SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION 65536 + * {@snippet lang = c : * #define SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION 65536 * } */ public static long SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION() { return SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION; } + private static final long SSL_OP_NO_COMPRESSION = 131072L; + /** - * {@snippet lang=c : - * #define SSL_OP_NO_COMPRESSION 131072 + * {@snippet lang = c : * #define SSL_OP_NO_COMPRESSION 131072 * } */ public static long SSL_OP_NO_COMPRESSION() { return SSL_OP_NO_COMPRESSION; } + private static final long SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION = 262144L; + /** - * {@snippet lang=c : - * #define SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION 262144 + * {@snippet lang = c : * #define SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION 262144 * } */ public static long SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION() { return SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION; } + private static final long SSL_OP_CIPHER_SERVER_PREFERENCE = 4194304L; + /** - * {@snippet lang=c : - * #define SSL_OP_CIPHER_SERVER_PREFERENCE 4194304 + * {@snippet lang = c : * #define SSL_OP_CIPHER_SERVER_PREFERENCE 4194304 * } */ public static long SSL_OP_CIPHER_SERVER_PREFERENCE() { return SSL_OP_CIPHER_SERVER_PREFERENCE; } + private static final long SSL_OP_NO_SSLv3 = 33554432L; + /** - * {@snippet lang=c : - * #define SSL_OP_NO_SSLv3 33554432 + * {@snippet lang = c : * #define SSL_OP_NO_SSLv3 33554432 * } */ public static long SSL_OP_NO_SSLv3() { return SSL_OP_NO_SSLv3; } + private static final long SSL_OP_NO_TLSv1 = 67108864L; + /** - * {@snippet lang=c : - * #define SSL_OP_NO_TLSv1 67108864 + * {@snippet lang = c : * #define SSL_OP_NO_TLSv1 67108864 * } */ public static long SSL_OP_NO_TLSv1() { return SSL_OP_NO_TLSv1; } + private static final long SSL_OP_NO_TLSv1_2 = 134217728L; + /** - * {@snippet lang=c : - * #define SSL_OP_NO_TLSv1_2 134217728 + * {@snippet lang = c : * #define SSL_OP_NO_TLSv1_2 134217728 * } */ public static long SSL_OP_NO_TLSv1_2() { return SSL_OP_NO_TLSv1_2; } + private static final long SSL_OP_NO_TLSv1_1 = 268435456L; + /** - * {@snippet lang=c : - * #define SSL_OP_NO_TLSv1_1 268435456 + * {@snippet lang = c : * #define SSL_OP_NO_TLSv1_1 268435456 * } */ public static long SSL_OP_NO_TLSv1_1() { return SSL_OP_NO_TLSv1_1; } + private static final long SSL_OP_NO_TLSv1_3 = 536870912L; + /** - * {@snippet lang=c : - * #define SSL_OP_NO_TLSv1_3 536870912 + * {@snippet lang = c : * #define SSL_OP_NO_TLSv1_3 536870912 * } */ public static long SSL_OP_NO_TLSv1_3() { return SSL_OP_NO_TLSv1_3; } + private static final long SSL_OP_ALL = 2147485776L; + /** - * {@snippet lang=c : - * #define SSL_OP_ALL 2147485776 + * {@snippet lang = c : * #define SSL_OP_ALL 2147485776 * } */ public static long SSL_OP_ALL() { return SSL_OP_ALL; } - private static final int ENGINE_METHOD_ALL = (int)65535L; - /** - * {@snippet lang=c : - * #define ENGINE_METHOD_ALL 65535 - * } - */ - public static int ENGINE_METHOD_ALL() { - return ENGINE_METHOD_ALL; - } } diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/openssl/openssl_h_Compatibility.java tomcat10-10.1.52/java/org/apache/tomcat/util/openssl/openssl_h_Compatibility.java --- tomcat10-10.1.40/java/org/apache/tomcat/util/openssl/openssl_h_Compatibility.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/openssl/openssl_h_Compatibility.java 2026-01-23 19:33:36.000000000 +0000 @@ -33,16 +33,45 @@ public static final boolean OPENSSL3; public static final boolean BORINGSSL; public static final boolean LIBRESSL; + + public static final int MAJOR; + public static final int MINOR; + static { String versionString = OpenSSL_version(0).getString(0); OPENSSL = versionString.contains("OpenSSL"); OPENSSL3 = OPENSSL && OpenSSL_version_num() >= 0x3000000fL; BORINGSSL = versionString.contains("BoringSSL"); LIBRESSL = versionString.contains("LibreSSL"); + int majorVersion = 0; + int minorVersion = 0; + try { + String[] blocks = versionString.split("\\s"); + if (blocks.length >= 2) { + versionString = blocks[1]; + } + String[] versionNumberStrings = versionString.split("\\."); + if (versionNumberStrings.length >= 2) { + majorVersion = Integer.parseInt(versionNumberStrings[0]); + minorVersion = Integer.parseInt(versionNumberStrings[1]); + } + } catch (Exception e) { + // Ignore, default to 0 + } finally { + MAJOR = majorVersion; + MINOR = minorVersion; + } + } + + public static boolean isLibreSSLPre35() { + return LIBRESSL && ((MAJOR == 3 && MINOR < 5) || MAJOR < 3); } // OpenSSL 1.1 FIPS_mode public static int FIPS_mode() { + if (isLibreSSLPre35()) { + return 0; + } class Holder { static final String NAME = "FIPS_mode"; static final FunctionDescriptor DESC = FunctionDescriptor.of(JAVA_INT); @@ -61,6 +90,9 @@ // OpenSSL 1.1 FIPS_mode_set public static int FIPS_mode_set(int r) { + if (isLibreSSLPre35()) { + return 0; + } class Holder { static final String NAME = "FIPS_mode_set"; static final FunctionDescriptor DESC = FunctionDescriptor.of(JAVA_INT, JAVA_INT); @@ -135,6 +167,58 @@ } } + private static class X509_STORE_CTX_get0_current_issuer { + public static final FunctionDescriptor DESC = FunctionDescriptor.of(openssl_h.C_POINTER, openssl_h.C_POINTER); + + public static final MemorySegment ADDR = openssl_h.findOrThrow("X509_STORE_CTX_get0_current_issuer"); + + public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC); + } + + /** + * OpenSSL 1.1 X509_STORE_CTX_get0_current_issuer + * Function descriptor for: + * {@snippet lang = c : * X509 *X509_STORE_CTX_get0_current_issuer(const X509_STORE_CTX *ctx) + * } + */ + public static FunctionDescriptor X509_STORE_CTX_get0_current_issuer$descriptor() { + return X509_STORE_CTX_get0_current_issuer.DESC; + } + + /** + * Downcall method handle for: + * {@snippet lang = c : * X509 *X509_STORE_CTX_get0_current_issuer(const X509_STORE_CTX *ctx) + * } + */ + public static MethodHandle X509_STORE_CTX_get0_current_issuer$handle() { + return X509_STORE_CTX_get0_current_issuer.HANDLE; + } + + /** + * Address for: + * {@snippet lang = c : * X509 *X509_STORE_CTX_get0_current_issuer(const X509_STORE_CTX *ctx) + * } + */ + public static MemorySegment X509_STORE_CTX_get0_current_issuer$address() { + return X509_STORE_CTX_get0_current_issuer.ADDR; + } + + /** + * {@snippet lang = c : * X509 *X509_STORE_CTX_get0_current_issuer(const X509_STORE_CTX *ctx) + * } + */ + public static MemorySegment X509_STORE_CTX_get0_current_issuer(MemorySegment ctx) { + var mh$ = X509_STORE_CTX_get0_current_issuer.HANDLE; + try { + if (openssl_h.TRACE_DOWNCALLS) { + openssl_h.traceDowncall("X509_STORE_CTX_get0_current_issuer", ctx); + } + return (MemorySegment) mh$.invokeExact(ctx); + } catch (Throwable ex$) { + throw new AssertionError("should not reach here", ex$); + } + } + // LibreSSL SSL_CTRL_OPTIONS public static final int SSL_CTRL_OPTIONS = 32; @@ -159,7 +243,7 @@ // LibreSSL SSL_get_options public static long SSL_get_options(MemorySegment s) { if (LIBRESSL) { - return openssl_h.SSL_ctrl(s, SSL_CTRL_OPTIONS, 0, MemorySegment.NULL); + return SSL_ctrl(s, SSL_CTRL_OPTIONS, 0, MemorySegment.NULL); } else { return openssl_h.SSL_get_options(s); } @@ -168,7 +252,7 @@ // LibreSSL SSL_set_options public static long SSL_set_options(MemorySegment s, long op) { if (LIBRESSL) { - return openssl_h.SSL_ctrl(s, SSL_CTRL_OPTIONS, op, MemorySegment.NULL); + return SSL_ctrl(s, SSL_CTRL_OPTIONS, op, MemorySegment.NULL); } else { return openssl_h.SSL_set_options(s, op); } @@ -213,7 +297,8 @@ if (LIBRESSL) { class Holder { static final String NAME = "sk_value"; - static final FunctionDescriptor DESC = FunctionDescriptor.of(openssl_h.C_POINTER, openssl_h.C_POINTER, openssl_h.C_INT); + static final FunctionDescriptor DESC = + FunctionDescriptor.of(openssl_h.C_POINTER, openssl_h.C_POINTER, openssl_h.C_INT); static final MethodHandle MH = Linker.nativeLinker().downcallHandle(openssl_h.findOrThrow(NAME), DESC); } var mh$ = Holder.MH; @@ -237,4 +322,151 @@ } } + /** + * {@snippet lang = c : * long SSL_ctrl(SSL *ssl, int cmd, long larg, void *parg) + * } + */ + public static long SSL_ctrl(MemorySegment ssl, int cmd, long larg, MemorySegment parg) { + class Holder { + static final FunctionDescriptor DESC = FunctionDescriptor.of(openssl_h.C_LONG, openssl_h.C_POINTER, + openssl_h.C_INT, openssl_h.C_LONG, openssl_h.C_POINTER); + + static final MethodHandle MH = + Linker.nativeLinker().downcallHandle(openssl_h.findOrThrow("SSL_ctrl"), DESC); + } + var mh$ = Holder.MH; + try { + return (long) mh$.invokeExact(ssl, cmd, larg, parg); + } catch (Throwable ex$) { + throw new AssertionError("should not reach here", ex$); + } + } + + // OpenSSL 1.x engine APIs + + /** + * {@snippet lang = c : * ENGINE *ENGINE_by_id(const char *id) + * } + */ + public static MemorySegment ENGINE_by_id(MemorySegment id) { + class Holder { + static final FunctionDescriptor DESC = FunctionDescriptor.of(openssl_h.C_POINTER, openssl_h.C_POINTER); + + static final MethodHandle MH = + Linker.nativeLinker().downcallHandle(openssl_h.findOrThrow("ENGINE_by_id"), DESC); + } + var mh$ = Holder.MH; + try { + return (MemorySegment) mh$.invokeExact(id); + } catch (Throwable ex$) { + throw new AssertionError("should not reach here", ex$); + } + } + + /** + * {@snippet lang = c : * int ENGINE_register_all_complete(void) + * } + */ + public static int ENGINE_register_all_complete() { + try { + return (int) Linker.nativeLinker().downcallHandle(openssl_h.findOrThrow("ENGINE_register_all_complete"), + FunctionDescriptor.of(JAVA_INT)).invokeExact(); + } catch (Throwable ex$) { + throw new AssertionError("should not reach here", ex$); + } + } + + /** + * {@snippet lang = c + * : * int ENGINE_ctrl_cmd_string(ENGINE *e, const char *cmd_name, const char *arg, int cmd_optional) + * } + */ + public static int ENGINE_ctrl_cmd_string(MemorySegment e, MemorySegment cmd_name, MemorySegment arg, + int cmd_optional) { + class Holder { + static final FunctionDescriptor DESC = FunctionDescriptor.of(openssl_h.C_INT, openssl_h.C_POINTER, + openssl_h.C_POINTER, openssl_h.C_POINTER, openssl_h.C_INT); + + static final MethodHandle MH = + Linker.nativeLinker().downcallHandle(openssl_h.findOrThrow("ENGINE_ctrl_cmd_string"), DESC); + } + var mh$ = Holder.MH; + try { + return (int) mh$.invokeExact(e, cmd_name, arg, cmd_optional); + } catch (Throwable ex$) { + throw new AssertionError("should not reach here", ex$); + } + } + + /** + * {@snippet lang = c : * int ENGINE_free(ENGINE *e) + * } + */ + public static int ENGINE_free(MemorySegment e) { + class Holder { + static final FunctionDescriptor DESC = FunctionDescriptor.of(openssl_h.C_INT, openssl_h.C_POINTER); + + static final MethodHandle MH = + Linker.nativeLinker().downcallHandle(openssl_h.findOrThrow("ENGINE_free"), DESC); + } + var mh$ = Holder.MH; + try { + return (int) mh$.invokeExact(e); + } catch (Throwable ex$) { + throw new AssertionError("should not reach here", ex$); + } + } + + /** + * {@snippet lang = c + * : * EVP_PKEY *ENGINE_load_private_key(ENGINE *e, const char *key_id, UI_METHOD *ui_method, void *callback_data) + * } + */ + public static MemorySegment ENGINE_load_private_key(MemorySegment e, MemorySegment key_id, MemorySegment ui_method, + MemorySegment callback_data) { + class Holder { + static final FunctionDescriptor DESC = FunctionDescriptor.of(openssl_h.C_POINTER, openssl_h.C_POINTER, + openssl_h.C_POINTER, openssl_h.C_POINTER, openssl_h.C_POINTER); + + static final MethodHandle MH = + Linker.nativeLinker().downcallHandle(openssl_h.findOrThrow("ENGINE_load_private_key"), DESC); + } + var mh$ = Holder.MH; + try { + return (MemorySegment) mh$.invokeExact(e, key_id, ui_method, callback_data); + } catch (Throwable ex$) { + throw new AssertionError("should not reach here", ex$); + } + } + + /** + * {@snippet lang = c : * int ENGINE_set_default(ENGINE *e, unsigned int flags) + * } + */ + public static int ENGINE_set_default(MemorySegment e, int flags) { + class Holder { + static final FunctionDescriptor DESC = + FunctionDescriptor.of(openssl_h.C_INT, openssl_h.C_POINTER, openssl_h.C_INT); + + static final MethodHandle MH = + Linker.nativeLinker().downcallHandle(openssl_h.findOrThrow("ENGINE_set_default"), DESC); + } + var mh$ = Holder.MH; + try { + return (int) mh$.invokeExact(e, flags); + } catch (Throwable ex$) { + throw new AssertionError("should not reach here", ex$); + } + } + + private static final int ENGINE_METHOD_ALL = (int) 65535L; + + /** + * {@snippet lang = c : * #define ENGINE_METHOD_ALL 65535 + * } + */ + public static int ENGINE_METHOD_ALL() { + return ENGINE_METHOD_ALL; + } + } diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/openssl/openssl_h_Macros.java tomcat10-10.1.52/java/org/apache/tomcat/util/openssl/openssl_h_Macros.java --- tomcat10-10.1.40/java/org/apache/tomcat/util/openssl/openssl_h_Macros.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/openssl/openssl_h_Macros.java 2026-01-23 19:33:36.000000000 +0000 @@ -46,7 +46,8 @@ if (openssl_h_Compatibility.BORINGSSL) { class Holder { static final String NAME = "SSL_CTX_set_max_proto_version"; - static final FunctionDescriptor DESC = FunctionDescriptor.of(openssl_h.C_LONG, openssl_h.C_POINTER, openssl_h.C_LONG); + static final FunctionDescriptor DESC = + FunctionDescriptor.of(openssl_h.C_LONG, openssl_h.C_POINTER, openssl_h.C_LONG); static final MethodHandle MH = Linker.nativeLinker().downcallHandle(openssl_h.findOrThrow(NAME), DESC); } var mh$ = Holder.MH; @@ -79,7 +80,8 @@ if (openssl_h_Compatibility.BORINGSSL) { class Holder { static final String NAME = "SSL_CTX_set_min_proto_version"; - static final FunctionDescriptor DESC = FunctionDescriptor.of(openssl_h.C_LONG, openssl_h.C_POINTER, openssl_h.C_LONG); + static final FunctionDescriptor DESC = + FunctionDescriptor.of(openssl_h.C_LONG, openssl_h.C_POINTER, openssl_h.C_LONG); static final MethodHandle MH = Linker.nativeLinker().downcallHandle(openssl_h.findOrThrow(NAME), DESC); } var mh$ = Holder.MH; @@ -144,7 +146,8 @@ if (openssl_h_Compatibility.BORINGSSL) { class Holder { static final String NAME = "SSL_CTX_sess_set_cache_size"; - static final FunctionDescriptor DESC = FunctionDescriptor.of(openssl_h.C_LONG, openssl_h.C_POINTER, openssl_h.C_LONG); + static final FunctionDescriptor DESC = + FunctionDescriptor.of(openssl_h.C_LONG, openssl_h.C_POINTER, openssl_h.C_LONG); static final MethodHandle MH = Linker.nativeLinker().downcallHandle(openssl_h.findOrThrow(NAME), DESC); } var mh$ = Holder.MH; @@ -209,7 +212,8 @@ if (openssl_h_Compatibility.BORINGSSL) { class Holder { static final String NAME = "SSL_CTX_set_session_cache_mode"; - static final FunctionDescriptor DESC = FunctionDescriptor.of(openssl_h.C_LONG, openssl_h.C_POINTER, openssl_h.C_LONG); + static final FunctionDescriptor DESC = + FunctionDescriptor.of(openssl_h.C_LONG, openssl_h.C_POINTER, openssl_h.C_LONG); static final MethodHandle MH = Linker.nativeLinker().downcallHandle(openssl_h.findOrThrow(NAME), DESC); } var mh$ = Holder.MH; @@ -242,7 +246,8 @@ if (openssl_h_Compatibility.BORINGSSL) { class Holder { static final String NAME = "SSL_CTX_add0_chain_cert"; - static final FunctionDescriptor DESC = FunctionDescriptor.of(openssl_h.C_LONG, openssl_h.C_POINTER, openssl_h.C_POINTER); + static final FunctionDescriptor DESC = + FunctionDescriptor.of(openssl_h.C_LONG, openssl_h.C_POINTER, openssl_h.C_POINTER); static final MethodHandle MH = Linker.nativeLinker().downcallHandle(openssl_h.findOrThrow(NAME), DESC); } var mh$ = Holder.MH; @@ -276,7 +281,8 @@ if (openssl_h_Compatibility.BORINGSSL) { class Holder { static final String NAME = "SSL_CTX_set_tlsext_ticket_keys"; - static final FunctionDescriptor DESC = FunctionDescriptor.of(openssl_h.C_LONG, openssl_h.C_POINTER, openssl_h.C_POINTER, openssl_h.C_LONG); + static final FunctionDescriptor DESC = FunctionDescriptor.of(openssl_h.C_LONG, openssl_h.C_POINTER, + openssl_h.C_POINTER, openssl_h.C_LONG); static final MethodHandle MH = Linker.nativeLinker().downcallHandle(openssl_h.findOrThrow(NAME), DESC); } var mh$ = Holder.MH; @@ -345,7 +351,8 @@ if (openssl_h_Compatibility.BORINGSSL) { class Holder { static final String NAME = "SSL_CTX_set_tmp_ecdh"; - static final FunctionDescriptor DESC = FunctionDescriptor.of(openssl_h.C_LONG, openssl_h.C_POINTER, openssl_h.C_POINTER); + static final FunctionDescriptor DESC = + FunctionDescriptor.of(openssl_h.C_LONG, openssl_h.C_POINTER, openssl_h.C_POINTER); static final MethodHandle MH = Linker.nativeLinker().downcallHandle(openssl_h.findOrThrow(NAME), DESC); } var mh$ = Holder.MH; @@ -364,6 +371,24 @@ /** + * Set automatic dh. + * {@snippet lang = c : # define SSL_CTX_set_dh_auto(ctx, onoff) \ + * SSL_CTX_ctrl(ctx,SSL_CTRL_SET_DH_AUTO,onoff,NULL) + * } + * @param sslCtx the SSL context + * @param onoff 1 to enable + * @return > 0 if successful + */ + public static long SSL_CTX_set_dh_auto(MemorySegment sslCtx, int onoff) { + if (openssl_h_Compatibility.BORINGSSL) { + return 1; + } else { + return SSL_CTX_ctrl(sslCtx, SSL_CTRL_SET_DH_AUTO(), 1, MemorySegment.NULL); + } + } + + + /** * Free memory. * {@snippet lang = c : # define OPENSSL_free(addr) CRYPTO_free(addr, OPENSSL_FILE, OPENSSL_LINE) * } @@ -406,7 +431,8 @@ if (openssl_h_Compatibility.BORINGSSL) { class Holder { static final String NAME = "SSL_CTX_set1_groups"; - static final FunctionDescriptor DESC = FunctionDescriptor.of(openssl_h.C_LONG, openssl_h.C_POINTER, openssl_h.C_POINTER, openssl_h.C_INT); + static final FunctionDescriptor DESC = FunctionDescriptor.of(openssl_h.C_LONG, openssl_h.C_POINTER, + openssl_h.C_POINTER, openssl_h.C_INT); static final MethodHandle MH = Linker.nativeLinker().downcallHandle(openssl_h.findOrThrow(NAME), DESC); } var mh$ = Holder.MH; @@ -425,6 +451,41 @@ /** + * Set list of groups in preference order. + * {@snippet lang = c : + * # define SSL_set1_groups_list(s, str) \ + * SSL_ctrl(s,SSL_CTRL_SET_GROUPS_LIST,0,(char *)(str)) + * } + * + * @param sslCtx the SSL context + * @param groupsList the groups list as a String + * + * @return > 0 if successful + */ + public static long SSL_CTX_set1_groups_list(MemorySegment sslCtx, MemorySegment groupsList) { + if (openssl_h_Compatibility.BORINGSSL) { + class Holder { + static final String NAME = "SSL_CTX_set1_groups_list"; + static final FunctionDescriptor DESC = FunctionDescriptor.of(openssl_h.C_LONG, openssl_h.C_POINTER, + openssl_h.C_POINTER); + static final MethodHandle MH = Linker.nativeLinker().downcallHandle(openssl_h.findOrThrow(NAME), DESC); + } + var mh$ = Holder.MH; + try { + if (openssl_h.TRACE_DOWNCALLS) { + openssl_h.traceDowncall(Holder.NAME, sslCtx, groupsList); + } + return (long) mh$.invokeExact(sslCtx, groupsList); + } catch (Throwable ex$) { + throw new AssertionError("should not reach here", ex$); + } + } else { + return SSL_CTX_ctrl(sslCtx, SSL_CTRL_SET_GROUPS_LIST(), 0, groupsList); + } + } + + + /** * Pass a path from which certificates are loaded into the store. * {@snippet lang = c : # define X509_LOOKUP_add_dir(x,name,type) \ * X509_LOOKUP_ctrl((x),X509_L_ADD_DIR,(name),(long)(type),NULL) @@ -460,6 +521,7 @@ /** * Return the d2i_ECPKParameters symbol. + * * @return the symbol */ public static MemorySegment d2i_ECPKParameters$SYMBOL() { diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/openssl/pem_password_cb.java tomcat10-10.1.52/java/org/apache/tomcat/util/openssl/pem_password_cb.java --- tomcat10-10.1.40/java/org/apache/tomcat/util/openssl/pem_password_cb.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/openssl/pem_password_cb.java 2026-01-23 19:33:36.000000000 +0000 @@ -26,8 +26,7 @@ import java.lang.invoke.MethodHandle; /** - * {@snippet lang=c : - * typedef int (pem_password_cb)(char *, int, int, void *) + * {@snippet lang = c : * typedef int (pem_password_cb)(char *, int, int, void *) * } */ @SuppressWarnings("javadoc") @@ -40,13 +39,8 @@ int apply(MemorySegment buf, int size, int rwflag, MemorySegment userdata); } - private static final FunctionDescriptor $DESC = FunctionDescriptor.of( - openssl_h.C_INT, - openssl_h.C_POINTER, - openssl_h.C_INT, - openssl_h.C_INT, - openssl_h.C_POINTER - ); + private static final FunctionDescriptor $DESC = FunctionDescriptor.of(openssl_h.C_INT, openssl_h.C_POINTER, + openssl_h.C_INT, openssl_h.C_INT, openssl_h.C_POINTER); /** * The descriptor of this function pointer @@ -58,8 +52,8 @@ private static final MethodHandle UP$MH = openssl_h.upcallHandle(pem_password_cb.Function.class, "apply", $DESC); /** - * Allocates a new upcall stub, whose implementation is defined by {@code fi}. - * The lifetime of the returned segment is managed by {@code arena} + * Allocates a new upcall stub, whose implementation is defined by {@code fi}. The lifetime of the returned segment + * is managed by {@code arena} */ public static MemorySegment allocate(pem_password_cb.Function fi, Arena arena) { return Linker.nativeLinker().upcallStub(UP$MH.bindTo(fi), $DESC, arena); @@ -70,7 +64,7 @@ /** * Invoke the upcall stub {@code funcPtr}, with given parameters */ - public static int invoke(MemorySegment funcPtr,MemorySegment buf, int size, int rwflag, MemorySegment userdata) { + public static int invoke(MemorySegment funcPtr, MemorySegment buf, int size, int rwflag, MemorySegment userdata) { try { return (int) DOWN$MH.invokeExact(funcPtr, buf, size, rwflag, userdata); } catch (Throwable ex$) { diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/res/StringManager.java tomcat10-10.1.52/java/org/apache/tomcat/util/res/StringManager.java --- tomcat10-10.1.40/java/org/apache/tomcat/util/res/StringManager.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/res/StringManager.java 2026-01-23 19:33:36.000000000 +0000 @@ -38,10 +38,6 @@ *

      * Please see the documentation for java.util.ResourceBundle for more information. * - * @author James Duncan Davidson [duncan@eng.sun.com] - * @author James Todd [gonzo@eng.sun.com] - * @author Mel Martinez [mmartinez@g1440.com] - * * @see java.util.ResourceBundle */ public class StringManager { @@ -81,7 +77,7 @@ if (cl != null) { try { bnd = ResourceBundle.getBundle(bundleName, locale, cl); - } catch (MissingResourceException ex2) { + } catch (MissingResourceException ignore) { // Ignore } } @@ -112,8 +108,7 @@ */ public String getString(String key) { if (key == null) { - String msg = "key may not have a null value"; - throw new IllegalArgumentException(msg); + throw new IllegalArgumentException("key may not have a null value"); } String str = null; @@ -123,7 +118,7 @@ if (bundle != null) { str = bundle.getString(key); } - } catch (MissingResourceException mre) { + } catch (MissingResourceException ignore) { // bad: shouldn't mask an exception the following way: // str = "[cannot find message associated with key '" + key + // "' due to " + mre + "]"; @@ -175,7 +170,7 @@ // STATIC SUPPORT METHODS // -------------------------------------------------------------- - private static final Map> managers = new HashMap<>(); + private static final Map> managers = new HashMap<>(); /** @@ -216,18 +211,18 @@ */ public static synchronized StringManager getManager(String packageName, Locale locale) { - Map map = managers.get(packageName); + Map map = managers.get(packageName); if (map == null) { /* * Don't want the HashMap size to exceed LOCALE_CACHE_SIZE. Expansion occurs when size() exceeds capacity. - * Therefore, keep size at or below capacity. removeEldestEntry() executes after insertion therefore the test - * for removal needs to use one less than the maximum desired size. Note this is an LRU cache. + * Therefore, keep size at or below capacity. removeEldestEntry() executes after insertion therefore the + * test for removal needs to use one less than the maximum desired size. Note this is an LRU cache. */ map = new LinkedHashMap<>(LOCALE_CACHE_SIZE, 0.75f, true) { private static final long serialVersionUID = 1L; @Override - protected boolean removeEldestEntry(Map.Entry eldest) { + protected boolean removeEldestEntry(Map.Entry eldest) { return size() > (LOCALE_CACHE_SIZE - 1); } }; diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/scan/AbstractInputStreamJar.java tomcat10-10.1.52/java/org/apache/tomcat/util/scan/AbstractInputStreamJar.java --- tomcat10-10.1.40/java/org/apache/tomcat/util/scan/AbstractInputStreamJar.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/scan/AbstractInputStreamJar.java 2026-01-23 19:33:36.000000000 +0000 @@ -28,8 +28,7 @@ import org.apache.tomcat.Jar; /** - * Base implementation of Jar for implementations that use a JarInputStream to - * access the JAR file. + * Base implementation of Jar for implementations that use a JarInputStream to access the JAR file. */ public abstract class AbstractInputStreamJar implements Jar { @@ -56,7 +55,7 @@ if (jarInputStream == null) { try { reset(); - } catch (IOException e) { + } catch (IOException ioe) { entry = null; return; } @@ -66,10 +65,8 @@ if (multiRelease.booleanValue()) { // Skip base entries where there is a multi-release entry // Skip multi-release entries that are not being used - while (entry != null && - (mrMap.containsKey(entry.getName()) || - entry.getName().startsWith("META-INF/versions/") && - !mrMap.containsValue(entry.getName()))) { + while (entry != null && (mrMap.containsKey(entry.getName()) || + entry.getName().startsWith("META-INF/versions/") && !mrMap.containsValue(entry.getName()))) { entry = jarInputStream.getNextJarEntry(); } } else { @@ -268,8 +265,8 @@ mrMap = new HashMap<>(); for (Entry mrVersion : mrVersions.entrySet()) { - mrMap.put(mrVersion.getKey() , "META-INF/versions/" + mrVersion.getValue().toString() + - "/" + mrVersion.getKey()); + mrMap.put(mrVersion.getKey(), + "META-INF/versions/" + mrVersion.getValue().toString() + "/" + mrVersion.getKey()); } // Reset stream back to the beginning of the JAR diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/scan/Constants.java tomcat10-10.1.52/java/org/apache/tomcat/util/scan/Constants.java --- tomcat10-10.1.40/java/org/apache/tomcat/util/scan/Constants.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/scan/Constants.java 2026-01-23 19:33:36.000000000 +0000 @@ -24,10 +24,8 @@ public static final String Package = "org.apache.tomcat.util.scan"; /* System properties */ - public static final String SKIP_JARS_PROPERTY = - "tomcat.util.scan.StandardJarScanFilter.jarsToSkip"; - public static final String SCAN_JARS_PROPERTY = - "tomcat.util.scan.StandardJarScanFilter.jarsToScan"; + public static final String SKIP_JARS_PROPERTY = "tomcat.util.scan.StandardJarScanFilter.jarsToSkip"; + public static final String SCAN_JARS_PROPERTY = "tomcat.util.scan.StandardJarScanFilter.jarsToScan"; /* Commons strings */ public static final String JAR_EXT = ".jar"; diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/scan/JarFactory.java tomcat10-10.1.52/java/org/apache/tomcat/util/scan/JarFactory.java --- tomcat10-10.1.40/java/org/apache/tomcat/util/scan/JarFactory.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/scan/JarFactory.java 2026-01-23 19:33:36.000000000 +0000 @@ -53,8 +53,7 @@ } - public static URL getJarEntryURL(URL baseUrl, String entryName) - throws MalformedURLException { + public static URL getJarEntryURL(URL baseUrl, String entryName) throws MalformedURLException { String baseExternal = baseUrl.toExternalForm(); @@ -62,8 +61,7 @@ // Assume this is pointing to a JAR file within a WAR. Java doesn't // support jar:jar:file:... so switch to Tomcat's war:file:... baseExternal = baseExternal.replaceFirst("^jar:", "war:"); - baseExternal = baseExternal.replaceFirst("!/", - Matcher.quoteReplacement(UriUtil.getWarSeparator())); + baseExternal = baseExternal.replaceFirst("!/", Matcher.quoteReplacement(UriUtil.getWarSeparator())); } return new URL("jar:" + baseExternal + "!/" + entryName); diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/scan/JarFileUrlJar.java tomcat10-10.1.52/java/org/apache/tomcat/util/scan/JarFileUrlJar.java --- tomcat10-10.1.40/java/org/apache/tomcat/util/scan/JarFileUrlJar.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/scan/JarFileUrlJar.java 2026-01-23 19:33:36.000000000 +0000 @@ -34,9 +34,8 @@ import org.apache.tomcat.Jar; /** - * Implementation of {@link Jar} that is optimised for file based JAR URLs that - * refer directly to a JAR file (e.g. URLs of the form jar:file: ... .jar!/ or - * file:... .jar). + * Implementation of {@link Jar} that is optimised for file based JAR URLs that refer directly to a JAR file (e.g. URLs + * of the form jar:file: ... .jar!/ or file:... .jar). */ public class JarFileUrlJar implements Jar { @@ -68,11 +67,14 @@ boolean multiReleaseValue = false; try { multiReleaseValue = jarFile.isMultiRelease(); - } catch (IllegalStateException e) { - // ISE can be thrown if the JAR URL is bad, for example: - // https://github.com/spring-projects/spring-boot/issues/33633 - // The Javadoc does not document that ISE and given what it does for a vanilla IOE, - // this looks like a Java bug, it should return false instead. + } catch (IllegalStateException ignore) { + /* + * ISE can be thrown if the JAR URL is bad, for example: + * https://github.com/spring-projects/spring-boot/issues/33633 + * + * The Javadoc does not document that ISE and given what it does for a vanilla IOE, this looks like a Java + * bug, it should return false instead. + */ } multiRelease = multiReleaseValue; } @@ -115,7 +117,7 @@ @Override public String getURL(String entry) { - return "jar:" + getJarFileURL().toExternalForm() + "!/" + entry; + return "jar:" + getJarFileURL().toExternalForm() + "!/" + entry; } @Override @@ -123,7 +125,7 @@ if (jarFile != null) { try { jarFile.close(); - } catch (IOException e) { + } catch (IOException ignore) { // Ignore } } @@ -142,11 +144,11 @@ if (multiRelease) { // Need to ensure that: // - the one, correct entry is returned where multiple versions - // are available + // are available // - that the order of entries in the JAR doesn't prevent the - // correct entries being returned + // correct entries being returned // - the case where an entry appears in the versions location - // but not in the base location is handled correctly + // but not in the base location is handled correctly // Enumerate the entries until one is reached that represents an // entry that has not been seen before. diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/scan/JarFileUrlNestedJar.java tomcat10-10.1.52/java/org/apache/tomcat/util/scan/JarFileUrlNestedJar.java --- tomcat10-10.1.40/java/org/apache/tomcat/util/scan/JarFileUrlNestedJar.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/scan/JarFileUrlNestedJar.java 2026-01-23 19:33:36.000000000 +0000 @@ -23,9 +23,8 @@ import java.util.jar.JarFile; /** - * Implementation of {@link org.apache.tomcat.Jar} that is optimised for file - * based JAR URLs that refer to a JAR file nested inside a WAR - * (e.g. URLs of the form jar:file: ... .war!/ ... .jar). + * Implementation of {@link org.apache.tomcat.Jar} that is optimised for file based JAR URLs that refer to a JAR file + * nested inside a WAR (e.g. URLs of the form jar:file: ... .war!/ ... .jar). */ public class JarFileUrlNestedJar extends AbstractInputStreamJar { @@ -51,7 +50,7 @@ if (warFile != null) { try { warFile.close(); - } catch (IOException e) { + } catch (IOException ignore) { // Ignore } } diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/scan/NonClosingJarInputStream.java tomcat10-10.1.52/java/org/apache/tomcat/util/scan/NonClosingJarInputStream.java --- tomcat10-10.1.40/java/org/apache/tomcat/util/scan/NonClosingJarInputStream.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/scan/NonClosingJarInputStream.java 2026-01-23 19:33:36.000000000 +0000 @@ -21,15 +21,13 @@ import java.util.jar.JarInputStream; /** - * When using a {@link JarInputStream} with an XML parser, the stream will be - * closed by the parser. This causes problems if multiple entries from the JAR - * need to be parsed. This implementation makes {{@link #close()} a NO-OP and - * adds {@link #reallyClose()} that will close the stream. + * When using a {@link JarInputStream} with an XML parser, the stream will be closed by the parser. This causes problems + * if multiple entries from the JAR need to be parsed. This implementation makes {{@link #close()} a NO-OP and adds + * {@link #reallyClose()} that will close the stream. */ public class NonClosingJarInputStream extends JarInputStream { - public NonClosingJarInputStream(InputStream in, boolean verify) - throws IOException { + public NonClosingJarInputStream(InputStream in, boolean verify) throws IOException { super(in, verify); } diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/scan/ReferenceCountedJar.java tomcat10-10.1.52/java/org/apache/tomcat/util/scan/ReferenceCountedJar.java --- tomcat10-10.1.40/java/org/apache/tomcat/util/scan/ReferenceCountedJar.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/scan/ReferenceCountedJar.java 2026-01-23 19:33:36.000000000 +0000 @@ -24,8 +24,8 @@ import org.apache.tomcat.Jar; /** - * This class provides a wrapper around {@link Jar} that uses reference counting - * to close and re-create the wrapped {@link Jar} instance as required. + * This class provides a wrapper around {@link Jar} that uses reference counting to close and re-create the wrapped + * {@link Jar} instance as required. */ public class ReferenceCountedJar implements Jar { diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/scan/StandardJarScanFilter.java tomcat10-10.1.52/java/org/apache/tomcat/util/scan/StandardJarScanFilter.java --- tomcat10-10.1.40/java/org/apache/tomcat/util/scan/StandardJarScanFilter.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/scan/StandardJarScanFilter.java 2026-01-23 19:33:36.000000000 +0000 @@ -29,8 +29,7 @@ public class StandardJarScanFilter implements JarScanFilter { - private final ReadWriteLock configurationLock = - new ReentrantReadWriteLock(); + private final ReadWriteLock configurationLock = new ReentrantReadWriteLock(); private static final String defaultSkip; private static final String defaultScan; @@ -60,32 +59,22 @@ private boolean defaultPluggabilityScan = true; /** - * This is the standard implementation of {@link JarScanFilter}. By default, - * the following filtering rules are used: + * This is the standard implementation of {@link JarScanFilter}. By default, the following filtering rules are used: *

        - *
      • JARs that match neither the skip nor the scan list will be included - * in scan results.
      • - *
      • JARs that match the skip list but not the scan list will be excluded - * from scan results.
      • - *
      • JARs that match the scan list will be included from scan results. - *
      • + *
      • JARs that match neither the skip nor the scan list will be included in scan results.
      • + *
      • JARs that match the skip list but not the scan list will be excluded from scan results.
      • + *
      • JARs that match the scan list will be included from scan results.
      • *
      - * The default skip list and default scan list are obtained from the system - * properties {@link Constants#SKIP_JARS_PROPERTY} and - * {@link Constants#SCAN_JARS_PROPERTY} respectively. These default values - * may be over-ridden for the {@link JarScanType#TLD} and - * {@link JarScanType#PLUGGABILITY} scans. The filtering rules may also be - * modified for these scan types using {@link #setDefaultTldScan(boolean)} - * and {@link #setDefaultPluggabilityScan(boolean)}. If set to - * false, the following filtering rules are used for associated - * type: + * The default skip list and default scan list are obtained from the system properties + * {@link Constants#SKIP_JARS_PROPERTY} and {@link Constants#SCAN_JARS_PROPERTY} respectively. These default values + * may be over-ridden for the {@link JarScanType#TLD} and {@link JarScanType#PLUGGABILITY} scans. The filtering + * rules may also be modified for these scan types using {@link #setDefaultTldScan(boolean)} and + * {@link #setDefaultPluggabilityScan(boolean)}. If set to false, the following filtering rules are + * used for associated type: *
        - *
      • JARs that match neither the skip nor the scan list will be excluded - * from scan results.
      • - *
      • JARs that match the scan list but not the skip list will be included - * in scan results.
      • - *
      • JARs that match the skip list will be excluded from scan results. - *
      • + *
      • JARs that match neither the skip nor the scan list will be excluded from scan results.
      • + *
      • JARs that match the scan list but not the skip list will be included in scan results.
      • + *
      • JARs that match the skip list will be excluded from scan results.
      • *
      */ public StandardJarScanFilter() { diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/scan/StandardJarScanner.java tomcat10-10.1.52/java/org/apache/tomcat/util/scan/StandardJarScanner.java --- tomcat10-10.1.40/java/org/apache/tomcat/util/scan/StandardJarScanner.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/scan/StandardJarScanner.java 2026-01-23 19:33:36.000000000 +0000 @@ -47,16 +47,13 @@ import org.apache.tomcat.util.res.StringManager; /** - * The default {@link JarScanner} implementation scans the WEB-INF/lib directory - * followed by the provided classloader and then works up the classloader - * hierarchy. This implementation is sufficient to meet the requirements of the - * Servlet 3.0 specification as well as to provide a number of Tomcat specific - * extensions. The extensions are: + * The default {@link JarScanner} implementation scans the WEB-INF/lib directory followed by the provided classloader + * and then works up the classloader hierarchy. This implementation is sufficient to meet the requirements of the + * Servlet 3.0 specification as well as to provide a number of Tomcat specific extensions. The extensions are: *
        - *
      • Scanning the classloader hierarchy (enabled by default)
      • - *
      • Testing all files to see if they are JARs (disabled by default)
      • - *
      • Testing all directories to see if they are exploded JARs - * (disabled by default)
      • + *
      • Scanning the classloader hierarchy (enabled by default)
      • + *
      • Testing all files to see if they are JARs (disabled by default)
      • + *
      • Testing all directories to see if they are exploded JARs (disabled by default)
      • *
      * All of the extensions may be controlled via configuration. */ @@ -87,9 +84,11 @@ * Controls the classpath scanning extension. */ private boolean scanClassPath = true; + public boolean isScanClassPath() { return scanClassPath; } + public void setScanClassPath(boolean scanClassPath) { this.scanClassPath = scanClassPath; } @@ -98,9 +97,11 @@ * Controls the JAR file Manifest scanning extension. */ private boolean scanManifest = true; + public boolean isScanManifest() { return scanManifest; } + public void setScanManifest(boolean scanManifest) { this.scanManifest = scanManifest; } @@ -109,33 +110,38 @@ * Controls the testing all files to see of they are JAR files extension. */ private boolean scanAllFiles = false; + public boolean isScanAllFiles() { return scanAllFiles; } + public void setScanAllFiles(boolean scanAllFiles) { this.scanAllFiles = scanAllFiles; } /** - * Controls the testing all directories to see of they are exploded JAR - * files extension. + * Controls the testing all directories to see of they are exploded JAR files extension. */ private boolean scanAllDirectories = true; + public boolean isScanAllDirectories() { return scanAllDirectories; } + public void setScanAllDirectories(boolean scanAllDirectories) { this.scanAllDirectories = scanAllDirectories; } /** - * Controls the testing of the bootstrap classpath which consists of the - * runtime classes provided by the JVM and any installed system extensions. + * Controls the testing of the bootstrap classpath which consists of the runtime classes provided by the JVM and any + * installed system extensions. */ private boolean scanBootstrapClassPath = false; + public boolean isScanBootstrapClassPath() { return scanBootstrapClassPath; } + public void setScanBootstrapClassPath(boolean scanBootstrapClassPath) { this.scanBootstrapClassPath = scanBootstrapClassPath; } @@ -144,29 +150,28 @@ * Controls the filtering of the results from the scan for JARs */ private JarScanFilter jarScanFilter = new StandardJarScanFilter(); + @Override public JarScanFilter getJarScanFilter() { return jarScanFilter; } + @Override public void setJarScanFilter(JarScanFilter jarScanFilter) { this.jarScanFilter = jarScanFilter; } /** - * Scan the provided ServletContext and class loader for JAR files. Each JAR - * file found will be passed to the callback handler to be processed. + * Scan the provided ServletContext and class loader for JAR files. Each JAR file found will be passed to the + * callback handler to be processed. * - * @param scanType The type of JAR scan to perform. This is passed to - * the filter which uses it to determine how to - * filter the results - * @param context The ServletContext - used to locate and access - * WEB-INF/lib - * @param callback The handler to process any JARs found + * @param scanType The type of JAR scan to perform. This is passed to the filter which uses it to determine how to + * filter the results + * @param context The ServletContext - used to locate and access WEB-INF/lib + * @param callback The handler to process any JARs found */ @Override - public void scan(JarScanType scanType, ServletContext context, - JarScannerCallback callback) { + public void scan(JarScanType scanType, ServletContext context, JarScannerCallback callback) { if (log.isTraceEnabled()) { log.trace(sm.getString("jarScan.webinflibStart")); @@ -183,8 +188,7 @@ if (dirList != null) { for (String path : dirList) { if (path.endsWith(Constants.JAR_EXT) && - getJarScanFilter().check(scanType, - path.substring(path.lastIndexOf('/')+1))) { + getJarScanFilter().check(scanType, path.substring(path.lastIndexOf('/') + 1))) { // Need to scan this JAR if (log.isDebugEnabled()) { log.debug(sm.getString("jarScan.webinflibJarScan", path)); @@ -198,8 +202,8 @@ } else { log.warn(sm.getString("jarScan.webinflibFail", path)); } - } catch (IOException e) { - log.warn(sm.getString("jarScan.webinflibFail", url), e); + } catch (IOException ioe) { + log.warn(sm.getString("jarScan.webinflibFail", url), ioe); } } else { if (log.isTraceEnabled()) { @@ -223,8 +227,8 @@ if (url != null) { try { callback.scanWebInfClasses(); - } catch (IOException e) { - log.warn(sm.getString("jarScan.webinfclassesFail"), e); + } catch (IOException ioe) { + log.warn(sm.getString("jarScan.webinfclassesFail"), ioe); } } } @@ -240,8 +244,8 @@ } - protected void doScanClassPath(JarScanType scanType, ServletContext context, - JarScannerCallback callback, Set processedURLs) { + protected void doScanClassPath(JarScanType scanType, ServletContext context, JarScannerCallback callback, + Set processedURLs) { if (log.isTraceEnabled()) { log.trace(sm.getString("jarScan.classloaderStart")); } @@ -269,8 +273,7 @@ isWebapp = isWebappClassLoader(classLoader); } - classPathUrlsToProcess.addAll( - Arrays.asList(((URLClassLoader) classLoader).getURLs())); + classPathUrlsToProcess.addAll(Arrays.asList(((URLClassLoader) classLoader).getURLs())); processURLs(scanType, callback, processedURLs, isWebapp, classPathUrlsToProcess); } @@ -298,8 +301,8 @@ } - protected void processURLs(JarScanType scanType, JarScannerCallback callback, - Set processedURLs, boolean isWebapp, Deque classPathUrlsToProcess) { + protected void processURLs(JarScanType scanType, JarScannerCallback callback, Set processedURLs, + boolean isWebapp, Deque classPathUrlsToProcess) { if (jarScanFilter.isSkipAll()) { return; @@ -319,11 +322,8 @@ // Directories are scanned for pluggability scans or // if scanAllDirectories is enabled unless the // filter says not to. - if ((cpe.isJar() || - scanType == JarScanType.PLUGGABILITY || - isScanAllDirectories()) && - getJarScanFilter().check(scanType, - cpe.getName())) { + if ((cpe.isJar() || scanType == JarScanType.PLUGGABILITY || isScanAllDirectories()) && + getJarScanFilter().check(scanType, cpe.getName())) { if (log.isDebugEnabled()) { log.debug(sm.getString("jarScan.classloaderJarScan", url)); } @@ -363,18 +363,14 @@ /* - * Since class loader hierarchies can get complicated, this method attempts - * to apply the following rule: A class loader is a web application class - * loader unless it loaded this class (StandardJarScanner) or is a parent - * of the class loader that loaded this class. + * Since class loader hierarchies can get complicated, this method attempts to apply the following rule: A class + * loader is a web application class loader unless it loaded this class (StandardJarScanner) or is a parent of the + * class loader that loaded this class. * - * This should mean: - * the webapp class loader is an application class loader - * the shared class loader is an application class loader - * the server class loader is not an application class loader - * the common class loader is not an application class loader - * the system class loader is not an application class loader - * the bootstrap class loader is not an application class loader + * This should mean: the webapp class loader is an application class loader the shared class loader is an + * application class loader the server class loader is not an application class loader the common class loader is + * not an application class loader the system class loader is not an application class loader the bootstrap class + * loader is not an application class loader */ private static boolean isWebappClassLoader(ClassLoader classLoader) { return !CLASSLOADER_HIERARCHY.contains(classLoader); @@ -382,12 +378,10 @@ /* - * Scan a URL for JARs with the optional extensions to look at all files - * and all directories. + * Scan a URL for JARs with the optional extensions to look at all files and all directories. */ - protected void process(JarScanType scanType, JarScannerCallback callback, - URL url, String webappPath, boolean isWebapp, Deque classPathUrlsToProcess) - throws IOException { + protected void process(JarScanType scanType, JarScannerCallback callback, URL url, String webappPath, + boolean isWebapp, Deque classPathUrlsToProcess) throws IOException { if (log.isTraceEnabled()) { log.trace(sm.getString("jarScan.jarUrlStart", url)); @@ -432,8 +426,7 @@ } - private void processManifest(Jar jar, boolean isWebapp, - Deque classPathUrlsToProcess) throws IOException { + private void processManifest(Jar jar, boolean isWebapp, Deque classPathUrlsToProcess) throws IOException { // Not processed for web application JARs nor if the caller did not // provide a Deque of URLs to append to. @@ -459,14 +452,11 @@ try { URI jarURI = jarURL.toURI(); /* - * Note: Resolving the relative URLs from the manifest has the - * potential to introduce security concerns. However, since - * only JARs provided by the container and NOT those provided - * by web applications are processed, there should be no - * issues. - * If this feature is ever extended to include JARs provided - * by web applications, checks should be added to ensure that - * any relative URL does not step outside the web application. + * Note: Resolving the relative URLs from the manifest has the potential to introduce security + * concerns. However, since only JARs provided by the container and NOT those provided by web + * applications are processed, there should be no issues. If this feature is ever extended to + * include JARs provided by web applications, checks should be added to ensure that any relative URL + * does not step outside the web application. */ URI classPathEntryURI = jarURI.resolve(classPathEntry); classPathEntryURL = classPathEntryURI.toURL(); diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/scan/UrlJar.java tomcat10-10.1.52/java/org/apache/tomcat/util/scan/UrlJar.java --- tomcat10-10.1.40/java/org/apache/tomcat/util/scan/UrlJar.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/scan/UrlJar.java 2026-01-23 19:33:36.000000000 +0000 @@ -22,8 +22,7 @@ import java.net.URLConnection; /** - * Implementation of {@link org.apache.tomcat.Jar} that is optimised for - * non-file based JAR URLs. + * Implementation of {@link org.apache.tomcat.Jar} that is optimised for non-file based JAR URLs. */ public class UrlJar extends AbstractInputStreamJar { diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/security/ConcurrentMessageDigest.java tomcat10-10.1.52/java/org/apache/tomcat/util/security/ConcurrentMessageDigest.java --- tomcat10-10.1.40/java/org/apache/tomcat/util/security/ConcurrentMessageDigest.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/security/ConcurrentMessageDigest.java 2026-01-23 19:33:36.000000000 +0000 @@ -28,9 +28,8 @@ import org.apache.tomcat.util.res.StringManager; /** - * A thread safe wrapper around {@link MessageDigest} that does not make use - * of ThreadLocal and - broadly - only creates enough MessageDigest objects - * to satisfy the concurrency requirements. + * A thread safe wrapper around {@link MessageDigest} that does not make use of ThreadLocal and - broadly - only creates + * enough MessageDigest objects to satisfy the concurrency requirements. */ public class ConcurrentMessageDigest { @@ -39,9 +38,9 @@ private static final String MD5 = "MD5"; private static final String SHA1 = "SHA-1"; + private static final String SHA256 = "SHA-256"; - private static final Map> queues = - new ConcurrentHashMap<>(); + private static final Map> queues = new ConcurrentHashMap<>(); private ConcurrentMessageDigest() { @@ -56,7 +55,12 @@ log.warn(sm.getString("concurrentMessageDigest.noDigest"), e); } try { - init(SHA1); + init(SHA1); + } catch (NoSuchAlgorithmException e) { + throw new IllegalArgumentException(sm.getString("concurrentMessageDigest.noDigest"), e); + } + try { + init(SHA256); } catch (NoSuchAlgorithmException e) { throw new IllegalArgumentException(sm.getString("concurrentMessageDigest.noDigest"), e); } @@ -70,6 +74,10 @@ return digest(SHA1, input); } + public static byte[] digestSHA256(byte[]... input) { + return digest(SHA256, input); + } + public static byte[] digest(String algorithm, byte[]... input) { return digest(algorithm, 1, input); } @@ -114,14 +122,12 @@ /** - * Ensures that {@link #digest(String, byte[][])} will support the specified - * algorithm. This method must be called and return successfully - * before using {@link #digest(String, byte[][])}. + * Ensures that {@link #digest(String, byte[][])} will support the specified algorithm. This method must be + * called and return successfully before using {@link #digest(String, byte[][])}. * * @param algorithm The message digest algorithm to be supported * - * @throws NoSuchAlgorithmException If the algorithm is not supported by the - * JVM + * @throws NoSuchAlgorithmException If the algorithm is not supported by the JVM */ public static void init(String algorithm) throws NoSuchAlgorithmException { if (!queues.containsKey(algorithm)) { diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/security/Escape.java tomcat10-10.1.52/java/org/apache/tomcat/util/security/Escape.java --- tomcat10-10.1.40/java/org/apache/tomcat/util/security/Escape.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/security/Escape.java 2026-01-23 19:33:36.000000000 +0000 @@ -17,9 +17,8 @@ package org.apache.tomcat.util.security; /** - * Provides utility methods to escape content for different contexts. It is - * critical that the escaping used is correct for the context in which the data - * is to be used. + * Provides utility methods to escape content for different contexts. It is critical that the escaping used is correct + * for the context in which the data is to be used. */ public class Escape { @@ -29,19 +28,16 @@ /** - * Escape content for use in HTML. This escaping is suitable for the - * following uses: + * Escape content for use in HTML. This escaping is suitable for the following uses: *
        - *
      • Element content when the escaped data will be placed directly inside - * tags such as <p>, <td> etc.
      • - *
      • Attribute values when the attribute value is quoted with " or - * '.
      • + *
      • Element content when the escaped data will be placed directly inside tags such as <p>, <td> + * etc.
      • + *
      • Attribute values when the attribute value is quoted with " or '.
      • *
      * - * @param content The content to escape + * @param content The content to escape * - * @return The escaped content or {@code null} if the content was - * {@code null} + * @return The escaped content or {@code null} if the content was {@code null} */ public static String htmlElementContent(String content) { if (content == null) { @@ -74,13 +70,12 @@ /** - * Convert the object to a string via {@link Object#toString()} and HTML - * escape the resulting string for use in HTML content. + * Convert the object to a string via {@link Object#toString()} and HTML escape the resulting string for use in HTML + * content. * - * @param obj The object to convert to String and then escape + * @param obj The object to convert to String and then escape * - * @return The escaped content or "?" if obj is - * {@code null} + * @return The escaped content or "?" if obj is {@code null} */ public static String htmlElementContent(Object obj) { if (obj == null) { @@ -93,10 +88,9 @@ /** * Escape content for use in XML. * - * @param content The content to escape + * @param content The content to escape * - * @return The escaped content or {@code null} if the content was - * {@code null} + * @return The escaped content or {@code null} if the content was {@code null} */ public static String xml(String content) { return xml(null, content); @@ -106,11 +100,10 @@ /** * Escape content for use in XML. * - * @param ifNull The value to return if content is {@code null} - * @param content The content to escape + * @param ifNull The value to return if content is {@code null} + * @param content The content to escape * - * @return The escaped content or the value of {@code ifNull} if the - * content was {@code null} + * @return The escaped content or the value of {@code ifNull} if the content was {@code null} */ public static String xml(String ifNull, String content) { return xml(ifNull, false, content); @@ -120,12 +113,11 @@ /** * Escape content for use in XML. * - * @param ifNull The value to return if content is {@code null} - * @param escapeCRLF Should CR and LF also be escaped? - * @param content The content to escape + * @param ifNull The value to return if content is {@code null} + * @param escapeCRLF Should CR and LF also be escaped? + * @param content The content to escape * - * @return The escaped content or the value of ifNull if the content was - * {@code null} + * @return The escaped content or the value of ifNull if the content was {@code null} */ public static String xml(String ifNull, boolean escapeCRLF, String content) { if (content == null) { @@ -155,6 +147,6 @@ } } - return (sb.length() > content.length()) ? sb.toString(): content; + return (sb.length() > content.length()) ? sb.toString() : content; } } diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/security/KeyStoreUtil.java tomcat10-10.1.52/java/org/apache/tomcat/util/security/KeyStoreUtil.java --- tomcat10-10.1.40/java/org/apache/tomcat/util/security/KeyStoreUtil.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/security/KeyStoreUtil.java 2026-01-23 19:33:36.000000000 +0000 @@ -32,23 +32,17 @@ /** * Loads a KeyStore from an InputStream working around the known JDK bug - * https://bugs.openjdk.java.net/browse/JDK-8157404. + * https://bugs.openjdk.java.net/browse/JDK-8157404. This code can be removed once the minimum Java version for + * Tomcat is 13. * - * This code can be removed once the minimum Java version for Tomcat is 13. - * - * - * @param keystore The KeyStore to load from the InputStream - * @param is The InputStream to use to populate the KeyStore + * @param keystore The KeyStore to load from the InputStream + * @param is The InputStream to use to populate the KeyStore * @param storePass The password to access the KeyStore * - * @throws IOException - * If an I/O occurs reading from the given InputStream - * @throws CertificateException - * If one or more certificates can't be loaded into the - * KeyStore - * @throws NoSuchAlgorithmException - * If the algorithm specified to validate the integrity of the - * KeyStore cannot be found + * @throws IOException If an I/O occurs reading from the given InputStream + * @throws CertificateException If one or more certificates can't be loaded into the KeyStore + * @throws NoSuchAlgorithmException If the algorithm specified to validate the integrity of the KeyStore cannot be + * found */ public static void load(KeyStore keystore, InputStream is, char[] storePass) throws NoSuchAlgorithmException, CertificateException, IOException { diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/security/MD5Encoder.java tomcat10-10.1.52/java/org/apache/tomcat/util/security/MD5Encoder.java --- tomcat10-10.1.40/java/org/apache/tomcat/util/security/MD5Encoder.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/security/MD5Encoder.java 2026-01-23 19:33:36.000000000 +0000 @@ -21,11 +21,8 @@ /** * Encode an MD5 digest into a String. *

      - * The 128 bit MD5 hash is converted into a 32 character long String. - * Each character of the String is the hexadecimal representation of 4 bits - * of the digest. - * - * @author Remy Maucherat + * The 128 bit MD5 hash is converted into a 32 character long String. Each character of the String is the hexadecimal + * representation of 4 bits of the digest. * * @deprecated Unused. Use {@link HexUtils} instead. Will be removed in Tomcat 11. */ @@ -38,8 +35,8 @@ } - private static final char[] hexadecimal = {'0', '1', '2', '3', '4', '5', - '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'}; + private static final char[] hexadecimal = + { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' }; /** @@ -57,11 +54,11 @@ char[] buffer = new char[32]; - for (int i=0; i<16; i++) { + for (int i = 0; i < 16; i++) { int low = binaryData[i] & 0x0f; int high = (binaryData[i] & 0xf0) >> 4; - buffer[i*2] = hexadecimal[high]; - buffer[i*2 + 1] = hexadecimal[low]; + buffer[i * 2] = hexadecimal[high]; + buffer[i * 2 + 1] = hexadecimal[low]; } return new String(buffer); diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/security/PermissionCheck.java tomcat10-10.1.52/java/org/apache/tomcat/util/security/PermissionCheck.java --- tomcat10-10.1.40/java/org/apache/tomcat/util/security/PermissionCheck.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/security/PermissionCheck.java 2026-01-23 19:33:36.000000000 +0000 @@ -19,15 +19,12 @@ import java.security.Permission; /** - * This interface is implemented by components to enable privileged code to - * check whether the component has a given permission. - * This is typically used when a privileged component (e.g. the container) is - * performing an action on behalf of an untrusted component (e.g. a web - * application) without the current thread having passed through a code source - * provided by the untrusted component. Because the current thread has not - * passed through a code source provided by the untrusted component the - * SecurityManager assumes the code is trusted so the standard checking - * mechanisms can't be used. + * This interface is implemented by components to enable privileged code to check whether the component has a given + * permission. This is typically used when a privileged component (e.g. the container) is performing an action on behalf + * of an untrusted component (e.g. a web application) without the current thread having passed through a code source + * provided by the untrusted component. Because the current thread has not passed through a code source provided by the + * untrusted component the SecurityManager assumes the code is trusted so the standard checking mechanisms can't be + * used. */ public interface PermissionCheck { @@ -36,8 +33,8 @@ * * @param permission The permission to test * - * @return {@code false} if a SecurityManager is enabled and the component - * does not have the given permission, otherwise {@code true} + * @return {@code false} if a SecurityManager is enabled and the component does not have the given permission, + * otherwise {@code true} */ boolean check(Permission permission); } diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/security/PrivilegedSetAccessControlContext.java tomcat10-10.1.52/java/org/apache/tomcat/util/security/PrivilegedSetAccessControlContext.java --- tomcat10-10.1.40/java/org/apache/tomcat/util/security/PrivilegedSetAccessControlContext.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/security/PrivilegedSetAccessControlContext.java 2026-01-23 19:33:36.000000000 +0000 @@ -57,7 +57,7 @@ public Void run() { try { if (field != null) { - field.set(t, acc); + field.set(t, acc); } } catch (IllegalArgumentException | IllegalAccessException e) { log.warn(sm.getString("privilegedSetAccessControlContext.setFailed"), e); diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/threads/InlineExecutorService.java tomcat10-10.1.52/java/org/apache/tomcat/util/threads/InlineExecutorService.java --- tomcat10-10.1.40/java/org/apache/tomcat/util/threads/InlineExecutorService.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/threads/InlineExecutorService.java 2026-01-23 19:33:36.000000000 +0000 @@ -55,11 +55,17 @@ @Override public boolean awaitTermination(long timeout, TimeUnit unit) throws InterruptedException { + long timeoutExpiry = System.nanoTime() + unit.toNanos(timeout); + long timeoutMillis = unit.toMillis(timeout); synchronized (lock) { - if (terminated) { - return true; + /* + * Spurious wake-ups are possible. Keep waiting until the service has been terminated or the timeout has + * expired. + */ + while (!terminated && timeoutMillis > 0) { + lock.wait(timeoutMillis); + timeoutMillis = (timeoutExpiry - System.nanoTime()) / 1_000_000; } - lock.wait(unit.toMillis(timeout)); return terminated; } } diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/threads/LimitLatch.java tomcat10-10.1.52/java/org/apache/tomcat/util/threads/LimitLatch.java --- tomcat10-10.1.40/java/org/apache/tomcat/util/threads/LimitLatch.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/threads/LimitLatch.java 2026-01-23 19:33:36.000000000 +0000 @@ -25,9 +25,8 @@ import org.apache.tomcat.util.res.StringManager; /** - * Shared latch that allows the latch to be acquired a limited number of times - * after which all subsequent requests to acquire the latch will be placed in a - * FIFO queue until one of the shares is returned. + * Shared latch that allows the latch to be acquired a limited number of times after which all subsequent requests to + * acquire the latch will be placed in a FIFO queue until one of the shares is returned. */ public class LimitLatch { @@ -69,6 +68,7 @@ /** * Instantiates a LimitLatch object with an initial limit. + * * @param limit - maximum number of concurrent acquisitions of this latch */ public LimitLatch(long limit) { @@ -79,6 +79,7 @@ /** * Returns the current count for the latch + * * @return the current count for latch */ public long getCount() { @@ -87,6 +88,7 @@ /** * Obtain the current limit. + * * @return the limit */ public long getLimit() { @@ -95,13 +97,11 @@ /** - * Sets a new limit. If the limit is decreased there may be a period where - * more shares of the latch are acquired than the limit. In this case no - * more shares of the latch will be issued until sufficient shares have been - * returned to reduce the number of acquired shares of the latch to below - * the new limit. If the limit is increased, threads currently in the queue - * may not be issued one of the newly available shares until the next - * request is made for a latch. + * Sets a new limit. If the limit is decreased there may be a period where more shares of the latch are acquired + * than the limit. In this case no more shares of the latch will be issued until sufficient shares have been + * returned to reduce the number of acquired shares of the latch to below the new limit. If the limit is increased, + * threads currently in the queue may not be issued one of the newly available shares until the next request is made + * for a latch. * * @param limit The new limit */ @@ -111,33 +111,34 @@ /** - * Acquires a shared latch if one is available or waits for one if no shared - * latch is current available. + * Acquires a shared latch if one is available or waits for one if no shared latch is current available. + * * @throws InterruptedException If the current thread is interrupted */ public void countUpOrAwait() throws InterruptedException { if (log.isTraceEnabled()) { - log.trace("Counting up["+Thread.currentThread().getName()+"] latch="+getCount()); + log.trace("Counting up[" + Thread.currentThread().getName() + "] latch=" + getCount()); } sync.acquireSharedInterruptibly(1); } /** * Releases a shared latch, making it available for another thread to use. + * * @return the previous counter value */ public long countDown() { sync.releaseShared(0); long result = getCount(); if (log.isTraceEnabled()) { - log.trace("Counting down["+Thread.currentThread().getName()+"] latch="+result); + log.trace("Counting down[" + Thread.currentThread().getName() + "] latch=" + result); } return result; } /** - * Releases all waiting threads and causes the {@link #limit} to be ignored - * until {@link #reset()} is called. + * Releases all waiting threads and causes the {@link #limit} to be ignored until {@link #reset()} is called. + * * @return true if release was done */ public boolean releaseAll() { @@ -147,6 +148,7 @@ /** * Resets the latch and initializes the shared acquisition counter to zero. + * * @see #releaseAll() */ public void reset() { @@ -155,8 +157,9 @@ } /** - * Returns true if there is at least one thread waiting to - * acquire the shared lock, otherwise returns false. + * Returns true if there is at least one thread waiting to acquire the shared lock, otherwise returns + * false. + * * @return true if threads are waiting */ public boolean hasQueuedThreads() { @@ -164,8 +167,8 @@ } /** - * Provide access to the list of threads waiting to acquire this limited - * shared latch. + * Provide access to the list of threads waiting to acquire this limited shared latch. + * * @return a collection of threads */ public Collection getQueuedThreads() { diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/threads/ResizableExecutor.java tomcat10-10.1.52/java/org/apache/tomcat/util/threads/ResizableExecutor.java --- tomcat10-10.1.40/java/org/apache/tomcat/util/threads/ResizableExecutor.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/threads/ResizableExecutor.java 2026-01-23 19:33:36.000000000 +0000 @@ -30,8 +30,7 @@ int getMaxThreads(); /** - * Returns the approximate number of threads that are actively executing - * tasks. + * Returns the approximate number of threads that are actively executing tasks. * * @return the number of threads */ diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/threads/RetryableQueue.java tomcat10-10.1.52/java/org/apache/tomcat/util/threads/RetryableQueue.java --- tomcat10-10.1.40/java/org/apache/tomcat/util/threads/RetryableQueue.java 1970-01-01 00:00:00.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/threads/RetryableQueue.java 2026-01-23 19:33:36.000000000 +0000 @@ -0,0 +1,32 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.tomcat.util.threads; + +import java.util.concurrent.BlockingQueue; + +public interface RetryableQueue extends BlockingQueue { + + /** + * Used to add a task to the queue if the task has been rejected by the Executor. + * + * @param o The task to add to the queue + * + * @return {@code true} if the task was added to the queue, otherwise {@code false} + */ + boolean force(T o); +} diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/threads/ScheduledThreadPoolExecutor.java tomcat10-10.1.52/java/org/apache/tomcat/util/threads/ScheduledThreadPoolExecutor.java --- tomcat10-10.1.40/java/org/apache/tomcat/util/threads/ScheduledThreadPoolExecutor.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/threads/ScheduledThreadPoolExecutor.java 2026-01-23 19:33:36.000000000 +0000 @@ -28,8 +28,7 @@ import java.util.concurrent.TimeoutException; /** - * Class which wraps a ScheduledExecutorService, while preventing - * lifecycle and configuration operations. + * Class which wraps a ScheduledExecutorService, while preventing lifecycle and configuration operations. */ public class ScheduledThreadPoolExecutor implements ScheduledExecutorService { @@ -37,6 +36,7 @@ /** * Builds a wrapper for the given executor. + * * @param executor the wrapped executor */ public ScheduledThreadPoolExecutor(ScheduledExecutorService executor) { @@ -65,8 +65,7 @@ } @Override - public boolean awaitTermination(long timeout, TimeUnit unit) - throws InterruptedException { + public boolean awaitTermination(long timeout, TimeUnit unit) throws InterruptedException { return executor.awaitTermination(timeout, unit); } @@ -86,26 +85,23 @@ } @Override - public List> invokeAll(Collection> tasks) - throws InterruptedException { + public List> invokeAll(Collection> tasks) throws InterruptedException { return executor.invokeAll(tasks); } @Override - public List> invokeAll(Collection> tasks, long timeout, - TimeUnit unit) throws InterruptedException { + public List> invokeAll(Collection> tasks, long timeout, TimeUnit unit) + throws InterruptedException { return executor.invokeAll(tasks, timeout, unit); } @Override - public T invokeAny(Collection> tasks) - throws InterruptedException, ExecutionException { + public T invokeAny(Collection> tasks) throws InterruptedException, ExecutionException { return executor.invokeAny(tasks); } @Override - public T invokeAny(Collection> tasks, - long timeout, TimeUnit unit) + public T invokeAny(Collection> tasks, long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException { return executor.invokeAny(tasks, timeout, unit); } @@ -116,26 +112,22 @@ } @Override - public ScheduledFuture schedule(Runnable command, long delay, - TimeUnit unit) { + public ScheduledFuture schedule(Runnable command, long delay, TimeUnit unit) { return executor.schedule(command, delay, unit); } @Override - public ScheduledFuture schedule(Callable callable, long delay, - TimeUnit unit) { + public ScheduledFuture schedule(Callable callable, long delay, TimeUnit unit) { return executor.schedule(callable, delay, unit); } @Override - public ScheduledFuture scheduleAtFixedRate(Runnable command, - long initialDelay, long period, TimeUnit unit) { + public ScheduledFuture scheduleAtFixedRate(Runnable command, long initialDelay, long period, TimeUnit unit) { return executor.scheduleAtFixedRate(command, initialDelay, period, unit); } @Override - public ScheduledFuture scheduleWithFixedDelay(Runnable command, - long initialDelay, long delay, TimeUnit unit) { + public ScheduledFuture scheduleWithFixedDelay(Runnable command, long initialDelay, long delay, TimeUnit unit) { return executor.scheduleWithFixedDelay(command, initialDelay, delay, unit); } diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/threads/StopPooledThreadException.java tomcat10-10.1.52/java/org/apache/tomcat/util/threads/StopPooledThreadException.java --- tomcat10-10.1.40/java/org/apache/tomcat/util/threads/StopPooledThreadException.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/threads/StopPooledThreadException.java 2026-01-23 19:33:36.000000000 +0000 @@ -18,8 +18,8 @@ /** - * A custom {@link RuntimeException} thrown by the {@link ThreadPoolExecutor} - * to signal that the thread should be disposed of. + * A custom {@link RuntimeException} thrown by the {@link ThreadPoolExecutor} to signal that the thread should be + * disposed of. */ public class StopPooledThreadException extends RuntimeException { diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/threads/TaskQueue.java tomcat10-10.1.52/java/org/apache/tomcat/util/threads/TaskQueue.java --- tomcat10-10.1.40/java/org/apache/tomcat/util/threads/TaskQueue.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/threads/TaskQueue.java 2026-01-23 19:33:36.000000000 +0000 @@ -24,13 +24,11 @@ import org.apache.tomcat.util.res.StringManager; /** - * As task queue specifically designed to run with a thread pool executor. The - * task queue is optimised to properly utilize threads within a thread pool - * executor. If you use a normal queue, the executor will spawn threads when - * there are idle threads and you won't be able to force items onto the queue - * itself. + * As task queue specifically designed to run with a thread pool executor. The task queue is optimised to properly + * utilize threads within a thread pool executor. If you use a normal queue, the executor will spawn threads when there + * are idle threads and you won't be able to force items onto the queue itself. */ -public class TaskQueue extends LinkedBlockingQueue { +public class TaskQueue extends LinkedBlockingQueue implements RetryableQueue { private static final long serialVersionUID = 1L; protected static final StringManager sm = StringManager.getManager(TaskQueue.class); @@ -54,48 +52,40 @@ } - /** - * Used to add a task to the queue if the task has been rejected by the Executor. - * - * @param o The task to add to the queue - * - * @return {@code true} if the task was added to the queue, - * otherwise {@code false} - */ + @Override public boolean force(Runnable o) { if (parent == null || parent.isShutdown()) { throw new RejectedExecutionException(sm.getString("taskQueue.notRunning")); } - return super.offer(o); //forces the item onto the queue, to be used if the task is rejected + return super.offer(o); // forces the item onto the queue, to be used if the task is rejected } @Override public boolean offer(Runnable o) { - //we can't do any checks - if (parent==null) { + // we can't do any checks + if (parent == null) { return super.offer(o); } - //we are maxed out on threads, simply queue the object + // we are maxed out on threads, simply queue the object if (parent.getPoolSizeNoLock() == parent.getMaximumPoolSize()) { return super.offer(o); } - //we have idle threads, just add it to the queue + // we have idle threads, just add it to the queue if (parent.getSubmittedCount() <= parent.getPoolSizeNoLock()) { return super.offer(o); } - //if we have less threads than maximum force creation of a new thread + // if we have less threads than maximum force creation of a new thread if (parent.getPoolSizeNoLock() < parent.getMaximumPoolSize()) { return false; } - //if we reached here, we need to add it to the queue + // if we reached here, we need to add it to the queue return super.offer(o); } @Override - public Runnable poll(long timeout, TimeUnit unit) - throws InterruptedException { + public Runnable poll(long timeout, TimeUnit unit) throws InterruptedException { Runnable runnable = super.poll(timeout, unit); if (runnable == null && parent != null) { // the poll timed out, it gives an opportunity to stop the current @@ -108,8 +98,7 @@ @Override public Runnable take() throws InterruptedException { if (parent != null && parent.currentThreadShouldBeStopped()) { - return poll(parent.getKeepAliveTime(TimeUnit.MILLISECONDS), - TimeUnit.MILLISECONDS); + return poll(parent.getKeepAliveTime(TimeUnit.MILLISECONDS), TimeUnit.MILLISECONDS); // yes, this may return null (in case of timeout) which normally // does not occur with take() // but the ThreadPoolExecutor implementation allows this diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/threads/TaskThread.java tomcat10-10.1.52/java/org/apache/tomcat/util/threads/TaskThread.java --- tomcat10-10.1.40/java/org/apache/tomcat/util/threads/TaskThread.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/threads/TaskThread.java 2026-01-23 19:33:36.000000000 +0000 @@ -22,7 +22,6 @@ /** * A Thread implementation that records the time at which it was created. - * */ public class TaskThread extends Thread { @@ -35,8 +34,7 @@ this.creationTime = System.currentTimeMillis(); } - public TaskThread(ThreadGroup group, Runnable target, String name, - long stackSize) { + public TaskThread(ThreadGroup group, Runnable target, String name, long stackSize) { super(group, new WrappingRunnable(target), name, stackSize); this.creationTime = System.currentTimeMillis(); } @@ -49,22 +47,25 @@ } /** - * Wraps a {@link Runnable} to swallow any {@link StopPooledThreadException} - * instead of letting it go and potentially trigger a break in a debugger. + * Wraps a {@link Runnable} to swallow any {@link StopPooledThreadException} instead of letting it go and + * potentially trigger a break in a debugger. */ private static class WrappingRunnable implements Runnable { private final Runnable wrappedRunnable; + WrappingRunnable(Runnable wrappedRunnable) { this.wrappedRunnable = wrappedRunnable; } + @Override public void run() { try { wrappedRunnable.run(); - } catch(StopPooledThreadException exc) { - //expected : we just swallow the exception to avoid disturbing - //debuggers like eclipse's - log.debug(sm.getString("taskThread.exiting"), exc); + } catch (StopPooledThreadException exc) { + // expected : we just swallow the exception to avoid disturbing debuggers like eclipse's + if (log.isDebugEnabled()) { + log.debug(sm.getString("taskThread.exiting"), exc); + } } } } diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/threads/TaskThreadFactory.java tomcat10-10.1.52/java/org/apache/tomcat/util/threads/TaskThreadFactory.java --- tomcat10-10.1.40/java/org/apache/tomcat/util/threads/TaskThreadFactory.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/threads/TaskThreadFactory.java 2026-01-23 19:33:36.000000000 +0000 @@ -25,8 +25,7 @@ import org.apache.tomcat.util.security.PrivilegedSetTccl; /** - * Simple task thread factory to use to create threads for an executor - * implementation. + * Simple task thread factory to use to create threads for an executor implementation. */ public class TaskThreadFactory implements ThreadFactory { @@ -54,8 +53,7 @@ // Set the context class loader of newly created threads to be the // class loader that loaded this factory. This avoids retaining // references to web application class loaders and similar. - PrivilegedAction pa = new PrivilegedSetTccl( - t, getClass().getClassLoader()); + PrivilegedAction pa = new PrivilegedSetTccl(t, getClass().getClassLoader()); AccessController.doPrivileged(pa); // This method may be triggered from an InnocuousThread. Ensure that diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/threads/ThreadPoolExecutor.java tomcat10-10.1.52/java/org/apache/tomcat/util/threads/ThreadPoolExecutor.java --- tomcat10-10.1.40/java/org/apache/tomcat/util/threads/ThreadPoolExecutor.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/threads/ThreadPoolExecutor.java 2026-01-23 19:33:36.000000000 +0000 @@ -44,244 +44,134 @@ import org.apache.tomcat.util.res.StringManager; /** - * An {@link java.util.concurrent.ExecutorService} - * that executes each submitted task using - * one of possibly several pooled threads, normally configured - * using {@link Executors} factory methods. - * - *

      Thread pools address two different problems: they usually - * provide improved performance when executing large numbers of - * asynchronous tasks, due to reduced per-task invocation overhead, - * and they provide a means of bounding and managing the resources, - * including threads, consumed when executing a collection of tasks. - * Each {@code ThreadPoolExecutor} also maintains some basic - * statistics, such as the number of completed tasks. - * - *

      To be useful across a wide range of contexts, this class - * provides many adjustable parameters and extensibility - * hooks. However, programmers are urged to use the more convenient - * {@link Executors} factory methods {@link - * Executors#newCachedThreadPool} (unbounded thread pool, with - * automatic thread reclamation), {@link Executors#newFixedThreadPool} - * (fixed size thread pool) and {@link - * Executors#newSingleThreadExecutor} (single background thread), that - * preconfigure settings for the most common usage - * scenarios. Otherwise, use the following guide when manually - * configuring and tuning this class: - * + * An {@link java.util.concurrent.ExecutorService} that executes each submitted task using one of possibly several + * pooled threads, normally configured using {@link Executors} factory methods. + *

      + * Thread pools address two different problems: they usually provide improved performance when executing large numbers + * of asynchronous tasks, due to reduced per-task invocation overhead, and they provide a means of bounding and managing + * the resources, including threads, consumed when executing a collection of tasks. Each {@code ThreadPoolExecutor} also + * maintains some basic statistics, such as the number of completed tasks. + *

      + * To be useful across a wide range of contexts, this class provides many adjustable parameters and extensibility hooks. + * However, programmers are urged to use the more convenient {@link Executors} factory methods + * {@link Executors#newCachedThreadPool} (unbounded thread pool, with automatic thread reclamation), + * {@link Executors#newFixedThreadPool} (fixed size thread pool) and {@link Executors#newSingleThreadExecutor} (single + * background thread), that preconfigure settings for the most common usage scenarios. Otherwise, use the following + * guide when manually configuring and tuning this class: *

      - * *
      Core and maximum pool sizes
      - * - *
      A {@code ThreadPoolExecutor} will automatically adjust the - * pool size (see {@link #getPoolSize}) - * according to the bounds set by - * corePoolSize (see {@link #getCorePoolSize}) and - * maximumPoolSize (see {@link #getMaximumPoolSize}). - * - * When a new task is submitted in method {@link #execute(Runnable)}, - * if fewer than corePoolSize threads are running, a new thread is - * created to handle the request, even if other worker threads are - * idle. Else if fewer than maximumPoolSize threads are running, a - * new thread will be created to handle the request only if the queue - * is full. By setting corePoolSize and maximumPoolSize the same, you - * create a fixed-size thread pool. By setting maximumPoolSize to an - * essentially unbounded value such as {@code Integer.MAX_VALUE}, you - * allow the pool to accommodate an arbitrary number of concurrent - * tasks. Most typically, core and maximum pool sizes are set only - * upon construction, but they may also be changed dynamically using - * {@link #setCorePoolSize} and {@link #setMaximumPoolSize}.
      - * + *
      A {@code ThreadPoolExecutor} will automatically adjust the pool size (see {@link #getPoolSize}) according to the + * bounds set by corePoolSize (see {@link #getCorePoolSize}) and maximumPoolSize (see {@link #getMaximumPoolSize}). When + * a new task is submitted in method {@link #execute(Runnable)}, if fewer than corePoolSize threads are running, a new + * thread is created to handle the request, even if other worker threads are idle. Else if fewer than maximumPoolSize + * threads are running, a new thread will be created to handle the request only if the queue is full. By setting + * corePoolSize and maximumPoolSize the same, you create a fixed-size thread pool. By setting maximumPoolSize to an + * essentially unbounded value such as {@code Integer.MAX_VALUE}, you allow the pool to accommodate an arbitrary number + * of concurrent tasks. Most typically, core and maximum pool sizes are set only upon construction, but they may also be + * changed dynamically using {@link #setCorePoolSize} and {@link #setMaximumPoolSize}.
      *
      On-demand construction
      - * - *
      By default, even core threads are initially created and - * started only when new tasks arrive, but this can be overridden - * dynamically using method {@link #prestartCoreThread} or {@link - * #prestartAllCoreThreads}. You probably want to prestart threads if - * you construct the pool with a non-empty queue.
      - * + *
      By default, even core threads are initially created and started only when new tasks arrive, but this can be + * overridden dynamically using method {@link #prestartCoreThread} or {@link #prestartAllCoreThreads}. You probably want + * to prestart threads if you construct the pool with a non-empty queue.
      *
      Creating new threads
      - * - *
      New threads are created using a {@link ThreadFactory}. If not - * otherwise specified, a {@link Executors#defaultThreadFactory} is - * used, that creates threads to all be in the same {@link - * ThreadGroup} and with the same {@code NORM_PRIORITY} priority and - * non-daemon status. By supplying a different ThreadFactory, you can - * alter the thread's name, thread group, priority, daemon status, - * etc. If a {@code ThreadFactory} fails to create a thread when asked - * by returning null from {@code newThread}, the executor will - * continue, but might not be able to execute any tasks. Threads - * should possess the "modifyThread" {@code RuntimePermission}. If - * worker threads or other threads using the pool do not possess this - * permission, service may be degraded: configuration changes may not - * take effect in a timely manner, and a shutdown pool may remain in a - * state in which termination is possible but not completed.
      - * + *
      New threads are created using a {@link ThreadFactory}. If not otherwise specified, a + * {@link Executors#defaultThreadFactory} is used, that creates threads to all be in the same {@link ThreadGroup} and + * with the same {@code NORM_PRIORITY} priority and non-daemon status. By supplying a different ThreadFactory, you can + * alter the thread's name, thread group, priority, daemon status, etc. If a {@code ThreadFactory} fails to create a + * thread when asked by returning null from {@code newThread}, the executor will continue, but might not be able to + * execute any tasks. Threads should possess the "modifyThread" {@code RuntimePermission}. If worker threads or other + * threads using the pool do not possess this permission, service may be degraded: configuration changes may not take + * effect in a timely manner, and a shutdown pool may remain in a state in which termination is possible but not + * completed.
      *
      Keep-alive times
      - * - *
      If the pool currently has more than corePoolSize threads, - * excess threads will be terminated if they have been idle for more - * than the keepAliveTime (see {@link #getKeepAliveTime(TimeUnit)}). - * This provides a means of reducing resource consumption when the - * pool is not being actively used. If the pool becomes more active - * later, new threads will be constructed. This parameter can also be - * changed dynamically using method {@link #setKeepAliveTime(long, - * TimeUnit)}. Using a value of {@code Long.MAX_VALUE} {@link - * TimeUnit#NANOSECONDS} effectively disables idle threads from ever - * terminating prior to shut down. By default, the keep-alive policy - * applies only when there are more than corePoolSize threads, but - * method {@link #allowCoreThreadTimeOut(boolean)} can be used to - * apply this time-out policy to core threads as well, so long as the - * keepAliveTime value is non-zero.
      - * + *
      If the pool currently has more than corePoolSize threads, excess threads will be terminated if they have been + * idle for more than the keepAliveTime (see {@link #getKeepAliveTime(TimeUnit)}). This provides a means of reducing + * resource consumption when the pool is not being actively used. If the pool becomes more active later, new threads + * will be constructed. This parameter can also be changed dynamically using method + * {@link #setKeepAliveTime(long, TimeUnit)}. Using a value of {@code Long.MAX_VALUE} {@link TimeUnit#NANOSECONDS} + * effectively disables idle threads from ever terminating prior to shut down. By default, the keep-alive policy applies + * only when there are more than corePoolSize threads, but method {@link #allowCoreThreadTimeOut(boolean)} can be used + * to apply this time-out policy to core threads as well, so long as the keepAliveTime value is non-zero.
      *
      Queuing
      - * - *
      Any {@link BlockingQueue} may be used to transfer and hold - * submitted tasks. The use of this queue interacts with pool sizing: - * + *
      Any {@link BlockingQueue} may be used to transfer and hold submitted tasks. The use of this queue interacts with + * pool sizing: *
        - * - *
      • If fewer than corePoolSize threads are running, the Executor - * always prefers adding a new thread - * rather than queuing. - * - *
      • If corePoolSize or more threads are running, the Executor - * always prefers queuing a request rather than adding a new - * thread. - * - *
      • If a request cannot be queued, a new thread is created unless - * this would exceed maximumPoolSize, in which case, the task will be - * rejected. - * + *
      • If fewer than corePoolSize threads are running, the Executor always prefers adding a new thread rather than + * queuing. + *
      • If corePoolSize or more threads are running, the Executor always prefers queuing a request rather than adding a + * new thread. + *
      • If a request cannot be queued, a new thread is created unless this would exceed maximumPoolSize, in which case, + * the task will be rejected. *
      - * * There are three general strategies for queuing: *
        - * - *
      1. Direct handoffs. A good default choice for a work - * queue is a {@link java.util.concurrent.SynchronousQueue} - * that hands off tasks to threads - * without otherwise holding them. Here, an attempt to queue a task - * will fail if no threads are immediately available to run it, so a - * new thread will be constructed. This policy avoids lockups when - * handling sets of requests that might have internal dependencies. - * Direct handoffs generally require unbounded maximumPoolSizes to - * avoid rejection of new submitted tasks. This in turn admits the - * possibility of unbounded thread growth when commands continue to - * arrive faster on average than they can be processed. - * - *
      2. Unbounded queues. Using an unbounded queue (for - * example a {@link java.util.concurrent.LinkedBlockingQueue} - * without a predefined - * capacity) will cause new tasks to wait in the queue when all - * corePoolSize threads are busy. Thus, no more than corePoolSize - * threads will ever be created. (And the value of the maximumPoolSize - * therefore doesn't have any effect.) This may be appropriate when - * each task is completely independent of others, so tasks cannot - * affect each others execution; for example, in a web page server. - * While this style of queuing can be useful in smoothing out - * transient bursts of requests, it admits the possibility of - * unbounded work queue growth when commands continue to arrive faster - * on average than they can be processed. - * - *
      3. Bounded queues. A bounded queue (for example, an - * {@link java.util.concurrent.ArrayBlockingQueue}) - * helps prevent resource exhaustion when - * used with finite maximumPoolSizes, but can be more difficult to - * tune and control. Queue sizes and maximum pool sizes may be traded - * off for each other: Using large queues and small pools minimizes - * CPU usage, OS resources, and context-switching overhead, but can - * lead to artificially low throughput. If tasks frequently block (for - * example if they are I/O bound), a system may be able to schedule - * time for more threads than you otherwise allow. Use of small queues - * generally requires larger pool sizes, which keeps CPUs busier but - * may encounter unacceptable scheduling overhead, which also - * decreases throughput. - * + *
      4. Direct handoffs. A good default choice for a work queue is a + * {@link java.util.concurrent.SynchronousQueue} that hands off tasks to threads without otherwise holding them. Here, + * an attempt to queue a task will fail if no threads are immediately available to run it, so a new thread will be + * constructed. This policy avoids lockups when handling sets of requests that might have internal dependencies. Direct + * handoffs generally require unbounded maximumPoolSizes to avoid rejection of new submitted tasks. This in turn admits + * the possibility of unbounded thread growth when commands continue to arrive faster on average than they can be + * processed. + *
      5. Unbounded queues. Using an unbounded queue (for example a + * {@link java.util.concurrent.LinkedBlockingQueue} without a predefined capacity) will cause new tasks to wait in the + * queue when all corePoolSize threads are busy. Thus, no more than corePoolSize threads will ever be created. (And the + * value of the maximumPoolSize therefore doesn't have any effect.) This may be appropriate when each task is completely + * independent of others, so tasks cannot affect each others execution; for example, in a web page server. While this + * style of queuing can be useful in smoothing out transient bursts of requests, it admits the possibility of unbounded + * work queue growth when commands continue to arrive faster on average than they can be processed. + *
      6. Bounded queues. A bounded queue (for example, an {@link java.util.concurrent.ArrayBlockingQueue}) helps + * prevent resource exhaustion when used with finite maximumPoolSizes, but can be more difficult to tune and control. + * Queue sizes and maximum pool sizes may be traded off for each other: Using large queues and small pools minimizes CPU + * usage, OS resources, and context-switching overhead, but can lead to artificially low throughput. If tasks frequently + * block (for example if they are I/O bound), a system may be able to schedule time for more threads than you otherwise + * allow. Use of small queues generally requires larger pool sizes, which keeps CPUs busier but may encounter + * unacceptable scheduling overhead, which also decreases throughput. *
      - * *
      - * *
      Rejected tasks
      - * - *
      New tasks submitted in method {@link #execute(Runnable)} will be - * rejected when the Executor has been shut down, and also when - * the Executor uses finite bounds for both maximum threads and work queue - * capacity, and is saturated. In either case, the {@code execute} method - * invokes the {@link - * RejectedExecutionHandler#rejectedExecution(Runnable, ThreadPoolExecutor)} - * method of its {@link RejectedExecutionHandler}. Four predefined handler - * policies are provided: - * + *
      New tasks submitted in method {@link #execute(Runnable)} will be rejected when the Executor has been + * shut down, and also when the Executor uses finite bounds for both maximum threads and work queue capacity, and is + * saturated. In either case, the {@code execute} method invokes the + * {@link RejectedExecutionHandler#rejectedExecution(Runnable, ThreadPoolExecutor)} method of its + * {@link RejectedExecutionHandler}. Four predefined handler policies are provided: *
        - * - *
      1. In the default {@link ThreadPoolExecutor.AbortPolicy}, the handler - * throws a runtime {@link RejectedExecutionException} upon rejection. - * - *
      2. In {@link ThreadPoolExecutor.CallerRunsPolicy}, the thread - * that invokes {@code execute} itself runs the task. This provides a - * simple feedback control mechanism that will slow down the rate that - * new tasks are submitted. - * - *
      3. In {@link ThreadPoolExecutor.DiscardPolicy}, a task that cannot - * be executed is simply dropped. This policy is designed only for - * those rare cases in which task completion is never relied upon. - * - *
      4. In {@link ThreadPoolExecutor.DiscardOldestPolicy}, if the - * executor is not shut down, the task at the head of the work queue - * is dropped, and then execution is retried (which can fail again, - * causing this to be repeated.) This policy is rarely acceptable. In - * nearly all cases, you should also cancel the task to cause an - * exception in any component waiting for its completion, and/or log - * the failure, as illustrated in {@link - * ThreadPoolExecutor.DiscardOldestPolicy} documentation. - * + *
      5. In the default {@link ThreadPoolExecutor.AbortPolicy}, the handler throws a runtime + * {@link RejectedExecutionException} upon rejection. + *
      6. In {@link ThreadPoolExecutor.CallerRunsPolicy}, the thread that invokes {@code execute} itself runs the task. + * This provides a simple feedback control mechanism that will slow down the rate that new tasks are submitted. + *
      7. In {@link ThreadPoolExecutor.DiscardPolicy}, a task that cannot be executed is simply dropped. This policy is + * designed only for those rare cases in which task completion is never relied upon. + *
      8. In {@link ThreadPoolExecutor.DiscardOldestPolicy}, if the executor is not shut down, the task at the head of the + * work queue is dropped, and then execution is retried (which can fail again, causing this to be repeated.) This policy + * is rarely acceptable. In nearly all cases, you should also cancel the task to cause an exception in any component + * waiting for its completion, and/or log the failure, as illustrated in {@link ThreadPoolExecutor.DiscardOldestPolicy} + * documentation. *
      - * - * It is possible to define and use other kinds of {@link - * RejectedExecutionHandler} classes. Doing so requires some care - * especially when policies are designed to work only under particular - * capacity or queuing policies.
      - * + * It is possible to define and use other kinds of {@link RejectedExecutionHandler} classes. Doing so requires some care + * especially when policies are designed to work only under particular capacity or queuing policies. *
      Hook methods
      - * - *
      This class provides {@code protected} overridable - * {@link #beforeExecute(Thread, Runnable)} and - * {@link #afterExecute(Runnable, Throwable)} methods that are called - * before and after execution of each task. These can be used to - * manipulate the execution environment; for example, reinitializing - * ThreadLocals, gathering statistics, or adding log entries. - * Additionally, method {@link #terminated} can be overridden to perform - * any special processing that needs to be done once the Executor has - * fully terminated. - * - *

      If hook, callback, or BlockingQueue methods throw exceptions, - * internal worker threads may in turn fail, abruptly terminate, and - * possibly be replaced.

      - * + *
      This class provides {@code protected} overridable {@link #beforeExecute(Thread, Runnable)} and + * {@link #afterExecute(Runnable, Throwable)} methods that are called before and after execution of each task. These can + * be used to manipulate the execution environment; for example, reinitializing ThreadLocals, gathering statistics, or + * adding log entries. Additionally, method {@link #terminated} can be overridden to perform any special processing that + * needs to be done once the Executor has fully terminated. + *

      + * If hook, callback, or BlockingQueue methods throw exceptions, internal worker threads may in turn fail, abruptly + * terminate, and possibly be replaced.

      *
      Queue maintenance
      - * - *
      Method {@link #getQueue()} allows access to the work queue - * for purposes of monitoring and debugging. Use of this method for - * any other purpose is strongly discouraged. Two supplied methods, - * {@link #remove(Runnable)} and {@link #purge} are available to - * assist in storage reclamation when large numbers of queued tasks - * become cancelled.
      - * + *
      Method {@link #getQueue()} allows access to the work queue for purposes of monitoring and debugging. Use of this + * method for any other purpose is strongly discouraged. Two supplied methods, {@link #remove(Runnable)} and + * {@link #purge} are available to assist in storage reclamation when large numbers of queued tasks become + * cancelled.
      *
      Reclamation
      - * - *
      A pool that is no longer referenced in a program AND - * has no remaining threads may be reclaimed (garbage collected) - * without being explicitly shutdown. You can configure a pool to - * allow all unused threads to eventually die by setting appropriate - * keep-alive times, using a lower bound of zero core threads and/or - * setting {@link #allowCoreThreadTimeOut(boolean)}.
      - * + *
      A pool that is no longer referenced in a program AND has no remaining threads may be reclaimed (garbage + * collected) without being explicitly shutdown. You can configure a pool to allow all unused threads to eventually die + * by setting appropriate keep-alive times, using a lower bound of zero core threads and/or setting + * {@link #allowCoreThreadTimeOut(boolean)}.
      *
      - * - *

      Extension example. Most extensions of this class - * override one or more of the protected hook methods. For example, - * here is a subclass that adds a simple pause/resume feature: + *

      + * Extension example. Most extensions of this class override one or more of the protected hook methods. For + * example, here is a subclass that adds a simple pause/resume feature: * *

       {@code
        * class PausableThreadPoolExecutor extends ThreadPoolExecutor {
      @@ -324,87 +214,74 @@
        * }}
      * * @since 1.5 - * @author Doug Lea */ public class ThreadPoolExecutor extends AbstractExecutorService { protected static final StringManager sm = StringManager.getManager(ThreadPoolExecutor.class); /** - * The main pool control state, ctl, is an atomic integer packing - * two conceptual fields - * workerCount, indicating the effective number of threads - * runState, indicating whether running, shutting down etc - * - * In order to pack them into one int, we limit workerCount to - * (2^29)-1 (about 500 million) threads rather than (2^31)-1 (2 - * billion) otherwise representable. If this is ever an issue in - * the future, the variable can be changed to be an AtomicLong, - * and the shift/mask constants below adjusted. But until the need - * arises, this code is a bit faster and simpler using an int. - * - * The workerCount is the number of workers that have been - * permitted to start and not permitted to stop. The value may be - * transiently different from the actual number of live threads, - * for example when a ThreadFactory fails to create a thread when - * asked, and when exiting threads are still performing - * bookkeeping before terminating. The user-visible pool size is - * reported as the current size of the workers set. - * + * The main pool control state, ctl, is an atomic integer packing two conceptual fields: + *
        + *
      • workerCount, indicating the effective number of threads
      • + *
      • runState, indicating whether running, shutting down etc
      • + *
      + * In order to pack them into one int, we limit workerCount to (2^29)-1 (about 500 million) threads rather than + * (2^31)-1 (2 billion) otherwise representable. If this is ever an issue in the future, the variable can be changed + * to be an AtomicLong, and the shift/mask constants below adjusted. But until the need arises, this code is a bit + * faster and simpler using an int. + *

      + * The workerCount is the number of workers that have been permitted to start and not permitted to stop. The value + * may be transiently different from the actual number of live threads, for example when a ThreadFactory fails to + * create a thread when asked, and when exiting threads are still performing bookkeeping before terminating. The + * user-visible pool size is reported as the current size of the workers set. + *

      * The runState provides the main lifecycle control, taking on values: - * - * RUNNING: Accept new tasks and process queued tasks - * SHUTDOWN: Don't accept new tasks, but process queued tasks - * STOP: Don't accept new tasks, don't process queued tasks, - * and interrupt in-progress tasks - * TIDYING: All tasks have terminated, workerCount is zero, - * the thread transitioning to state TIDYING - * will run the terminated() hook method - * TERMINATED: terminated() has completed - * - * The numerical order among these values matters, to allow - * ordered comparisons. The runState monotonically increases over - * time, but need not hit each state. The transitions are: - * - * RUNNING -> SHUTDOWN - * On invocation of shutdown() - * (RUNNING or SHUTDOWN) -> STOP - * On invocation of shutdownNow() - * SHUTDOWN -> TIDYING - * When both queue and pool are empty - * STOP -> TIDYING - * When pool is empty - * TIDYING -> TERMINATED - * When the terminated() hook method has completed - * - * Threads waiting in awaitTermination() will return when the - * state reaches TERMINATED. - * - * Detecting the transition from SHUTDOWN to TIDYING is less - * straightforward than you'd like because the queue may become - * empty after non-empty and vice versa during SHUTDOWN state, but - * we can only terminate if, after seeing that it is empty, we see - * that workerCount is 0 (which sometimes entails a recheck -- see - * below). + *

        + *
      • RUNNING: Accept new tasks and process queued tasks
      • + *
      • SHUTDOWN: Don't accept new tasks, but process queued tasks
      • + *
      • STOP: Don't accept new tasks, don't process queued tasks, and interrupt in-progress tasks
      • + *
      • TIDYING: All tasks have terminated, workerCount is zero, the thread transitioning to state TIDYING will run + * the terminated() hook method
      • + *
      • TERMINATED: terminated() has completed
      • + *
      + * The numerical order among these values matters, to allow ordered comparisons. The runState monotonically + * increases over time, but need not hit each state. The transitions are: + *
        + *
      • RUNNING -> SHUTDOWN On invocation of shutdown()
      • + *
      • (RUNNING or SHUTDOWN) -> STOP On invocation of shutdownNow()
      • + *
      • SHUTDOWN -> TIDYING When both queue and pool are empty
      • + *
      • STOP -> TIDYING When pool is empty
      • + *
      • TIDYING -> TERMINATED When the terminated() hook method has completed
      • + *
      + * Threads waiting in awaitTermination() will return when the state reaches TERMINATED. + *

      + * Detecting the transition from SHUTDOWN to TIDYING is less straightforward than you'd like because the queue may + * become empty after non-empty and vice versa during SHUTDOWN state, but we can only terminate if, after seeing + * that it is empty, we see that workerCount is 0 (which sometimes entails a recheck -- see below). */ private final AtomicInteger ctl = new AtomicInteger(ctlOf(RUNNING, 0)); private static final int COUNT_BITS = Integer.SIZE - 3; private static final int COUNT_MASK = (1 << COUNT_BITS) - 1; // runState is stored in the high-order bits - private static final int RUNNING = -1 << COUNT_BITS; - private static final int SHUTDOWN = 0; - private static final int STOP = 1 << COUNT_BITS; - private static final int TIDYING = 2 << COUNT_BITS; - private static final int TERMINATED = 3 << COUNT_BITS; + private static final int RUNNING = -1 << COUNT_BITS; + private static final int SHUTDOWN = 0; + private static final int STOP = 1 << COUNT_BITS; + private static final int TIDYING = 2 << COUNT_BITS; + private static final int TERMINATED = 3 << COUNT_BITS; // Packing and unpacking ctl - private static int workerCountOf(int c) { return c & COUNT_MASK; } - private static int ctlOf(int rs, int wc) { return rs | wc; } + private static int workerCountOf(int c) { + return c & COUNT_MASK; + } + + private static int ctlOf(int rs, int wc) { + return rs | wc; + } /* - * Bit field accessors that don't require unpacking ctl. - * These depend on the bit layout and on workerCount being never negative. + * Bit field accessors that don't require unpacking ctl. These depend on the bit layout and on workerCount being + * never negative. */ private static boolean runStateLessThan(int c, int s) { @@ -434,45 +311,35 @@ } /** - * Decrements the workerCount field of ctl. This is called only on - * abrupt termination of a thread (see processWorkerExit). Other - * decrements are performed within getTask. + * Decrements the workerCount field of ctl. This is called only on abrupt termination of a thread (see + * processWorkerExit). Other decrements are performed within getTask. */ private void decrementWorkerCount() { ctl.addAndGet(-1); } /** - * The queue used for holding tasks and handing off to worker - * threads. We do not require that workQueue.poll() returning - * null necessarily means that workQueue.isEmpty(), so rely - * solely on isEmpty to see if the queue is empty (which we must - * do for example when deciding whether to transition from - * SHUTDOWN to TIDYING). This accommodates special-purpose - * queues such as DelayQueues for which poll() is allowed to - * return null even if it may later return non-null when delays - * expire. + * The queue used for holding tasks and handing off to worker threads. We do not require that workQueue.poll() + * returning null necessarily means that workQueue.isEmpty(), so rely solely on isEmpty to see if the queue is empty + * (which we must do for example when deciding whether to transition from SHUTDOWN to TIDYING). This accommodates + * special-purpose queues such as DelayQueues for which poll() is allowed to return null even if it may later return + * non-null when delays expire. */ private final BlockingQueue workQueue; /** - * Lock held on access to workers set and related bookkeeping. - * While we could use a concurrent set of some sort, it turns out - * to be generally preferable to use a lock. Among the reasons is - * that this serializes interruptIdleWorkers, which avoids - * unnecessary interrupt storms, especially during shutdown. - * Otherwise, exiting threads would concurrently interrupt those - * that have not yet interrupted. It also simplifies some of the - * associated statistics bookkeeping of largestPoolSize etc. We - * also hold mainLock on shutdown and shutdownNow, for the sake of - * ensuring workers set is stable while separately checking - * permission to interrupt and actually interrupting. + * Lock held on access to workers set and related bookkeeping. While we could use a concurrent set of some sort, it + * turns out to be generally preferable to use a lock. Among the reasons is that this serializes + * interruptIdleWorkers, which avoids unnecessary interrupt storms, especially during shutdown. Otherwise, exiting + * threads would concurrently interrupt those that have not yet interrupted. It also simplifies some of the + * associated statistics bookkeeping of largestPoolSize etc. We also hold mainLock on shutdown and shutdownNow, for + * the sake of ensuring workers set is stable while separately checking permission to interrupt and actually + * interrupting. */ private final ReentrantLock mainLock = new ReentrantLock(); /** - * Set containing all worker threads in pool. Accessed only when - * holding mainLock. + * Set containing all worker threads in pool. Accessed only when holding mainLock. */ private final HashSet workers = new HashSet<>(); @@ -482,38 +349,33 @@ private final Condition termination = mainLock.newCondition(); /** - * Tracks largest attained pool size. Accessed only under - * mainLock. + * Tracks largest attained pool size. Accessed only under mainLock. */ private int largestPoolSize; /** - * Counter for completed tasks. Updated only on termination of - * worker threads. Accessed only under mainLock. + * Counter for completed tasks. Updated only on termination of worker threads. Accessed only under mainLock. */ private long completedTaskCount; /** - * The number of tasks submitted but not yet finished. This includes tasks - * in the queue and tasks that have been handed to a worker thread but the - * latter did not start executing the task yet. - * This number is always greater or equal to {@link #getActiveCount()}. + * The number of tasks submitted but not yet finished. This includes tasks in the queue and tasks that have been + * handed to a worker thread but the latter did not start executing the task yet. This number is always greater or + * equal to {@link #getActiveCount()}. */ private final AtomicInteger submittedCount = new AtomicInteger(0); private final AtomicLong lastContextStoppedTime = new AtomicLong(0L); /** - * Most recent time in ms when a thread decided to kill itself to avoid - * potential memory leaks. Useful to throttle the rate of renewals of - * threads. + * Most recent time in ms when a thread decided to kill itself to avoid potential memory leaks. Useful to throttle + * the rate of renewals of threads. */ private final AtomicLong lastTimeThreadKilledItself = new AtomicLong(0L); /* - * All user control parameters are declared as volatiles so that - * ongoing actions are based on freshest values, but without need - * for locking, since no internal invariants depend on them - * changing synchronously with respect to other actions. + * All user control parameters are declared as volatiles so that ongoing actions are based on freshest values, but + * without need for locking, since no internal invariants depend on them changing synchronously with respect to + * other actions. */ /** @@ -522,21 +384,15 @@ private volatile long threadRenewalDelay = Constants.DEFAULT_THREAD_RENEWAL_DELAY; /** - * Factory for new threads. All threads are created using this - * factory (via method addWorker). All callers must be prepared - * for addWorker to fail, which may reflect a system or user's - * policy limiting the number of threads. Even though it is not - * treated as an error, failure to create threads may result in - * new tasks being rejected or existing ones remaining stuck in - * the queue. - * - * We go further and preserve pool invariants even in the face of - * errors such as OutOfMemoryError, that might be thrown while - * trying to create threads. Such errors are rather common due to - * the need to allocate a native stack in Thread.start, and users - * will want to perform clean pool shutdown to clean up. There - * will likely be enough memory available for the cleanup code to - * complete without encountering yet another OutOfMemoryError. + * Factory for new threads. All threads are created using this factory (via method addWorker). All callers must be + * prepared for addWorker to fail, which may reflect a system or user's policy limiting the number of threads. Even + * though it is not treated as an error, failure to create threads may result in new tasks being rejected or + * existing ones remaining stuck in the queue. + *

      + * We go further and preserve pool invariants even in the face of errors such as OutOfMemoryError, that might be + * thrown while trying to create threads. Such errors are rather common due to the need to allocate a native stack + * in Thread.start, and users will want to perform clean pool shutdown to clean up. There will likely be enough + * memory available for the cleanup code to complete without encountering yet another OutOfMemoryError. */ private volatile ThreadFactory threadFactory; @@ -546,35 +402,31 @@ private volatile RejectedExecutionHandler handler; /** - * Timeout in nanoseconds for idle threads waiting for work. - * Threads use this timeout when there are more than corePoolSize - * present or if allowCoreThreadTimeOut. Otherwise, they wait - * forever for new work. + * Timeout in nanoseconds for idle threads waiting for work. Threads use this timeout when there are more than + * corePoolSize present or if allowCoreThreadTimeOut. Otherwise, they wait forever for new work. */ private volatile long keepAliveTime; /** - * If false (default), core threads stay alive even when idle. - * If true, core threads use keepAliveTime to time out waiting - * for work. + * If false (default), core threads stay alive even when idle. If true, core threads use keepAliveTime to time out + * waiting for work. */ private volatile boolean allowCoreThreadTimeOut; /** - * Core pool size is the minimum number of workers to keep alive - * (and not allow to time out etc) unless allowCoreThreadTimeOut - * is set, in which case the minimum is zero. - * - * Since the worker count is actually stored in COUNT_BITS bits, - * the effective limit is {@code corePoolSize & COUNT_MASK}. + * Core pool size is the minimum number of workers to keep alive (and not allow to time out etc) unless + * allowCoreThreadTimeOut is set, in which case the minimum is zero. + *

      + * Since the worker count is actually stored in COUNT_BITS bits, the effective limit is + * {@code corePoolSize & COUNT_MASK}. */ private volatile int corePoolSize; /** * Maximum pool size. - * - * Since the worker count is actually stored in COUNT_BITS bits, - * the effective limit is {@code maximumPoolSize & COUNT_MASK}. + *

      + * Since the worker count is actually stored in COUNT_BITS bits, the effective limit is + * {@code maximumPoolSize & COUNT_MASK}. */ private volatile int maximumPoolSize; @@ -584,57 +436,37 @@ private static final RejectedExecutionHandler defaultHandler = new RejectPolicy(); /** - * Permission required for callers of shutdown and shutdownNow. - * We additionally require (see checkShutdownAccess) that callers - * have permission to actually interrupt threads in the worker set - * (as governed by Thread.interrupt, which relies on - * ThreadGroup.checkAccess, which in turn relies on - * SecurityManager.checkAccess). Shutdowns are attempted only if - * these checks pass. - * - * All actual invocations of Thread.interrupt (see - * interruptIdleWorkers and interruptWorkers) ignore - * SecurityExceptions, meaning that the attempted interrupts - * silently fail. In the case of shutdown, they should not fail - * unless the SecurityManager has inconsistent policies, sometimes - * allowing access to a thread and sometimes not. In such cases, - * failure to actually interrupt threads may disable or delay full - * termination. Other uses of interruptIdleWorkers are advisory, - * and failure to actually interrupt will merely delay response to - * configuration changes so is not handled exceptionally. - */ - private static final RuntimePermission shutdownPerm = - new RuntimePermission("modifyThread"); - - /** - * Class Worker mainly maintains interrupt control state for - * threads running tasks, along with other minor bookkeeping. - * This class opportunistically extends AbstractQueuedSynchronizer - * to simplify acquiring and releasing a lock surrounding each - * task execution. This protects against interrupts that are - * intended to wake up a worker thread waiting for a task from - * instead interrupting a task being run. We implement a simple - * non-reentrant mutual exclusion lock rather than use - * ReentrantLock because we do not want worker tasks to be able to - * reacquire the lock when they invoke pool control methods like - * setCorePoolSize. Additionally, to suppress interrupts until - * the thread actually starts running tasks, we initialize lock - * state to a negative value, and clear it upon start (in + * Permission required for callers of shutdown and shutdownNow. We additionally require (see checkShutdownAccess) + * that callers have permission to actually interrupt threads in the worker set (as governed by Thread.interrupt, + * which relies on ThreadGroup.checkAccess, which in turn relies on SecurityManager.checkAccess). Shutdowns are + * attempted only if these checks pass. All actual invocations of Thread.interrupt (see interruptIdleWorkers and + * interruptWorkers) ignore SecurityExceptions, meaning that the attempted interrupts silently fail. In the case of + * shutdown, they should not fail unless the SecurityManager has inconsistent policies, sometimes allowing access to + * a thread and sometimes not. In such cases, failure to actually interrupt threads may disable or delay full + * termination. Other uses of interruptIdleWorkers are advisory, and failure to actually interrupt will merely delay + * response to configuration changes so is not handled exceptionally. + */ + private static final RuntimePermission shutdownPerm = new RuntimePermission("modifyThread"); + + /** + * Class Worker mainly maintains interrupt control state for threads running tasks, along with other minor + * bookkeeping. This class opportunistically extends AbstractQueuedSynchronizer to simplify acquiring and releasing + * a lock surrounding each task execution. This protects against interrupts that are intended to wake up a worker + * thread waiting for a task from instead interrupting a task being run. We implement a simple non-reentrant mutual + * exclusion lock rather than use ReentrantLock because we do not want worker tasks to be able to reacquire the lock + * when they invoke pool control methods like setCorePoolSize. Additionally, to suppress interrupts until the thread + * actually starts running tasks, we initialize lock state to a negative value, and clear it upon start (in * runWorker). */ - private final class Worker - extends AbstractQueuedSynchronizer - implements Runnable - { + private final class Worker extends AbstractQueuedSynchronizer implements Runnable { /** - * This class will never be serialized, but we provide a - * serialVersionUID to suppress a javac warning. + * This class will never be serialized, but we provide a serialVersionUID to suppress a javac warning. */ private static final long serialVersionUID = 6138294804551838833L; - /** Thread this worker is running in. Null if factory fails. */ + /** Thread this worker is running in. Null if factory fails. */ final Thread thread; - /** Initial task to run. Possibly null. */ + /** Initial task to run. Possibly null. */ Runnable firstTask; /** Per-thread task counter */ volatile long completedTasks; @@ -644,6 +476,7 @@ /** * Creates with given first task and thread from ThreadFactory. + * * @param firstTask the first task (null if none) */ Worker(Runnable firstTask) { @@ -684,10 +517,21 @@ return true; } - public void lock() { acquire(1); } - public boolean tryLock() { return tryAcquire(1); } - public void unlock() { release(1); } - public boolean isLocked() { return isHeldExclusively(); } + public void lock() { + acquire(1); + } + + public boolean tryLock() { + return tryAcquire(1); + } + + public void unlock() { + release(1); + } + + public boolean isLocked() { + return isHeldExclusively(); + } void interruptIfStarted() { Thread t; @@ -705,39 +549,32 @@ */ /** - * Transitions runState to given target, or leaves it alone if - * already at least the given target. + * Transitions runState to given target, or leaves it alone if already at least the given target. * - * @param targetState the desired state, either SHUTDOWN or STOP - * (but not TIDYING or TERMINATED -- use tryTerminate for that) + * @param targetState the desired state, either SHUTDOWN or STOP (but not TIDYING or TERMINATED -- use tryTerminate + * for that) */ private void advanceRunState(int targetState) { // assert targetState == SHUTDOWN || targetState == STOP; for (;;) { int c = ctl.get(); - if (runStateAtLeast(c, targetState) || - ctl.compareAndSet(c, ctlOf(targetState, workerCountOf(c)))) { + if (runStateAtLeast(c, targetState) || ctl.compareAndSet(c, ctlOf(targetState, workerCountOf(c)))) { break; } } } /** - * Transitions to TERMINATED state if either (SHUTDOWN and pool - * and queue empty) or (STOP and pool empty). If otherwise - * eligible to terminate but workerCount is nonzero, interrupts an - * idle worker to ensure that shutdown signals propagate. This - * method must be called following any action that might make - * termination possible -- reducing worker count or removing tasks - * from the queue during shutdown. The method is non-private to - * allow access from ScheduledThreadPoolExecutor. + * Transitions to TERMINATED state if either (SHUTDOWN and pool and queue empty) or (STOP and pool empty). If + * otherwise eligible to terminate but workerCount is nonzero, interrupts an idle worker to ensure that shutdown + * signals propagate. This method must be called following any action that might make termination possible -- + * reducing worker count or removing tasks from the queue during shutdown. The method is non-private to allow access + * from ScheduledThreadPoolExecutor. */ final void tryTerminate() { for (;;) { int c = ctl.get(); - if (isRunning(c) || - runStateAtLeast(c, TIDYING) || - (runStateLessThan(c, STOP) && ! workQueue.isEmpty())) { + if (isRunning(c) || runStateAtLeast(c, TIDYING) || (runStateLessThan(c, STOP) && !workQueue.isEmpty())) { return; } if (workerCountOf(c) != 0) { // Eligible to terminate @@ -769,12 +606,9 @@ */ /** - * If there is a security manager, makes sure caller has - * permission to shut down threads in general (see shutdownPerm). - * If this passes, additionally makes sure the caller is allowed - * to interrupt each worker thread. This might not be true even if - * first check passed, if the SecurityManager treats some threads - * specially. + * If there is a security manager, makes sure caller has permission to shut down threads in general (see + * shutdownPerm). If this passes, additionally makes sure the caller is allowed to interrupt each worker thread. + * This might not be true even if first check passed, if the SecurityManager treats some threads specially. */ private void checkShutdownAccess() { // assert mainLock.isHeldByCurrentThread(); @@ -788,8 +622,8 @@ } /** - * Interrupts all threads, even if active. Ignores SecurityExceptions - * (in which case some threads may remain uninterrupted). + * Interrupts all threads, even if active. Ignores SecurityExceptions (in which case some threads may remain + * uninterrupted). */ private void interruptWorkers() { // assert mainLock.isHeldByCurrentThread(); @@ -799,23 +633,17 @@ } /** - * Interrupts threads that might be waiting for tasks (as - * indicated by not being locked) so they can check for - * termination or configuration changes. Ignores - * SecurityExceptions (in which case some threads may remain + * Interrupts threads that might be waiting for tasks (as indicated by not being locked) so they can check for + * termination or configuration changes. Ignores SecurityExceptions (in which case some threads may remain * uninterrupted). * - * @param onlyOne If true, interrupt at most one worker. This is - * called only from tryTerminate when termination is otherwise - * enabled but there are still other workers. In this case, at - * most one waiting worker is interrupted to propagate shutdown - * signals in case all threads are currently waiting. - * Interrupting any arbitrary thread ensures that newly arriving - * workers since shutdown began will also eventually exit. - * To guarantee eventual termination, it suffices to always - * interrupt only one idle worker, but shutdown() interrupts all - * idle workers so that redundant workers exit promptly, not - * waiting for a straggler task to finish. + * @param onlyOne If true, interrupt at most one worker. This is called only from tryTerminate when termination is + * otherwise enabled but there are still other workers. In this case, at most one waiting worker + * is interrupted to propagate shutdown signals in case all threads are currently waiting. + * Interrupting any arbitrary thread ensures that newly arriving workers since shutdown began + * will also eventually exit. To guarantee eventual termination, it suffices to always interrupt + * only one idle worker, but shutdown() interrupts all idle workers so that redundant workers + * exit promptly, not waiting for a straggler task to finish. */ private void interruptIdleWorkers(boolean onlyOne) { final ReentrantLock mainLock = this.mainLock; @@ -841,8 +669,7 @@ } /** - * Common form of interruptIdleWorkers, to avoid having to - * remember what the boolean argument means. + * Common form of interruptIdleWorkers, to avoid having to remember what the boolean argument means. */ private void interruptIdleWorkers() { interruptIdleWorkers(false); @@ -851,31 +678,27 @@ private static final boolean ONLY_ONE = true; /* - * Misc utilities, most of which are also exported to - * ScheduledThreadPoolExecutor + * Misc utilities, most of which are also exported to ScheduledThreadPoolExecutor */ /** - * Invokes the rejected execution handler for the given command. - * Package-protected for use by ScheduledThreadPoolExecutor. + * Invokes the rejected execution handler for the given command. Package-protected for use by + * ScheduledThreadPoolExecutor. */ final void reject(Runnable command) { handler.rejectedExecution(command, this); } /** - * Performs any further cleanup following run state transition on - * invocation of shutdown. A no-op here, but used by + * Performs any further cleanup following run state transition on invocation of shutdown. A no-op here, but used by * ScheduledThreadPoolExecutor to cancel delayed tasks. */ void onShutdown() { } /** - * Drains the task queue into a new list, normally using - * drainTo. But if the queue is a DelayQueue or any other kind of - * queue for which poll or drainTo may fail to remove some - * elements, it deletes them one by one. + * Drains the task queue into a new list, normally using drainTo. But if the queue is a DelayQueue or any other kind + * of queue for which poll or drainTo may fail to remove some elements, it deletes them one by one. */ private List drainQueue() { BlockingQueue q = workQueue; @@ -896,55 +719,43 @@ */ /** - * Checks if a new worker can be added with respect to current - * pool state and the given bound (either core or maximum). If so, - * the worker count is adjusted accordingly, and, if possible, a - * new worker is created and started, running firstTask as its - * first task. This method returns false if the pool is stopped or - * eligible to shut down. It also returns false if the thread - * factory fails to create a thread when asked. If the thread - * creation fails, either due to the thread factory returning - * null, or due to an exception (typically OutOfMemoryError in + * Checks if a new worker can be added with respect to current pool state and the given bound (either core or + * maximum). If so, the worker count is adjusted accordingly, and, if possible, a new worker is created and started, + * running firstTask as its first task. This method returns false if the pool is stopped or eligible to shut down. + * It also returns false if the thread factory fails to create a thread when asked. If the thread creation fails, + * either due to the thread factory returning null, or due to an exception (typically OutOfMemoryError in * Thread.start()), we roll back cleanly. * - * @param firstTask the task the new thread should run first (or - * null if none). Workers are created with an initial first task - * (in method execute()) to bypass queuing when there are fewer - * than corePoolSize threads (in which case we always start one), - * or when the queue is full (in which case we must bypass queue). - * Initially idle threads are usually created via - * prestartCoreThread or to replace other dying workers. - * - * @param core if true use corePoolSize as bound, else - * maximumPoolSize. (A boolean indicator is used here rather than a - * value to ensure reads of fresh values after checking other pool - * state). + * @param firstTask the task the new thread should run first (or null if none). Workers are created with an initial + * first task (in method execute()) to bypass queuing when there are fewer than corePoolSize + * threads (in which case we always start one), or when the queue is full (in which case we + * must bypass queue). Initially idle threads are usually created via prestartCoreThread or to + * replace other dying workers. + * @param core if true use corePoolSize as bound, else maximumPoolSize. (A boolean indicator is used here + * rather than a value to ensure reads of fresh values after checking other pool state). + * * @return true if successful */ private boolean addWorker(Runnable firstTask, boolean core) { retry: for (int c = ctl.get();;) { // Check if queue empty only if necessary. - if (runStateAtLeast(c, SHUTDOWN) - && (runStateAtLeast(c, STOP) - || firstTask != null - || workQueue.isEmpty())) { + if (runStateAtLeast(c, SHUTDOWN) && + (runStateAtLeast(c, STOP) || firstTask != null || workQueue.isEmpty())) { return false; } for (;;) { - if (workerCountOf(c) - >= ((core ? corePoolSize : maximumPoolSize) & COUNT_MASK)) { + if (workerCountOf(c) >= ((core ? corePoolSize : maximumPoolSize) & COUNT_MASK)) { return false; } if (compareAndIncrementWorkerCount(c)) { break retry; } - c = ctl.get(); // Re-read ctl - if (runStateAtLeast(c, SHUTDOWN)) - { + c = ctl.get(); // Re-read ctl + if (runStateAtLeast(c, SHUTDOWN)) { continue retry; - // else CAS failed due to workerCount change; retry inner loop + // else CAS failed due to workerCount change; retry inner loop } } } @@ -964,8 +775,7 @@ // shut down before lock acquired. int c = ctl.get(); - if (isRunning(c) || - (runStateLessThan(c, STOP) && firstTask == null)) { + if (isRunning(c) || (runStateLessThan(c, STOP) && firstTask == null)) { if (t.getState() != Thread.State.NEW) { throw new IllegalThreadStateException(); } @@ -985,7 +795,7 @@ } } } finally { - if (! workerStarted) { + if (!workerStarted) { addWorkerFailed(w); } } @@ -994,10 +804,11 @@ /** * Rolls back the worker thread creation. - * - removes worker from workers, if present - * - decrements worker count - * - rechecks for termination, in case the existence of this - * worker was holding up termination + *

        + *
      • removes worker from workers, if present
      • + *
      • decrements worker count
      • + *
      • rechecks for termination, in case the existence of this worker was holding up termination
      • + *
      */ private void addWorkerFailed(Worker w) { final ReentrantLock mainLock = this.mainLock; @@ -1014,16 +825,12 @@ } /** - * Performs cleanup and bookkeeping for a dying worker. Called - * only from worker threads. Unless completedAbruptly is set, - * assumes that workerCount has already been adjusted to account - * for exit. This method removes thread from worker set, and - * possibly terminates the pool or replaces the worker if either - * it exited due to user task exception or if fewer than - * corePoolSize workers are running or queue is non-empty but - * there are no workers. + * Performs cleanup and bookkeeping for a dying worker. Called only from worker threads. Unless completedAbruptly is + * set, assumes that workerCount has already been adjusted to account for exit. This method removes thread from + * worker set, and possibly terminates the pool or replaces the worker if either it exited due to user task + * exception or if fewer than corePoolSize workers are running or queue is non-empty but there are no workers. * - * @param w the worker + * @param w the worker * @param completedAbruptly if the worker died due to user exception */ private void processWorkerExit(Worker w, boolean completedAbruptly) { @@ -1046,7 +853,7 @@ if (runStateLessThan(c, STOP)) { if (!completedAbruptly) { int min = allowCoreThreadTimeOut ? 0 : corePoolSize; - if (min == 0 && ! workQueue.isEmpty()) { + if (min == 0 && !workQueue.isEmpty()) { min = 1; } // https://bz.apache.org/bugzilla/show_bug.cgi?id=65454 @@ -1065,21 +872,18 @@ } /** - * Performs blocking or timed wait for a task, depending on - * current configuration settings, or returns null if this worker - * must exit because of any of: - * 1. There are more than maximumPoolSize workers (due to - * a call to setMaximumPoolSize). - * 2. The pool is stopped. - * 3. The pool is shutdown and the queue is empty. - * 4. This worker timed out waiting for a task, and timed-out - * workers are subject to termination (that is, - * {@code allowCoreThreadTimeOut || workerCount > corePoolSize}) - * both before and after the timed wait, and if the queue is - * non-empty, this worker is not the last thread in the pool. + * Performs blocking or timed wait for a task, depending on current configuration settings, or returns null if this + * worker must exit because of any of: + *
        + *
      1. There are more than maximumPoolSize workers (due to a call to setMaximumPoolSize).
      2. + *
      3. The pool is stopped.
      4. + *
      5. The pool is shutdown and the queue is empty.
      6. + *
      7. This worker timed out waiting for a task, and timed-out workers are subject to termination (that is, + * {@code allowCoreThreadTimeOut || workerCount > corePoolSize}) both before and after the timed wait, and if the + * queue is non-empty, this worker is not the last thread in the pool.
      8. + *
      * - * @return task, or null if the worker must exit, in which case - * workerCount is decremented + * @return task, or null if the worker must exit, in which case workerCount is decremented */ private Runnable getTask() { boolean timedOut = false; // Did the last poll() time out? @@ -1088,8 +892,7 @@ int c = ctl.get(); // Check if queue empty only if necessary. - if (runStateAtLeast(c, SHUTDOWN) - && (runStateAtLeast(c, STOP) || workQueue.isEmpty())) { + if (runStateAtLeast(c, SHUTDOWN) && (runStateAtLeast(c, STOP) || workQueue.isEmpty())) { decrementWorkerCount(); return null; } @@ -1099,8 +902,7 @@ // Are workers subject to culling? boolean timed = allowCoreThreadTimeOut || wc > corePoolSize; - if ((wc > maximumPoolSize || (timed && timedOut)) - && (wc > 1 || workQueue.isEmpty())) { + if ((wc > maximumPoolSize || (timed && timedOut)) && (wc > 1 || workQueue.isEmpty())) { if (compareAndDecrementWorkerCount(c)) { return null; } @@ -1108,9 +910,7 @@ } try { - Runnable r = timed ? - workQueue.poll(keepAliveTime, TimeUnit.NANOSECONDS) : - workQueue.take(); + Runnable r = timed ? workQueue.poll(keepAliveTime, TimeUnit.NANOSECONDS) : workQueue.take(); if (r != null) { return r; } @@ -1122,45 +922,31 @@ } /** - * Main worker run loop. Repeatedly gets tasks from queue and - * executes them, while coping with a number of issues: - * - * 1. We may start out with an initial task, in which case we - * don't need to get the first one. Otherwise, as long as pool is - * running, we get tasks from getTask. If it returns null then the - * worker exits due to changed pool state or configuration - * parameters. Other exits result from exception throws in - * external code, in which case completedAbruptly holds, which - * usually leads processWorkerExit to replace this thread. - * - * 2. Before running any task, the lock is acquired to prevent - * other pool interrupts while the task is executing, and then we - * ensure that unless pool is stopping, this thread does not have - * its interrupt set. - * - * 3. Each task run is preceded by a call to beforeExecute, which - * might throw an exception, in which case we cause thread to die - * (breaking loop with completedAbruptly true) without processing - * the task. - * - * 4. Assuming beforeExecute completes normally, we run the task, - * gathering any of its thrown exceptions to send to afterExecute. - * We separately handle RuntimeException, Error (both of which the - * specs guarantee that we trap) and arbitrary Throwables. - * Because we cannot rethrow Throwables within Runnable.run, we - * wrap them within Errors on the way out (to the thread's - * UncaughtExceptionHandler). Any thrown exception also - * conservatively causes thread to die. - * - * 5. After task.run completes, we call afterExecute, which may - * also throw an exception, which will also cause thread to - * die. According to JLS Sec 14.20, this exception is the one that - * will be in effect even if task.run throws. - * - * The net effect of the exception mechanics is that afterExecute - * and the thread's UncaughtExceptionHandler have as accurate - * information as we can provide about any problems encountered by - * user code. + * Main worker run loop. Repeatedly gets tasks from queue and executes them, while coping with a number of issues: + *

      + * 1. We may start out with an initial task, in which case we don't need to get the first one. Otherwise, as long as + * pool is running, we get tasks from getTask. If it returns null then the worker exits due to changed pool state or + * configuration parameters. Other exits result from exception throws in external code, in which case + * completedAbruptly holds, which usually leads processWorkerExit to replace this thread. + *

      + * 2. Before running any task, the lock is acquired to prevent other pool interrupts while the task is executing, + * and then we ensure that unless pool is stopping, this thread does not have its interrupt set. + *

      + * 3. Each task run is preceded by a call to beforeExecute, which might throw an exception, in which case we cause + * thread to die (breaking loop with completedAbruptly true) without processing the task. + *

      + * 4. Assuming beforeExecute completes normally, we run the task, gathering any of its thrown exceptions to send to + * afterExecute. We separately handle RuntimeException, Error (both of which the specs guarantee that we trap) and + * arbitrary Throwables. Because we cannot rethrow Throwables within Runnable.run, we wrap them within Errors on the + * way out (to the thread's UncaughtExceptionHandler). Any thrown exception also conservatively causes thread to + * die. + *

      + * 5. After task.run completes, we call afterExecute, which may also throw an exception, which will also cause + * thread to die. According to JLS Sec 14.20, this exception is the one that will be in effect even if task.run + * throws. + *

      + * The net effect of the exception mechanics is that afterExecute and the thread's UncaughtExceptionHandler have as + * accurate information as we can provide about any problems encountered by user code. * * @param w the worker */ @@ -1174,13 +960,11 @@ while (task != null || (task = getTask()) != null) { w.lock(); // If pool is stopping, ensure thread is interrupted; - // if not, ensure thread is not interrupted. This + // if not, ensure thread is not interrupted. This // requires a recheck in second case to deal with // shutdownNow race while clearing interrupt - if ((runStateAtLeast(ctl.get(), STOP) || - (Thread.interrupted() && - runStateAtLeast(ctl.get(), STOP))) && - !wt.isInterrupted()) { + if ((runStateAtLeast(ctl.get(), STOP) || (Thread.interrupted() && runStateAtLeast(ctl.get(), STOP))) && + !wt.isInterrupted()) { wt.interrupt(); } try { @@ -1207,152 +991,113 @@ // Public constructors and methods /** - * Creates a new {@code ThreadPoolExecutor} with the given initial - * parameters, the - * {@linkplain Executors#defaultThreadFactory default thread factory} - * and the {@linkplain ThreadPoolExecutor.RejectPolicy - * default rejected execution handler}. - * - *

      It may be more convenient to use one of the {@link Executors} - * factory methods instead of this general purpose constructor. - * - * @param corePoolSize the number of threads to keep in the pool, even - * if they are idle, unless {@code allowCoreThreadTimeOut} is set - * @param maximumPoolSize the maximum number of threads to allow in the - * pool - * @param keepAliveTime when the number of threads is greater than - * the core, this is the maximum time that excess idle threads - * will wait for new tasks before terminating. - * @param unit the time unit for the {@code keepAliveTime} argument - * @param workQueue the queue to use for holding tasks before they are - * executed. This queue will hold only the {@code Runnable} - * tasks submitted by the {@code execute} method. + * Creates a new {@code ThreadPoolExecutor} with the given initial parameters, the + * {@linkplain Executors#defaultThreadFactory default thread factory} and the + * {@linkplain ThreadPoolExecutor.RejectPolicy default rejected execution handler}. + *

      + * It may be more convenient to use one of the {@link Executors} factory methods instead of this general purpose + * constructor. + * + * @param corePoolSize the number of threads to keep in the pool, even if they are idle, unless + * {@code allowCoreThreadTimeOut} is set + * @param maximumPoolSize the maximum number of threads to allow in the pool + * @param keepAliveTime when the number of threads is greater than the core, this is the maximum time that excess + * idle threads will wait for new tasks before terminating. + * @param unit the time unit for the {@code keepAliveTime} argument + * @param workQueue the queue to use for holding tasks before they are executed. This queue will hold only the + * {@code Runnable} tasks submitted by the {@code execute} method. + * * @throws IllegalArgumentException if one of the following holds:
      - * {@code corePoolSize < 0}
      - * {@code keepAliveTime < 0}
      - * {@code maximumPoolSize <= 0}
      - * {@code maximumPoolSize < corePoolSize} - * @throws NullPointerException if {@code workQueue} is null - */ - public ThreadPoolExecutor(int corePoolSize, - int maximumPoolSize, - long keepAliveTime, - TimeUnit unit, - BlockingQueue workQueue) { - this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, - Executors.defaultThreadFactory(), defaultHandler); + * {@code corePoolSize < 0}
      + * {@code keepAliveTime < 0}
      + * {@code maximumPoolSize <= 0}
      + * {@code maximumPoolSize < corePoolSize} + * @throws NullPointerException if {@code workQueue} is null + */ + public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, + BlockingQueue workQueue) { + this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, Executors.defaultThreadFactory(), + defaultHandler); } /** - * Creates a new {@code ThreadPoolExecutor} with the given initial - * parameters and the {@linkplain ThreadPoolExecutor.RejectPolicy - * default rejected execution handler}. - * - * @param corePoolSize the number of threads to keep in the pool, even - * if they are idle, unless {@code allowCoreThreadTimeOut} is set - * @param maximumPoolSize the maximum number of threads to allow in the - * pool - * @param keepAliveTime when the number of threads is greater than - * the core, this is the maximum time that excess idle threads - * will wait for new tasks before terminating. - * @param unit the time unit for the {@code keepAliveTime} argument - * @param workQueue the queue to use for holding tasks before they are - * executed. This queue will hold only the {@code Runnable} - * tasks submitted by the {@code execute} method. - * @param threadFactory the factory to use when the executor - * creates a new thread + * Creates a new {@code ThreadPoolExecutor} with the given initial parameters and the + * {@linkplain ThreadPoolExecutor.RejectPolicy default rejected execution handler}. + * + * @param corePoolSize the number of threads to keep in the pool, even if they are idle, unless + * {@code allowCoreThreadTimeOut} is set + * @param maximumPoolSize the maximum number of threads to allow in the pool + * @param keepAliveTime when the number of threads is greater than the core, this is the maximum time that excess + * idle threads will wait for new tasks before terminating. + * @param unit the time unit for the {@code keepAliveTime} argument + * @param workQueue the queue to use for holding tasks before they are executed. This queue will hold only the + * {@code Runnable} tasks submitted by the {@code execute} method. + * @param threadFactory the factory to use when the executor creates a new thread + * * @throws IllegalArgumentException if one of the following holds:
      - * {@code corePoolSize < 0}
      - * {@code keepAliveTime < 0}
      - * {@code maximumPoolSize <= 0}
      - * {@code maximumPoolSize < corePoolSize} - * @throws NullPointerException if {@code workQueue} - * or {@code threadFactory} is null - */ - public ThreadPoolExecutor(int corePoolSize, - int maximumPoolSize, - long keepAliveTime, - TimeUnit unit, - BlockingQueue workQueue, - ThreadFactory threadFactory) { - this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, - threadFactory, defaultHandler); + * {@code corePoolSize < 0}
      + * {@code keepAliveTime < 0}
      + * {@code maximumPoolSize <= 0}
      + * {@code maximumPoolSize < corePoolSize} + * @throws NullPointerException if {@code workQueue} or {@code threadFactory} is null + */ + public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, + BlockingQueue workQueue, ThreadFactory threadFactory) { + this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, threadFactory, defaultHandler); } /** - * Creates a new {@code ThreadPoolExecutor} with the given initial - * parameters and the + * Creates a new {@code ThreadPoolExecutor} with the given initial parameters and the * {@linkplain Executors#defaultThreadFactory default thread factory}. * - * @param corePoolSize the number of threads to keep in the pool, even - * if they are idle, unless {@code allowCoreThreadTimeOut} is set - * @param maximumPoolSize the maximum number of threads to allow in the - * pool - * @param keepAliveTime when the number of threads is greater than - * the core, this is the maximum time that excess idle threads - * will wait for new tasks before terminating. - * @param unit the time unit for the {@code keepAliveTime} argument - * @param workQueue the queue to use for holding tasks before they are - * executed. This queue will hold only the {@code Runnable} - * tasks submitted by the {@code execute} method. - * @param handler the handler to use when execution is blocked - * because the thread bounds and queue capacities are reached + * @param corePoolSize the number of threads to keep in the pool, even if they are idle, unless + * {@code allowCoreThreadTimeOut} is set + * @param maximumPoolSize the maximum number of threads to allow in the pool + * @param keepAliveTime when the number of threads is greater than the core, this is the maximum time that excess + * idle threads will wait for new tasks before terminating. + * @param unit the time unit for the {@code keepAliveTime} argument + * @param workQueue the queue to use for holding tasks before they are executed. This queue will hold only the + * {@code Runnable} tasks submitted by the {@code execute} method. + * @param handler the handler to use when execution is blocked because the thread bounds and queue + * capacities are reached + * * @throws IllegalArgumentException if one of the following holds:
      - * {@code corePoolSize < 0}
      - * {@code keepAliveTime < 0}
      - * {@code maximumPoolSize <= 0}
      - * {@code maximumPoolSize < corePoolSize} - * @throws NullPointerException if {@code workQueue} - * or {@code handler} is null - */ - public ThreadPoolExecutor(int corePoolSize, - int maximumPoolSize, - long keepAliveTime, - TimeUnit unit, - BlockingQueue workQueue, - RejectedExecutionHandler handler) { - this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, - Executors.defaultThreadFactory(), handler); + * {@code corePoolSize < 0}
      + * {@code keepAliveTime < 0}
      + * {@code maximumPoolSize <= 0}
      + * {@code maximumPoolSize < corePoolSize} + * @throws NullPointerException if {@code workQueue} or {@code handler} is null + */ + public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, + BlockingQueue workQueue, RejectedExecutionHandler handler) { + this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, Executors.defaultThreadFactory(), handler); } /** - * Creates a new {@code ThreadPoolExecutor} with the given initial - * parameters. - * - * @param corePoolSize the number of threads to keep in the pool, even - * if they are idle, unless {@code allowCoreThreadTimeOut} is set - * @param maximumPoolSize the maximum number of threads to allow in the - * pool - * @param keepAliveTime when the number of threads is greater than - * the core, this is the maximum time that excess idle threads - * will wait for new tasks before terminating. - * @param unit the time unit for the {@code keepAliveTime} argument - * @param workQueue the queue to use for holding tasks before they are - * executed. This queue will hold only the {@code Runnable} - * tasks submitted by the {@code execute} method. - * @param threadFactory the factory to use when the executor - * creates a new thread - * @param handler the handler to use when execution is blocked - * because the thread bounds and queue capacities are reached + * Creates a new {@code ThreadPoolExecutor} with the given initial parameters. + * + * @param corePoolSize the number of threads to keep in the pool, even if they are idle, unless + * {@code allowCoreThreadTimeOut} is set + * @param maximumPoolSize the maximum number of threads to allow in the pool + * @param keepAliveTime when the number of threads is greater than the core, this is the maximum time that excess + * idle threads will wait for new tasks before terminating. + * @param unit the time unit for the {@code keepAliveTime} argument + * @param workQueue the queue to use for holding tasks before they are executed. This queue will hold only the + * {@code Runnable} tasks submitted by the {@code execute} method. + * @param threadFactory the factory to use when the executor creates a new thread + * @param handler the handler to use when execution is blocked because the thread bounds and queue + * capacities are reached + * * @throws IllegalArgumentException if one of the following holds:
      - * {@code corePoolSize < 0}
      - * {@code keepAliveTime < 0}
      - * {@code maximumPoolSize <= 0}
      - * {@code maximumPoolSize < corePoolSize} - * @throws NullPointerException if {@code workQueue} - * or {@code threadFactory} or {@code handler} is null - */ - public ThreadPoolExecutor(int corePoolSize, - int maximumPoolSize, - long keepAliveTime, - TimeUnit unit, - BlockingQueue workQueue, - ThreadFactory threadFactory, - RejectedExecutionHandler handler) { - if (corePoolSize < 0 || - maximumPoolSize <= 0 || - maximumPoolSize < corePoolSize || - keepAliveTime < 0) { + * {@code corePoolSize < 0}
      + * {@code keepAliveTime < 0}
      + * {@code maximumPoolSize <= 0}
      + * {@code maximumPoolSize < corePoolSize} + * @throws NullPointerException if {@code workQueue} or {@code threadFactory} or {@code handler} is null + */ + public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, + BlockingQueue workQueue, ThreadFactory threadFactory, RejectedExecutionHandler handler) { + if (corePoolSize < 0 || maximumPoolSize <= 0 || maximumPoolSize < corePoolSize || keepAliveTime < 0) { throw new IllegalArgumentException(); } if (workQueue == null || threadFactory == null || handler == null) { @@ -1375,12 +1120,12 @@ try { executeInternal(command); } catch (RejectedExecutionException rx) { - if (getQueue() instanceof TaskQueue) { + if (getQueue() instanceof RetryableQueue) { // If the Executor is close to maximum pool size, concurrent // calls to execute() may result (due to Tomcat's use of // TaskQueue) in some tasks being rejected rather than queued. // If this happens, add them to the queue. - final TaskQueue queue = (TaskQueue) getQueue(); + final RetryableQueue queue = (RetryableQueue) getQueue(); if (!queue.force(command)) { submittedCount.decrementAndGet(); throw new RejectedExecutionException(sm.getString("threadPoolExecutor.queueFull")); @@ -1394,18 +1139,15 @@ /** - * Executes the given task sometime in the future. The task - * may execute in a new thread or in an existing pooled thread. - * - * If the task cannot be submitted for execution, either because this - * executor has been shutdown or because its capacity has been reached, - * the task is handled by the current {@link RejectedExecutionHandler}. + * Executes the given task sometime in the future. The task may execute in a new thread or in an existing pooled + * thread. If the task cannot be submitted for execution, either because this executor has been shutdown or because + * its capacity has been reached, the task is handled by the current {@link RejectedExecutionHandler}. * * @param command the task to execute - * @throws RejectedExecutionException at discretion of - * {@code RejectedExecutionHandler}, if the task - * cannot be accepted for execution - * @throws NullPointerException if {@code command} is null + * + * @throws RejectedExecutionException at discretion of {@code RejectedExecutionHandler}, if the task cannot be + * accepted for execution + * @throws NullPointerException if {@code command} is null */ private void executeInternal(Runnable command) { if (command == null) { @@ -1414,22 +1156,17 @@ /* * Proceed in 3 steps: * - * 1. If fewer than corePoolSize threads are running, try to - * start a new thread with the given command as its first - * task. The call to addWorker atomically checks runState and - * workerCount, and so prevents false alarms that would add - * threads when it shouldn't, by returning false. + * 1. If fewer than corePoolSize threads are running, try to start a new thread with the given command as its + * first task. The call to addWorker atomically checks runState and workerCount, and so prevents false alarms + * that would add threads when it shouldn't, by returning false. * - * 2. If a task can be successfully queued, then we still need - * to double-check whether we should have added a thread - * (because existing ones died since last checking) or that - * the pool shut down since entry into this method. So we - * recheck state and if necessary roll back the enqueuing if - * stopped, or start a new thread if there are none. + * 2. If a task can be successfully queued, then we still need to double-check whether we should have added a + * thread (because existing ones died since last checking) or that the pool shut down since entry into this + * method. So we recheck state and if necessary roll back the enqueuing if stopped, or start a new thread if + * there are none. * - * 3. If we cannot queue task, then we try to add a new - * thread. If it fails, we know we are shut down or saturated - * and so reject the task. + * 3. If we cannot queue task, then we try to add a new thread. If it fails, we know we are shut down or + * saturated and so reject the task. */ int c = ctl.get(); if (workerCountOf(c) < corePoolSize) { @@ -1440,25 +1177,22 @@ } if (isRunning(c) && workQueue.offer(command)) { int recheck = ctl.get(); - if (! isRunning(recheck) && remove(command)) { + if (!isRunning(recheck) && remove(command)) { reject(command); } else if (workerCountOf(recheck) == 0) { addWorker(null, false); } - } - else if (!addWorker(command, false)) { + } else if (!addWorker(command, false)) { reject(command); } } /** - * Initiates an orderly shutdown in which previously submitted - * tasks are executed, but no new tasks will be accepted. - * Invocation has no additional effect if already shut down. - * - *

      This method does not wait for previously submitted tasks to - * complete execution. Use {@link #awaitTermination awaitTermination} - * to do that. + * Initiates an orderly shutdown in which previously submitted tasks are executed, but no new tasks will be + * accepted. Invocation has no additional effect if already shut down. + *

      + * This method does not wait for previously submitted tasks to complete execution. Use {@link #awaitTermination + * awaitTermination} to do that. * * @throws SecurityException {@inheritDoc} */ @@ -1478,19 +1212,16 @@ } /** - * Attempts to stop all actively executing tasks, halts the - * processing of waiting tasks, and returns a list of the tasks - * that were awaiting execution. These tasks are drained (removed) - * from the task queue upon return from this method. - * - *

      This method does not wait for actively executing tasks to - * terminate. Use {@link #awaitTermination awaitTermination} to - * do that. - * - *

      There are no guarantees beyond best-effort attempts to stop - * processing actively executing tasks. This implementation - * interrupts tasks via {@link Thread#interrupt}; any task that - * fails to respond to interrupts may never terminate. + * Attempts to stop all actively executing tasks, halts the processing of waiting tasks, and returns a list of the + * tasks that were awaiting execution. These tasks are drained (removed) from the task queue upon return from this + * method. + *

      + * This method does not wait for actively executing tasks to terminate. Use {@link #awaitTermination + * awaitTermination} to do that. + *

      + * There are no guarantees beyond best-effort attempts to stop processing actively executing tasks. This + * implementation interrupts tasks via {@link Thread#interrupt}; any task that fails to respond to interrupts may + * never terminate. * * @throws SecurityException {@inheritDoc} */ @@ -1522,13 +1253,10 @@ } /** - * Returns true if this executor is in the process of terminating - * after {@link #shutdown} or {@link #shutdownNow} but has not - * completely terminated. This method may be useful for - * debugging. A return of {@code true} reported a sufficient - * period after shutdown may indicate that submitted tasks have - * ignored or suppressed interruption, causing this executor not - * to properly terminate. + * Returns true if this executor is in the process of terminating after {@link #shutdown} or {@link #shutdownNow} + * but has not completely terminated. This method may be useful for debugging. A return of {@code true} reported a + * sufficient period after shutdown may indicate that submitted tasks have ignored or suppressed interruption, + * causing this executor not to properly terminate. * * @return {@code true} if terminating but not yet terminated */ @@ -1543,8 +1271,7 @@ } @Override - public boolean awaitTermination(long timeout, TimeUnit unit) - throws InterruptedException { + public boolean awaitTermination(long timeout, TimeUnit unit) throws InterruptedException { long nanos = unit.toNanos(timeout); final ReentrantLock mainLock = this.mainLock; mainLock.lock(); @@ -1565,7 +1292,9 @@ * Sets the thread factory used to create new threads. * * @param threadFactory the new thread factory + * * @throws NullPointerException if threadFactory is null + * * @see #getThreadFactory */ public void setThreadFactory(ThreadFactory threadFactory) { @@ -1579,6 +1308,7 @@ * Returns the thread factory used to create new threads. * * @return the current thread factory + * * @see #setThreadFactory(ThreadFactory) */ public ThreadFactory getThreadFactory() { @@ -1589,7 +1319,9 @@ * Sets a new handler for unexecutable tasks. * * @param handler the new handler + * * @throws NullPointerException if handler is null + * * @see #getRejectedExecutionHandler */ public void setRejectedExecutionHandler(RejectedExecutionHandler handler) { @@ -1603,6 +1335,7 @@ * Returns the current handler for unexecutable tasks. * * @return the current handler + * * @see #setRejectedExecutionHandler(RejectedExecutionHandler) */ public RejectedExecutionHandler getRejectedExecutionHandler() { @@ -1610,16 +1343,15 @@ } /** - * Sets the core number of threads. This overrides any value set - * in the constructor. If the new value is smaller than the - * current value, excess existing threads will be terminated when - * they next become idle. If larger, new threads will, if needed, - * be started to execute any queued tasks. + * Sets the core number of threads. This overrides any value set in the constructor. If the new value is smaller + * than the current value, excess existing threads will be terminated when they next become idle. If larger, new + * threads will, if needed, be started to execute any queued tasks. * * @param corePoolSize the new core size - * @throws IllegalArgumentException if {@code corePoolSize < 0} - * or {@code corePoolSize} is greater than the {@linkplain - * #getMaximumPoolSize() maximum pool size} + * + * @throws IllegalArgumentException if {@code corePoolSize < 0} or {@code corePoolSize} is greater than the + * {@linkplain #getMaximumPoolSize() maximum pool size} + * * @see #getCorePoolSize */ public void setCorePoolSize(int corePoolSize) { @@ -1648,6 +1380,7 @@ * Returns the core number of threads. * * @return the core number of threads + * * @see #setCorePoolSize */ public int getCorePoolSize() { @@ -1655,21 +1388,18 @@ } /** - * Starts a core thread, causing it to idly wait for work. This - * overrides the default policy of starting core threads only when - * new tasks are executed. This method will return {@code false} - * if all core threads have already been started. + * Starts a core thread, causing it to idly wait for work. This overrides the default policy of starting core + * threads only when new tasks are executed. This method will return {@code false} if all core threads have already + * been started. * * @return {@code true} if a thread was started */ public boolean prestartCoreThread() { - return workerCountOf(ctl.get()) < corePoolSize && - addWorker(null, true); + return workerCountOf(ctl.get()) < corePoolSize && addWorker(null, true); } /** - * Same as prestartCoreThread except arranges that at least one - * thread is started even if corePoolSize is 0. + * Same as prestartCoreThread except arranges that at least one thread is started even if corePoolSize is 0. */ void ensurePrestart() { int wc = workerCountOf(ctl.get()); @@ -1681,9 +1411,8 @@ } /** - * Starts all core threads, causing them to idly wait for work. This - * overrides the default policy of starting core threads only when - * new tasks are executed. + * Starts all core threads, causing them to idly wait for work. This overrides the default policy of starting core + * threads only when new tasks are executed. * * @return the number of threads started */ @@ -1696,15 +1425,12 @@ } /** - * Returns true if this pool allows core threads to time out and - * terminate if no tasks arrive within the keepAlive time, being - * replaced if needed when new tasks arrive. When true, the same - * keep-alive policy applying to non-core threads applies also to - * core threads. When false (the default), core threads are never - * terminated due to lack of incoming tasks. + * Returns true if this pool allows core threads to time out and terminate if no tasks arrive within the keepAlive + * time, being replaced if needed when new tasks arrive. When true, the same keep-alive policy applying to non-core + * threads applies also to core threads. When false (the default), core threads are never terminated due to lack of + * incoming tasks. * - * @return {@code true} if core threads are allowed to time out, - * else {@code false} + * @return {@code true} if core threads are allowed to time out, else {@code false} * * @since 1.6 */ @@ -1713,19 +1439,16 @@ } /** - * Sets the policy governing whether core threads may time out and - * terminate if no tasks arrive within the keep-alive time, being - * replaced if needed when new tasks arrive. When false, core - * threads are never terminated due to lack of incoming - * tasks. When true, the same keep-alive policy applying to - * non-core threads applies also to core threads. To avoid - * continual thread replacement, the keep-alive time must be - * greater than zero when setting {@code true}. This method - * should in general be called before the pool is actively used. + * Sets the policy governing whether core threads may time out and terminate if no tasks arrive within the + * keep-alive time, being replaced if needed when new tasks arrive. When false, core threads are never terminated + * due to lack of incoming tasks. When true, the same keep-alive policy applying to non-core threads applies also to + * core threads. To avoid continual thread replacement, the keep-alive time must be greater than zero when setting + * {@code true}. This method should in general be called before the pool is actively used. * * @param value {@code true} if should time out, else {@code false} - * @throws IllegalArgumentException if value is {@code true} - * and the current keep-alive time is not greater than zero + * + * @throws IllegalArgumentException if value is {@code true} and the current keep-alive time is not greater than + * zero * * @since 1.6 */ @@ -1742,15 +1465,14 @@ } /** - * Sets the maximum allowed number of threads. This overrides any - * value set in the constructor. If the new value is smaller than - * the current value, excess existing threads will be - * terminated when they next become idle. + * Sets the maximum allowed number of threads. This overrides any value set in the constructor. If the new value is + * smaller than the current value, excess existing threads will be terminated when they next become idle. * * @param maximumPoolSize the new maximum - * @throws IllegalArgumentException if the new maximum is - * less than or equal to zero, or - * less than the {@linkplain #getCorePoolSize core pool size} + * + * @throws IllegalArgumentException if the new maximum is less than or equal to zero, or less than the + * {@linkplain #getCorePoolSize core pool size} + * * @see #getMaximumPoolSize */ public void setMaximumPoolSize(int maximumPoolSize) { @@ -1767,6 +1489,7 @@ * Returns the maximum allowed number of threads. * * @return the maximum allowed number of threads + * * @see #setMaximumPoolSize */ public int getMaximumPoolSize() { @@ -1774,19 +1497,18 @@ } /** - * Sets the thread keep-alive time, which is the amount of time - * that threads may remain idle before being terminated. - * Threads that wait this amount of time without processing a - * task will be terminated if there are more than the core - * number of threads currently in the pool, or if this pool - * {@linkplain #allowsCoreThreadTimeOut() allows core thread timeout}. - * This overrides any value set in the constructor. + * Sets the thread keep-alive time, which is the amount of time that threads may remain idle before being + * terminated. Threads that wait this amount of time without processing a task will be terminated if there are more + * than the core number of threads currently in the pool, or if this pool {@linkplain #allowsCoreThreadTimeOut() + * allows core thread timeout}. This overrides any value set in the constructor. * - * @param time the time to wait. A time value of zero will cause - * excess threads to terminate immediately after executing tasks. + * @param time the time to wait. A time value of zero will cause excess threads to terminate immediately after + * executing tasks. * @param unit the time unit of the {@code time} argument - * @throws IllegalArgumentException if {@code time} less than zero or - * if {@code time} is zero and {@code allowsCoreThreadTimeOut} + * + * @throws IllegalArgumentException if {@code time} less than zero or if {@code time} is zero and + * {@code allowsCoreThreadTimeOut} + * * @see #getKeepAliveTime(TimeUnit) */ public void setKeepAliveTime(long time, TimeUnit unit) { @@ -1805,15 +1527,15 @@ } /** - * Returns the thread keep-alive time, which is the amount of time - * that threads may remain idle before being terminated. - * Threads that wait this amount of time without processing a - * task will be terminated if there are more than the core - * number of threads currently in the pool, or if this pool - * {@linkplain #allowsCoreThreadTimeOut() allows core thread timeout}. + * Returns the thread keep-alive time, which is the amount of time that threads may remain idle before being + * terminated. Threads that wait this amount of time without processing a task will be terminated if there are more + * than the core number of threads currently in the pool, or if this pool {@linkplain #allowsCoreThreadTimeOut() + * allows core thread timeout}. * * @param unit the desired time unit of the result + * * @return the time limit + * * @see #setKeepAliveTime(long, TimeUnit) */ public long getKeepAliveTime(TimeUnit unit) { @@ -1834,10 +1556,9 @@ /* User-level queue utilities */ /** - * Returns the task queue used by this executor. Access to the - * task queue is intended primarily for debugging and monitoring. - * This queue may be in active use. Retrieving the task queue - * does not prevent queued tasks from executing. + * Returns the task queue used by this executor. Access to the task queue is intended primarily for debugging and + * monitoring. This queue may be in active use. Retrieving the task queue does not prevent queued tasks from + * executing. * * @return the task queue */ @@ -1846,19 +1567,16 @@ } /** - * Removes this task from the executor's internal queue if it is - * present, thus causing it not to be run if it has not already - * started. - * - *

      This method may be useful as one part of a cancellation - * scheme. It may fail to remove tasks that have been converted - * into other forms before being placed on the internal queue. - * For example, a task entered using {@code submit} might be - * converted into a form that maintains {@code Future} status. - * However, in such cases, method {@link #purge} may be used to - * remove those Futures that have been cancelled. + * Removes this task from the executor's internal queue if it is present, thus causing it not to be run if it has + * not already started. + *

      + * This method may be useful as one part of a cancellation scheme. It may fail to remove tasks that have been + * converted into other forms before being placed on the internal queue. For example, a task entered using + * {@code submit} might be converted into a form that maintains {@code Future} status. However, in such cases, + * method {@link #purge} may be used to remove those Futures that have been cancelled. * * @param task the task to remove + * * @return {@code true} if the task was removed */ public boolean remove(Runnable task) { @@ -1868,14 +1586,11 @@ } /** - * Tries to remove from the work queue all {@link Future} - * tasks that have been cancelled. This method can be useful as a - * storage reclamation operation, that has no other impact on - * functionality. Cancelled tasks are never executed, but may - * accumulate in work queues until worker threads can actively - * remove them. Invoking this method instead tries to remove them now. - * However, this method may fail to remove tasks in - * the presence of interference by other threads. + * Tries to remove from the work queue all {@link Future} tasks that have been cancelled. This method can be useful + * as a storage reclamation operation, that has no other impact on functionality. Cancelled tasks are never + * executed, but may accumulate in work queues until worker threads can actively remove them. Invoking this method + * instead tries to remove them now. However, this method may fail to remove tasks in the presence of interference + * by other threads. */ public void purge() { final BlockingQueue q = workQueue; @@ -1886,7 +1601,7 @@ // Make copy for traversal and call remove for cancelled entries. // The slow path is more likely to be O(N*N). for (Object r : q.toArray()) { - if (r instanceof Future && ((Future)r).isCancelled()) { + if (r instanceof Future && ((Future) r).isCancelled()) { q.remove(r); } } @@ -1926,28 +1641,25 @@ try { // Remove rare and surprising possibility of // isTerminated() && getPoolSize() > 0 - return runStateAtLeast(ctl.get(), TIDYING) ? 0 - : workers.size(); + return runStateAtLeast(ctl.get(), TIDYING) ? 0 : workers.size(); } finally { mainLock.unlock(); } } /** - * Returns the current number of threads in the pool. - *
      NOTE: this method only used in {@link TaskQueue#offer(Runnable)}, - * where operations are frequent, can greatly reduce unnecessary - * performance overhead by a lock-free way. + * Returns the current number of threads in the pool.
      + * NOTE: this method only used in {@link TaskQueue#offer(Runnable)}, where operations are frequent, can + * greatly reduce unnecessary performance overhead by a lock-free way. + * * @return the number of threads */ protected int getPoolSizeNoLock() { - return runStateAtLeast(ctl.get(), TIDYING) ? 0 - : workers.size(); + return runStateAtLeast(ctl.get(), TIDYING) ? 0 : workers.size(); } /** - * Returns the approximate number of threads that are actively - * executing tasks. + * Returns the approximate number of threads that are actively executing tasks. * * @return the number of threads */ @@ -1968,8 +1680,7 @@ } /** - * Returns the largest number of threads that have ever - * simultaneously been in the pool. + * Returns the largest number of threads that have ever simultaneously been in the pool. * * @return the number of threads */ @@ -1984,10 +1695,8 @@ } /** - * Returns the approximate total number of tasks that have ever been - * scheduled for execution. Because the states of tasks and - * threads may change dynamically during computation, the returned - * value is only an approximation. + * Returns the approximate total number of tasks that have ever been scheduled for execution. Because the states of + * tasks and threads may change dynamically during computation, the returned value is only an approximation. * * @return the number of tasks */ @@ -2009,11 +1718,9 @@ } /** - * Returns the approximate total number of tasks that have - * completed execution. Because the states of tasks and threads - * may change dynamically during computation, the returned value - * is only an approximation, but one that does not ever decrease - * across successive calls. + * Returns the approximate total number of tasks that have completed execution. Because the states of tasks and + * threads may change dynamically during computation, the returned value is only an approximation, but one that does + * not ever decrease across successive calls. * * @return the number of tasks */ @@ -2038,9 +1745,8 @@ /** - * Returns a string identifying this pool, as well as its state, - * including indications of run state and estimated worker and - * task counts. + * Returns a string identifying this pool, as well as its state, including indications of run state and estimated + * worker and task counts. * * @return a string identifying this pool, as well as its state */ @@ -2064,87 +1770,66 @@ mainLock.unlock(); } int c = ctl.get(); - String runState = - isRunning(c) ? "Running" : - runStateAtLeast(c, TERMINATED) ? "Terminated" : - "Shutting down"; - return super.toString() + - "[" + runState + - ", pool size = " + nworkers + - ", active threads = " + nactive + - ", queued tasks = " + workQueue.size() + - ", completed tasks = " + ncompleted + - "]"; + String runState = isRunning(c) ? "Running" : runStateAtLeast(c, TERMINATED) ? "Terminated" : "Shutting down"; + return super.toString() + "[" + runState + ", pool size = " + nworkers + ", active threads = " + nactive + + ", queued tasks = " + workQueue.size() + ", completed tasks = " + ncompleted + "]"; } /* Extension hooks */ /** - * Method invoked prior to executing the given Runnable in the - * given thread. This method is invoked by thread {@code t} that - * will execute task {@code r}, and may be used to re-initialize - * ThreadLocals, or to perform logging. - * - *

      This implementation does nothing, but may be customized in - * subclasses. Note: To properly nest multiple overridings, subclasses - * should generally invoke {@code super.beforeExecute} at the end of - * this method. + * Method invoked prior to executing the given Runnable in the given thread. This method is invoked by thread + * {@code t} that will execute task {@code r}, and may be used to re-initialize ThreadLocals, or to perform logging. + *

      + * This implementation does nothing, but may be customized in subclasses. Note: To properly nest multiple + * overridings, subclasses should generally invoke {@code super.beforeExecute} at the end of this method. * * @param t the thread that will run task {@code r} * @param r the task that will be executed */ - protected void beforeExecute(Thread t, Runnable r) { } + protected void beforeExecute(Thread t, Runnable r) { + } /** - * Method invoked upon completion of execution of the given Runnable. - * This method is invoked by the thread that executed the task. If - * non-null, the Throwable is the uncaught {@code RuntimeException} - * or {@code Error} that caused execution to terminate abruptly. - * - *

      This implementation does nothing, but may be customized in - * subclasses. Note: To properly nest multiple overridings, subclasses - * should generally invoke {@code super.afterExecute} at the - * beginning of this method. - * - *

      Note: When actions are enclosed in tasks (such as - * {@link java.util.concurrent.FutureTask}) - * either explicitly or via methods such as - * {@code submit}, these task objects catch and maintain - * computational exceptions, and so they do not cause abrupt - * termination, and the internal exceptions are not - * passed to this method. If you would like to trap both kinds of - * failures in this method, you can further probe for such cases, - * as in this sample subclass that prints either the direct cause - * or the underlying exception if a task has been aborted: + * Method invoked upon completion of execution of the given Runnable. This method is invoked by the thread that + * executed the task. If non-null, the Throwable is the uncaught {@code RuntimeException} or {@code Error} that + * caused execution to terminate abruptly. + *

      + * This implementation does nothing, but may be customized in subclasses. Note: To properly nest multiple + * overridings, subclasses should generally invoke {@code super.afterExecute} at the beginning of this method. + *

      + * Note: When actions are enclosed in tasks (such as {@link java.util.concurrent.FutureTask}) either + * explicitly or via methods such as {@code submit}, these task objects catch and maintain computational exceptions, + * and so they do not cause abrupt termination, and the internal exceptions are not passed to this method. + * If you would like to trap both kinds of failures in this method, you can further probe for such cases, as in this + * sample subclass that prints either the direct cause or the underlying exception if a task has been aborted: * *

       {@code
            * class ExtendedExecutor extends ThreadPoolExecutor {
      -     *   // ...
      -     *   protected void afterExecute(Runnable r, Throwable t) {
      -     *     super.afterExecute(r, t);
      -     *     if (t == null
      -     *         && r instanceof Future
      -     *         && ((Future)r).isDone()) {
      -     *       try {
      -     *         Object result = ((Future) r).get();
      -     *       } catch (CancellationException ce) {
      -     *         t = ce;
      -     *       } catch (ExecutionException ee) {
      -     *         t = ee.getCause();
      -     *       } catch (InterruptedException ie) {
      -     *         // ignore/reset
      -     *         Thread.currentThread().interrupt();
      -     *       }
      +     *     // ...
      +     *     protected void afterExecute(Runnable r, Throwable t) {
      +     *         super.afterExecute(r, t);
      +     *         if (t == null && r instanceof Future && ((Future) r).isDone()) {
      +     *             try {
      +     *                 Object result = ((Future) r).get();
      +     *             } catch (CancellationException ce) {
      +     *                 t = ce;
      +     *             } catch (ExecutionException ee) {
      +     *                 t = ee.getCause();
      +     *             } catch (InterruptedException ie) {
      +     *                 // ignore/reset
      +     *                 Thread.currentThread().interrupt();
      +     *             }
      +     *         }
      +     *         if (t != null)
      +     *             System.out.println(t);
            *     }
      -     *     if (t != null)
      -     *       System.out.println(t);
      -     *   }
      -     * }}
      + * } + * } * * @param r the runnable that has completed - * @param t the exception that caused termination, or null if - * execution completed normally + * @param t the exception that caused termination, or null if execution completed normally */ protected void afterExecute(Runnable r, Throwable t) { // Throwing StopPooledThreadException is likely to cause this method to @@ -2162,20 +1847,18 @@ /** - * If the current thread was started before the last time when a context was - * stopped, an exception is thrown so that the current thread is stopped. + * If the current thread was started before the last time when a context was stopped, an exception is thrown so that + * the current thread is stopped. */ protected void stopCurrentThreadIfNeeded() { if (currentThreadShouldBeStopped()) { long lastTime = lastTimeThreadKilledItself.longValue(); if (lastTime + threadRenewalDelay < System.currentTimeMillis()) { - if (lastTimeThreadKilledItself.compareAndSet(lastTime, - System.currentTimeMillis() + 1)) { + if (lastTimeThreadKilledItself.compareAndSet(lastTime, System.currentTimeMillis() + 1)) { // OK, it's really time to dispose of this thread - final String msg = sm.getString( - "threadPoolExecutor.threadStoppedToAvoidPotentialLeak", - Thread.currentThread().getName()); + final String msg = sm.getString("threadPoolExecutor.threadStoppedToAvoidPotentialLeak", + Thread.currentThread().getName()); throw new StopPooledThreadException(msg); } @@ -2195,30 +1878,28 @@ /** - * Method invoked when the Executor has terminated. Default - * implementation does nothing. Note: To properly nest multiple - * overridings, subclasses should generally invoke - * {@code super.terminated} within this method. + * Method invoked when the Executor has terminated. Default implementation does nothing. Note: To properly nest + * multiple overridings, subclasses should generally invoke {@code super.terminated} within this method. */ - protected void terminated() { } + protected void terminated() { + } /* Predefined RejectedExecutionHandlers */ /** - * A handler for rejected tasks that runs the rejected task - * directly in the calling thread of the {@code execute} method, - * unless the executor has been shut down, in which case the task - * is discarded. + * A handler for rejected tasks that runs the rejected task directly in the calling thread of the {@code execute} + * method, unless the executor has been shut down, in which case the task is discarded. */ public static class CallerRunsPolicy implements RejectedExecutionHandler { /** * Creates a {@code CallerRunsPolicy}. */ - public CallerRunsPolicy() { } + public CallerRunsPolicy() { + } /** - * Executes task r in the caller's thread, unless the executor - * has been shut down, in which case the task is discarded. + * Executes task r in the caller's thread, unless the executor has been shut down, in which case the task is + * discarded. * * @param r the runnable task requested to be executed * @param e the executor attempting to execute this task @@ -2232,20 +1913,21 @@ } /** - * A handler for rejected tasks that throws a - * {@link RejectedExecutionException}. + * A handler for rejected tasks that throws a {@link RejectedExecutionException}. */ public static class AbortPolicy implements RejectedExecutionHandler { /** * Creates an {@code AbortPolicy}. */ - public AbortPolicy() { } + public AbortPolicy() { + } /** * Always throws RejectedExecutionException. * * @param r the runnable task requested to be executed * @param e the executor attempting to execute this task + * * @throws RejectedExecutionException always */ @Override @@ -2256,14 +1938,14 @@ } /** - * A handler for rejected tasks that silently discards the - * rejected task. + * A handler for rejected tasks that silently discards the rejected task. */ public static class DiscardPolicy implements RejectedExecutionHandler { /** * Creates a {@code DiscardPolicy}. */ - public DiscardPolicy() { } + public DiscardPolicy() { + } /** * Does nothing, which has the effect of discarding task r. @@ -2277,34 +1959,35 @@ } /** - * A handler for rejected tasks that discards the oldest unhandled - * request and then retries {@code execute}, unless the executor - * is shut down, in which case the task is discarded. This policy is - * rarely useful in cases where other threads may be waiting for - * tasks to terminate, or failures must be recorded. Instead, consider - * using a handler of the form: + * A handler for rejected tasks that discards the oldest unhandled request and then retries {@code execute}, unless + * the executor is shut down, in which case the task is discarded. This policy is rarely useful in cases where other + * threads may be waiting for tasks to terminate, or failures must be recorded. Instead, consider using a handler of + * the form: + * *
       {@code
            * new RejectedExecutionHandler() {
      -     *   public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
      -     *     Runnable dropped = e.getQueue().poll();
      -     *     if (dropped instanceof Future) {
      -     *       ((Future)dropped).cancel(false);
      -     *       // also consider logging the failure
      +     *     public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
      +     *         Runnable dropped = e.getQueue().poll();
      +     *         if (dropped instanceof Future) {
      +     *             ((Future) dropped).cancel(false);
      +     *             // also consider logging the failure
      +     *         }
      +     *         e.execute(r); // retry
            *     }
      -     *     e.execute(r);  // retry
      -     * }}}
      + * } + * } */ public static class DiscardOldestPolicy implements RejectedExecutionHandler { /** * Creates a {@code DiscardOldestPolicy} for the given executor. */ - public DiscardOldestPolicy() { } + public DiscardOldestPolicy() { + } /** - * Obtains and ignores the next task that the executor - * would otherwise execute, if one is immediately available, - * and then retries execution of task r, unless the executor - * is shut down, in which case task r is instead discarded. + * Obtains and ignores the next task that the executor would otherwise execute, if one is immediately available, + * and then retries execution of task r, unless the executor is shut down, in which case task r is instead + * discarded. * * @param r the runnable task requested to be executed * @param e the executor attempting to execute this task @@ -2329,18 +2012,16 @@ public interface RejectedExecutionHandler { /** - * Method that may be invoked by a {@link ThreadPoolExecutor} when - * {@link ThreadPoolExecutor#execute execute} cannot accept a - * task. This may occur when no more threads or queue slots are - * available because their bounds would be exceeded, or upon - * shutdown of the Executor. + * Method that may be invoked by a {@link ThreadPoolExecutor} when {@link ThreadPoolExecutor#execute execute} + * cannot accept a task. This may occur when no more threads or queue slots are available because their bounds + * would be exceeded, or upon shutdown of the Executor. + *

      + * In the absence of other alternatives, the method may throw an unchecked {@link RejectedExecutionException}, + * which will be propagated to the caller of {@code execute}. * - *

      In the absence of other alternatives, the method may throw - * an unchecked {@link RejectedExecutionException}, which will be - * propagated to the caller of {@code execute}. - * - * @param r the runnable task requested to be executed + * @param r the runnable task requested to be executed * @param executor the executor attempting to execute this task + * * @throws RejectedExecutionException if there is no remedy */ void rejectedExecution(Runnable r, ThreadPoolExecutor executor); diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/xreflection/ObjectReflectionPropertyInspector.java tomcat10-10.1.52/java/org/apache/tomcat/util/xreflection/ObjectReflectionPropertyInspector.java --- tomcat10-10.1.40/java/org/apache/tomcat/util/xreflection/ObjectReflectionPropertyInspector.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/xreflection/ObjectReflectionPropertyInspector.java 2026-01-23 19:33:36.000000000 +0000 @@ -36,90 +36,71 @@ public static void main(String... args) throws Exception { if (args.length == 0) { - System.err.println("Usage:\n\t"+ - "org.apache.tomcat.util.xreflection.ObjectReflectionPropertyInspector" + - " " - ); + System.err.println("Usage:\n\t" + "org.apache.tomcat.util.xreflection.ObjectReflectionPropertyInspector" + + " "); System.exit(1); } File outputDir = new File(args[0]); if (!outputDir.exists() || !outputDir.isDirectory()) { - System.err.println("Invalid output directory: "+ outputDir.getAbsolutePath()); + System.err.println("Invalid output directory: " + outputDir.getAbsolutePath()); System.exit(1); } - Set baseClasses = getKnownClasses() - .stream() - .map(ObjectReflectionPropertyInspector::processClass) - .collect(Collectors.toCollection(LinkedHashSet::new)); - generateCode( - baseClasses, - "org.apache.tomcat.util", - outputDir, - "XReflectionIntrospectionUtils" - ); + Set baseClasses = + getKnownClasses().stream().map(ObjectReflectionPropertyInspector::processClass) + .collect(Collectors.toCollection(LinkedHashSet::new)); + generateCode(baseClasses, "org.apache.tomcat.util", outputDir, "XReflectionIntrospectionUtils"); } private static Set> getKnownClasses() throws ClassNotFoundException { - return - Collections.unmodifiableSet(new LinkedHashSet<>( - Arrays.asList( - Class.forName("org.apache.catalina.authenticator.jaspic.SimpleAuthConfigProvider"), - Class.forName("org.apache.catalina.authenticator.jaspic.PersistentProviderRegistrations$Property"), - Class.forName("org.apache.catalina.authenticator.jaspic.PersistentProviderRegistrations$Provider"), - Class.forName("org.apache.catalina.connector.Connector"), - Class.forName("org.apache.catalina.core.ContainerBase"), - Class.forName("org.apache.catalina.core.StandardContext"), - Class.forName("org.apache.catalina.core.StandardEngine"), - Class.forName("org.apache.catalina.core.StandardHost"), - Class.forName("org.apache.catalina.core.StandardServer"), - Class.forName("org.apache.catalina.core.StandardService"), - Class.forName("org.apache.catalina.filters.AddDefaultCharsetFilter"), - Class.forName("org.apache.catalina.filters.RestCsrfPreventionFilter"), - Class.forName("org.apache.catalina.loader.ParallelWebappClassLoader"), - Class.forName("org.apache.catalina.loader.WebappClassLoaderBase"), - Class.forName("org.apache.catalina.realm.UserDatabaseRealm"), - Class.forName("org.apache.catalina.valves.AccessLogValve"), - Class.forName("org.apache.coyote.AbstractProtocol"), - Class.forName("org.apache.coyote.ajp.AbstractAjpProtocol"), - Class.forName("org.apache.coyote.ajp.AjpNio2Protocol"), - Class.forName("org.apache.coyote.ajp.AjpNioProtocol"), - Class.forName("org.apache.coyote.http11.AbstractHttp11JsseProtocol"), - Class.forName("org.apache.coyote.http11.AbstractHttp11Protocol"), - Class.forName("org.apache.coyote.http11.Http11Nio2Protocol"), - Class.forName("org.apache.coyote.http11.Http11NioProtocol"), - Class.forName("org.apache.tomcat.util.descriptor.web.ContextResource"), - Class.forName("org.apache.tomcat.util.descriptor.web.ResourceBase"), - Class.forName("org.apache.tomcat.util.modeler.AttributeInfo"), - Class.forName("org.apache.tomcat.util.modeler.FeatureInfo"), - Class.forName("org.apache.tomcat.util.modeler.ManagedBean"), - Class.forName("org.apache.tomcat.util.modeler.OperationInfo"), - Class.forName("org.apache.tomcat.util.modeler.ParameterInfo"), - Class.forName("org.apache.tomcat.util.net.AbstractEndpoint"), - Class.forName("org.apache.tomcat.util.net.Nio2Endpoint"), - Class.forName("org.apache.tomcat.util.net.NioEndpoint"), - Class.forName("org.apache.tomcat.util.net.SocketProperties") - ) - ) - ); - } - - //types of properties that IntrospectionUtils.setProperty supports - private static final Set> ALLOWED_TYPES = Collections.unmodifiableSet(new LinkedHashSet<>( - Arrays.asList( - Boolean.TYPE, - Integer.TYPE, - Long.TYPE, - String.class, - InetAddress.class - ) - )); - private static final Map, SetPropertyClass> classes = new LinkedHashMap<>(); - - public static void generateCode(Set baseClasses, String packageName, File location, String className) throws Exception { - String packageDirectory = packageName.replace('.','/'); + return Collections.unmodifiableSet(new LinkedHashSet<>(Arrays.asList( + Class.forName("org.apache.catalina.authenticator.jaspic.SimpleAuthConfigProvider"), + Class.forName("org.apache.catalina.authenticator.jaspic.PersistentProviderRegistrations$Property"), + Class.forName("org.apache.catalina.authenticator.jaspic.PersistentProviderRegistrations$Provider"), + Class.forName("org.apache.catalina.connector.Connector"), + Class.forName("org.apache.catalina.core.ContainerBase"), + Class.forName("org.apache.catalina.core.StandardContext"), + Class.forName("org.apache.catalina.core.StandardEngine"), + Class.forName("org.apache.catalina.core.StandardHost"), + Class.forName("org.apache.catalina.core.StandardServer"), + Class.forName("org.apache.catalina.core.StandardService"), + Class.forName("org.apache.catalina.filters.AddDefaultCharsetFilter"), + Class.forName("org.apache.catalina.filters.RestCsrfPreventionFilter"), + Class.forName("org.apache.catalina.loader.ParallelWebappClassLoader"), + Class.forName("org.apache.catalina.loader.WebappClassLoaderBase"), + Class.forName("org.apache.catalina.realm.UserDatabaseRealm"), + Class.forName("org.apache.catalina.valves.AccessLogValve"), + Class.forName("org.apache.coyote.AbstractProtocol"), + Class.forName("org.apache.coyote.ajp.AbstractAjpProtocol"), + Class.forName("org.apache.coyote.ajp.AjpNio2Protocol"), + Class.forName("org.apache.coyote.ajp.AjpNioProtocol"), + Class.forName("org.apache.coyote.http11.AbstractHttp11JsseProtocol"), + Class.forName("org.apache.coyote.http11.AbstractHttp11Protocol"), + Class.forName("org.apache.coyote.http11.Http11Nio2Protocol"), + Class.forName("org.apache.coyote.http11.Http11NioProtocol"), + Class.forName("org.apache.tomcat.util.descriptor.web.ContextResource"), + Class.forName("org.apache.tomcat.util.descriptor.web.ResourceBase"), + Class.forName("org.apache.tomcat.util.modeler.AttributeInfo"), + Class.forName("org.apache.tomcat.util.modeler.FeatureInfo"), + Class.forName("org.apache.tomcat.util.modeler.ManagedBean"), + Class.forName("org.apache.tomcat.util.modeler.OperationInfo"), + Class.forName("org.apache.tomcat.util.modeler.ParameterInfo"), + Class.forName("org.apache.tomcat.util.net.AbstractEndpoint"), + Class.forName("org.apache.tomcat.util.net.Nio2Endpoint"), + Class.forName("org.apache.tomcat.util.net.NioEndpoint"), + Class.forName("org.apache.tomcat.util.net.SocketProperties")))); + } + + // types of properties that IntrospectionUtils.setProperty supports + private static final Set> ALLOWED_TYPES = Collections.unmodifiableSet( + new LinkedHashSet<>(Arrays.asList(Boolean.TYPE, Integer.TYPE, Long.TYPE, String.class, InetAddress.class))); + private static final Map,SetPropertyClass> classes = new LinkedHashMap<>(); + + public static void generateCode(Set baseClasses, String packageName, File location, + String className) throws Exception { + String packageDirectory = packageName.replace('.', '/'); File sourceFileLocation = new File(location, packageDirectory); ReflectionLessCodeGenerator.generateCode(sourceFileLocation, className, packageName, baseClasses); } @@ -130,17 +111,14 @@ } private static boolean isAllowedSetMethod(Method method) { - return method.getName().startsWith("set") && - method.getParameterTypes().length == 1 && - ALLOWED_TYPES.contains(method.getParameterTypes()[0]) && - !Modifier.isPrivate(method.getModifiers()); + return method.getName().startsWith("set") && method.getParameterTypes().length == 1 && + ALLOWED_TYPES.contains(method.getParameterTypes()[0]) && !Modifier.isPrivate(method.getModifiers()); } private static boolean isAllowedGetMethod(Method method) { return (method.getName().startsWith("get") || method.getName().startsWith("is")) && - method.getParameterTypes().length == 0 && - ALLOWED_TYPES.contains(method.getReturnType()) && - !Modifier.isPrivate(method.getModifiers()); + method.getParameterTypes().length == 0 && ALLOWED_TYPES.contains(method.getReturnType()) && + !Modifier.isPrivate(method.getModifiers()); } @@ -155,7 +133,8 @@ } static Method findGetter(Class declaringClass, String propertyName) { - for (String getterName : Arrays.asList("get" + IntrospectionUtils.capitalize(propertyName), "is" + propertyName)) { + for (String getterName : Arrays.asList("get" + IntrospectionUtils.capitalize(propertyName), + "is" + propertyName)) { try { Method method = declaringClass.getMethod(getterName); if (!Modifier.isPrivate(method.getModifiers())) { @@ -201,8 +180,7 @@ if (name == null || name.isEmpty()) { return name; } - if (name.length() > 1 && Character.isUpperCase(name.charAt(1)) && - Character.isUpperCase(name.charAt(0))) { + if (name.length() > 1 && Character.isUpperCase(name.charAt(1)) && Character.isUpperCase(name.charAt(0))) { return name; } char[] chars = name.toCharArray(); @@ -220,13 +198,8 @@ Class propertyType = method.getParameterTypes()[0]; Method getter = findGetter(clazz, propertyName); Method setter = findSetter(clazz, propertyName, propertyType); - ReflectionProperty property = new ReflectionProperty( - spc.getClazz().getName(), - propertyName, - propertyType, - setter, - getter - ); + ReflectionProperty property = + new ReflectionProperty(spc.getClazz().getName(), propertyName, propertyType, setter, getter); spc.addProperty(property); } else if (isAllowedGetMethod(method)) { boolean startsWithIs = method.getName().startsWith("is"); @@ -234,13 +207,8 @@ Class propertyType = method.getReturnType(); Method getter = findGetter(clazz, propertyName); Method setter = findSetter(clazz, propertyName, propertyType); - ReflectionProperty property = new ReflectionProperty( - spc.getClazz().getName(), - propertyName, - propertyType, - setter, - getter - ); + ReflectionProperty property = + new ReflectionProperty(spc.getClazz().getName(), propertyName, propertyType, setter, getter); spc.addProperty(property); } } @@ -248,22 +216,11 @@ final Field[] fields = clazz.getDeclaredFields(); for (Field field : fields) { if (isAllowedField(field)) { - Method getter = findGetter( - field.getDeclaringClass(), - IntrospectionUtils.capitalize(field.getName()) - ); - Method setter = findSetter( - field.getDeclaringClass(), - IntrospectionUtils.capitalize(field.getName()), - field.getType() - ); - ReflectionProperty property = new ReflectionProperty( - spc.getClazz().getName(), - field.getName(), - field.getType(), - setter, - getter - ); + Method getter = findGetter(field.getDeclaringClass(), IntrospectionUtils.capitalize(field.getName())); + Method setter = findSetter(field.getDeclaringClass(), IntrospectionUtils.capitalize(field.getName()), + field.getType()); + ReflectionProperty property = new ReflectionProperty(spc.getClazz().getName(), field.getName(), + field.getType(), setter, getter); spc.addProperty(property); } } diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/xreflection/ReflectionLessCodeGenerator.java tomcat10-10.1.52/java/org/apache/tomcat/util/xreflection/ReflectionLessCodeGenerator.java --- tomcat10-10.1.40/java/org/apache/tomcat/util/xreflection/ReflectionLessCodeGenerator.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/xreflection/ReflectionLessCodeGenerator.java 2026-01-23 19:33:36.000000000 +0000 @@ -33,13 +33,10 @@ return indent; } - static void generateCode( - File directory, - String className, - String packageName, - Set baseClasses - ) throws IOException { - //begin - class + static void generateCode(File directory, String className, String packageName, Set baseClasses) + throws IOException { + //@formatter:off + // begin - class StringBuilder code = new StringBuilder(AL20_HEADER) .append("package ") .append(packageName) @@ -52,7 +49,7 @@ .append(System.lineSeparator()) .append(System.lineSeparator()); - //begin - isEnabled method + // begin - isEnabled method code.append(getIndent(1)) .append("static boolean isEnabled() {") .append(System.lineSeparator()) @@ -64,9 +61,9 @@ .append(System.lineSeparator()) .append(System.lineSeparator()) ; - //end - isEnabled method + // end - isEnabled method - //begin - getInetAddress method + // begin - getInetAddress method code.append(getIndent(1)) .append("private static java.net.InetAddress getInetAddress(String value) {") .append(System.lineSeparator()) @@ -84,9 +81,9 @@ .append(System.lineSeparator()) .append(System.lineSeparator()) ; - //end - getInetAddress method + // end - getInetAddress method - //begin - getPropertyInternal method + // begin - getPropertyInternal method code.append(getIndent(1)) .append("static Object getPropertyInternal(Object ") .append(SetPropertyClass.OBJECT_VAR_NAME) @@ -107,7 +104,7 @@ .append("switch (checkThisClass.getName()) {") .append(System.lineSeparator()); - //generate case statements for getPropertyInternal + // generate case statements for getPropertyInternal generateCaseStatementsForGetPropertyInternal(baseClasses, code); @@ -127,13 +124,13 @@ .append(getIndent(1)) .append('}') .append(System.lineSeparator()); - //end - getPropertyInternal method + // end - getPropertyInternal method - //begin - getPropertyForXXX methods + // begin - getPropertyForXXX methods generateGetPropertyForMethods(baseClasses, code); - //end - getPropertyForXXX methods + // end - getPropertyForXXX methods - //begin - setPropertyInternal method + // begin - setPropertyInternal method code.append(getIndent(1)) .append("static boolean setPropertyInternal(Object ") .append(SetPropertyClass.OBJECT_VAR_NAME) @@ -155,7 +152,7 @@ .append("switch (checkThisClass.getName()) {") .append(System.lineSeparator()); - //generate case statements for setPropertyInternal + // generate case statements for setPropertyInternal generateCaseStatementsForSetPropertyInternal(baseClasses, code); @@ -175,16 +172,17 @@ .append(getIndent(1)) .append('}') .append(System.lineSeparator()); - //end - setPropertyInternal method + // end - setPropertyInternal method - //begin - setPropertyForXXX methods + // begin - setPropertyForXXX methods generateSetPropertyForMethods(baseClasses, code); - //end - setPropertyForXXX methods + // end - setPropertyForXXX methods code.append('}') .append(System.lineSeparator()); - //end - class - File destination = new File(directory, className+".java"); + // end - class + //@formatter:on + File destination = new File(directory, className + ".java"); try (BufferedWriter writer = new BufferedWriter(new FileWriter(destination, false))) { writer.write(code.toString()); writer.flush(); @@ -201,7 +199,8 @@ } } - private static void generateCaseStatementsForSetPropertyInternal(Set baseClasses, StringBuilder code) { + private static void generateCaseStatementsForSetPropertyInternal(Set baseClasses, + StringBuilder code) { for (SetPropertyClass clazz : baseClasses) { generateCaseStatementForSetPropertyInternal(clazz, code); } @@ -211,9 +210,7 @@ for (SetPropertyClass child : clazz.getChildren()) { generateSetPropertyForMethod(child, code); } - code.append(clazz.generateSetPropertyForMethod()) - .append(System.lineSeparator()) - .append(System.lineSeparator()); + code.append(clazz.generateSetPropertyForMethod()).append(System.lineSeparator()).append(System.lineSeparator()); } private static void generateSetPropertyForMethods(Set baseClasses, StringBuilder code) { @@ -223,7 +220,6 @@ } - private static void generateCaseStatementForGetPropertyInternal(SetPropertyClass clazz, StringBuilder code) { for (SetPropertyClass child : clazz.getChildren()) { generateCaseStatementForGetPropertyInternal(child, code); @@ -233,7 +229,8 @@ } } - private static void generateCaseStatementsForGetPropertyInternal(Set baseClasses, StringBuilder code) { + private static void generateCaseStatementsForGetPropertyInternal(Set baseClasses, + StringBuilder code) { for (SetPropertyClass clazz : baseClasses) { generateCaseStatementForGetPropertyInternal(clazz, code); } @@ -243,9 +240,7 @@ for (SetPropertyClass child : clazz.getChildren()) { generateGetPropertyForMethod(child, code); } - code.append(clazz.generateGetPropertyForMethod()) - .append(System.lineSeparator()) - .append(System.lineSeparator()); + code.append(clazz.generateGetPropertyForMethod()).append(System.lineSeparator()).append(System.lineSeparator()); } private static void generateGetPropertyForMethods(Set baseClasses, StringBuilder code) { @@ -254,20 +249,17 @@ } } - private static final String AL20_HEADER = "/*\n" + - " * Licensed to the Apache Software Foundation (ASF) under one or more\n" + - " * contributor license agreements. See the NOTICE file distributed with\n" + - " * this work for additional information regarding copyright ownership.\n" + - " * The ASF licenses this file to You under the Apache License, Version 2.0\n" + - " * (the \"License\"); you may not use this file except in compliance with\n" + - " * the License. You may obtain a copy of the License at\n" + - " *\n" + - " * http://www.apache.org/licenses/LICENSE-2.0\n" + - " *\n" + - " * Unless required by applicable law or agreed to in writing, software\n" + - " * distributed under the License is distributed on an \"AS IS\" BASIS,\n" + - " * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n" + - " * See the License for the specific language governing permissions and\n" + - " * limitations under the License.\n" + - " */\n"; + private static final String AL20_HEADER = + "/*\n" + " * Licensed to the Apache Software Foundation (ASF) under one or more\n" + + " * contributor license agreements. See the NOTICE file distributed with\n" + + " * this work for additional information regarding copyright ownership.\n" + + " * The ASF licenses this file to You under the Apache License, Version 2.0\n" + + " * (the \"License\"); you may not use this file except in compliance with\n" + + " * the License. You may obtain a copy of the License at\n" + " *\n" + + " * http://www.apache.org/licenses/LICENSE-2.0\n" + " *\n" + + " * Unless required by applicable law or agreed to in writing, software\n" + + " * distributed under the License is distributed on an \"AS IS\" BASIS,\n" + + " * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n" + + " * See the License for the specific language governing permissions and\n" + + " * limitations under the License.\n" + " */\n"; } diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/xreflection/ReflectionProperty.java tomcat10-10.1.52/java/org/apache/tomcat/util/xreflection/ReflectionProperty.java --- tomcat10-10.1.40/java/org/apache/tomcat/util/xreflection/ReflectionProperty.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/xreflection/ReflectionProperty.java 2026-01-23 19:33:36.000000000 +0000 @@ -116,9 +116,7 @@ @Override public String toString() { - return "ReflectionProperty{" + "name='" + propertyName + '\'' + - ", type=" + propertyType + - '}'; + return "ReflectionProperty{" + "name='" + propertyName + '\'' + ", type=" + propertyType + '}'; } @Override diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/util/xreflection/SetPropertyClass.java tomcat10-10.1.52/java/org/apache/tomcat/util/xreflection/SetPropertyClass.java --- tomcat10-10.1.40/java/org/apache/tomcat/util/xreflection/SetPropertyClass.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/util/xreflection/SetPropertyClass.java 2026-01-23 19:33:36.000000000 +0000 @@ -118,8 +118,7 @@ @Override public String toString() { - return "SetPropertyClass{" + "clazz=" + clazz.getName() + - '}'; + return "SetPropertyClass{" + "clazz=" + clazz.getName() + '}'; } public void addProperty(ReflectionProperty property) { @@ -127,38 +126,38 @@ } - public String generateSetPropertyMethod(ReflectionProperty property) { - //this property has a setProperty method + // this property has a setProperty method if (property.hasSetPropertySetter()) { - return "((" + this.getClazz().getName().replace('$','.') + ")" + OBJECT_VAR_NAME + ")." + - property.getSetMethod().getName() + "(" + NAME_VAR_NAME + ", " + VALUE_VAR_NAME + ");"; + return "((" + this.getClazz().getName().replace('$', '.') + ")" + OBJECT_VAR_NAME + ")." + + property.getSetMethod().getName() + "(" + NAME_VAR_NAME + ", " + VALUE_VAR_NAME + ");"; } - //direct setter + // direct setter if (property.hasSetter()) { - return "((" + this.getClazz().getName().replace('$','.') + ")" + OBJECT_VAR_NAME + ")." + - property.getSetMethod().getName() + "(" + property.getConversion(VALUE_VAR_NAME) + ");"; + return "((" + this.getClazz().getName().replace('$', '.') + ")" + OBJECT_VAR_NAME + ")." + + property.getSetMethod().getName() + "(" + property.getConversion(VALUE_VAR_NAME) + ");"; } return null; } public String generateGetPropertyMethod(ReflectionProperty property) { - //this property has a getProperty method + // this property has a getProperty method if (property.hasGetPropertyGetter()) { - return "result = ((" + this.getClazz().getName().replace('$','.') + ")" + OBJECT_VAR_NAME + ")." + - property.getGetMethod().getName() + "(" + NAME_VAR_NAME + ");"; + return "result = ((" + this.getClazz().getName().replace('$', '.') + ")" + OBJECT_VAR_NAME + ")." + + property.getGetMethod().getName() + "(" + NAME_VAR_NAME + ");"; } - //direct getter + // direct getter if (property.hasGetter()) { - return "result = ((" + this.getClazz().getName().replace('$','.') + ")" + OBJECT_VAR_NAME + ")." + - property.getGetMethod().getName() + "();"; + return "result = ((" + this.getClazz().getName().replace('$', '.') + ")" + OBJECT_VAR_NAME + ")." + + property.getGetMethod().getName() + "();"; } return null; } public String generateSetPropertyForMethod() { + //@formatter:off StringBuilder code = new StringBuilder(ReflectionLessCodeGenerator.getIndent(1)) .append(generatesSetPropertyForMethodHeader()) .append(System.lineSeparator()) @@ -168,7 +167,7 @@ .append(") {") .append(System.lineSeparator()); - //case statements for each property + // case statements for each property for (ReflectionProperty property : getProperties()) { String invocation = generateSetPropertyMethod(property); if (invocation != null) { @@ -183,25 +182,22 @@ .append(System.lineSeparator()) .append(ReflectionLessCodeGenerator.getIndent(4)) .append("return true;") - .append(System.lineSeparator()) - ; + .append(System.lineSeparator()); } else { code.append(ReflectionLessCodeGenerator.getIndent(3)).append("//no set") - .append(IntrospectionUtils.capitalize(property.getPropertyName())).append(" method found on this class") - .append(System.lineSeparator()) - ; + .append(IntrospectionUtils.capitalize( + property.getPropertyName())).append(" method found on this class") + .append(System.lineSeparator()); } } - - - //end switch statement + // end switch statement code.append(ReflectionLessCodeGenerator.getIndent(2)) .append('}') .append(System.lineSeparator()); - //we have a generic setProperty(String, String) method, invoke it + // we have a generic setProperty(String, String) method, invoke it if (getGenericSetPropertyMethod() != null) { ReflectionProperty p = new ReflectionProperty( clazz.getName(), @@ -226,7 +222,7 @@ .append(System.lineSeparator()); } - //invoke parent or return false + // invoke parent or return false code.append(ReflectionLessCodeGenerator.getIndent(2)) .append("return ") .append(getSetPropertyForExitStatement()) @@ -235,18 +231,20 @@ .append('}'); return code.toString(); + //@formatter:on } private String getSetPropertyForExitStatement() { return (getParent() != null) ? - //invoke the parent if we have one - getParent().generateParentSetPropertyForMethodInvocation() : - //if we invoke setProperty, return true, return false otherwise - getGenericSetPropertyMethod() != null ? "true;" : "false;"; + // invoke the parent if we have one + getParent().generateParentSetPropertyForMethodInvocation() : + // if we invoke setProperty, return true, return false otherwise + getGenericSetPropertyMethod() != null ? "true;" : "false;"; } public String generateInvocationSetForPropertyCaseStatement(int level) { + //@formatter:off StringBuilder code = new StringBuilder(ReflectionLessCodeGenerator.getIndent(level)) .append("case \"") .append(getClazz().getName()) @@ -257,6 +255,7 @@ .append(generateParentSetPropertyForMethodInvocation()) .append(System.lineSeparator()); return code.toString(); + //@formatter:on } public String generateParentSetPropertyForMethodInvocation() { @@ -265,8 +264,9 @@ for (String s : classParts) { methodInvocation.append(IntrospectionUtils.capitalize(s)); } + //@formatter:off methodInvocation.append('(') - .append(OBJECT_VAR_NAME) + .append(OBJECT_VAR_NAME) .append(", ") .append(NAME_VAR_NAME) .append(", ") @@ -275,6 +275,7 @@ .append(SETP_VAR_NAME) .append(");"); return methodInvocation.toString(); + //@formatter:on } public String generatesSetPropertyForMethodHeader() { @@ -283,6 +284,7 @@ for (String s : classParts) { methodInvocation.append(IntrospectionUtils.capitalize(s)); } + //@formatter:off methodInvocation.append("(Object ") .append(OBJECT_VAR_NAME) .append(", String ") @@ -293,9 +295,11 @@ .append(SETP_VAR_NAME) .append(") {"); return methodInvocation.toString(); + //@formatter:on } public String generateInvocationGetForPropertyCaseStatement(int level) { + //@formatter:off StringBuilder code = new StringBuilder(ReflectionLessCodeGenerator.getIndent(level)) .append("case \"") .append(getClazz().getName()) @@ -307,9 +311,9 @@ .append(System.lineSeparator()) .append(ReflectionLessCodeGenerator.getIndent(level+1)) .append("break;") - .append(System.lineSeparator()) - ; + .append(System.lineSeparator()); return code.toString(); + //@formatter:on } public String generateParentGetPropertyForMethodInvocation() { @@ -318,12 +322,14 @@ for (String s : classParts) { methodInvocation.append(IntrospectionUtils.capitalize(s)); } + //@formatter:off methodInvocation.append('(') .append(OBJECT_VAR_NAME) .append(", ") .append(NAME_VAR_NAME) .append(");"); return methodInvocation.toString(); + //@formatter:on } public String generatesGetPropertyForMethodHeader() { @@ -332,12 +338,14 @@ for (String s : classParts) { methodInvocation.append(IntrospectionUtils.capitalize(s)); } + //@formatter:off methodInvocation.append("(Object ") .append(OBJECT_VAR_NAME) .append(", String ") .append(NAME_VAR_NAME) .append(") {"); return methodInvocation.toString(); + //@formatter:on } private String getGetPropertyForExitStatement() { @@ -349,6 +357,7 @@ public String generateGetPropertyForMethod() { + //@formatter:off StringBuilder code = new StringBuilder(ReflectionLessCodeGenerator.getIndent(1)) .append(generatesGetPropertyForMethodHeader()) .append(System.lineSeparator()) @@ -361,7 +370,7 @@ .append(") {") .append(System.lineSeparator()); - //case statements for each property + // case statements for each property for (ReflectionProperty property : getProperties()) { String invocation = generateGetPropertyMethod(property); if (invocation != null) { @@ -376,23 +385,20 @@ .append(System.lineSeparator()) .append(ReflectionLessCodeGenerator.getIndent(4)) .append("break;") - .append(System.lineSeparator()) - ; - + .append(System.lineSeparator()); } else { code.append(ReflectionLessCodeGenerator.getIndent(3)).append("//no get") .append(IntrospectionUtils.capitalize(property.getPropertyName())).append(" method found on this class") - .append(System.lineSeparator()) - ; + .append(System.lineSeparator()); } } - //end switch statement + // end switch statement code.append(ReflectionLessCodeGenerator.getIndent(2)) .append('}') .append(System.lineSeparator()); - //invoke parent or return null + // invoke parent or return null code.append(ReflectionLessCodeGenerator.getIndent(2)) .append("if (result == null) {") .append(System.lineSeparator()) @@ -402,10 +408,9 @@ .append(System.lineSeparator()) .append(ReflectionLessCodeGenerator.getIndent(2)) .append('}') - .append(System.lineSeparator()) - ; + .append(System.lineSeparator()); - //we have a generic getProperty(String, String) method, invoke it + // we have a generic getProperty(String, String) method, invoke it if (getGenericGetPropertyMethod() != null) { ReflectionProperty p = new ReflectionProperty( clazz.getName(), @@ -431,9 +436,8 @@ .append('}') .append(System.lineSeparator()); - - return code.toString(); + //@formatter:on } @Override diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/websocket/AsyncChannelGroupUtil.java tomcat10-10.1.52/java/org/apache/tomcat/websocket/AsyncChannelGroupUtil.java --- tomcat10-10.1.40/java/org/apache/tomcat/websocket/AsyncChannelGroupUtil.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/websocket/AsyncChannelGroupUtil.java 2026-01-23 19:33:36.000000000 +0000 @@ -81,12 +81,12 @@ // These are the same settings as the default // AsynchronousChannelGroup int initialSize = Runtime.getRuntime().availableProcessors(); - ExecutorService executorService = new ThreadPoolExecutor(0, Integer.MAX_VALUE, 60, - TimeUnit.SECONDS, new SynchronousQueue<>(), new AsyncIOThreadFactory()); + ExecutorService executorService = new ThreadPoolExecutor(0, Integer.MAX_VALUE, 60, TimeUnit.SECONDS, + new SynchronousQueue<>(), new AsyncIOThreadFactory()); try { return AsynchronousChannelGroup.withCachedThreadPool(executorService, initialSize); - } catch (IOException e) { + } catch (IOException ioe) { // No good reason for this to happen. throw new IllegalStateException(sm.getString("asyncChannelGroup.createFail")); } diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/websocket/AsyncChannelWrapper.java tomcat10-10.1.52/java/org/apache/tomcat/websocket/AsyncChannelWrapper.java --- tomcat10-10.1.40/java/org/apache/tomcat/websocket/AsyncChannelWrapper.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/websocket/AsyncChannelWrapper.java 2026-01-23 19:33:36.000000000 +0000 @@ -33,12 +33,12 @@ Future read(ByteBuffer dst); - void read(ByteBuffer dst, A attachment, CompletionHandler handler); + void read(ByteBuffer dst, A attachment, CompletionHandler handler); Future write(ByteBuffer src); void write(ByteBuffer[] srcs, int offset, int length, long timeout, TimeUnit unit, A attachment, - CompletionHandler handler); + CompletionHandler handler); void close(); diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/websocket/AsyncChannelWrapperNonSecure.java tomcat10-10.1.52/java/org/apache/tomcat/websocket/AsyncChannelWrapperNonSecure.java --- tomcat10-10.1.40/java/org/apache/tomcat/websocket/AsyncChannelWrapperNonSecure.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/websocket/AsyncChannelWrapperNonSecure.java 2026-01-23 19:33:36.000000000 +0000 @@ -46,7 +46,7 @@ } @Override - public void read(ByteBuffer dst, A attachment, CompletionHandler handler) { + public void read(ByteBuffer dst, A attachment, CompletionHandler handler) { socketChannel.read(dst, attachment, handler); } @@ -57,7 +57,7 @@ @Override public void write(ByteBuffer[] srcs, int offset, int length, long timeout, TimeUnit unit, - A attachment, CompletionHandler handler) { + A attachment, CompletionHandler handler) { socketChannel.write(srcs, offset, length, timeout, unit, attachment, handler); } @@ -65,7 +65,7 @@ public void close() { try { socketChannel.close(); - } catch (IOException e) { + } catch (IOException ignore) { // Ignore } } diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/websocket/AsyncChannelWrapperSecure.java tomcat10-10.1.52/java/org/apache/tomcat/websocket/AsyncChannelWrapperSecure.java --- tomcat10-10.1.40/java/org/apache/tomcat/websocket/AsyncChannelWrapperSecure.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/websocket/AsyncChannelWrapperSecure.java 2026-01-23 19:33:36.000000000 +0000 @@ -73,7 +73,7 @@ @Override public Future read(ByteBuffer dst) { - WrapperFuture future = new WrapperFuture<>(); + WrapperFuture future = new WrapperFuture<>(); if (!reading.compareAndSet(false, true)) { throw new IllegalStateException(sm.getString("asyncChannelWrapperSecure.concurrentRead")); @@ -87,9 +87,9 @@ } @Override - public void read(ByteBuffer dst, A attachment, CompletionHandler handler) { + public void read(ByteBuffer dst, A attachment, CompletionHandler handler) { - WrapperFuture future = new WrapperFuture<>(handler, attachment); + WrapperFuture future = new WrapperFuture<>(handler, attachment); if (!reading.compareAndSet(false, true)) { throw new IllegalStateException(sm.getString("asyncChannelWrapperSecure.concurrentRead")); @@ -103,7 +103,7 @@ @Override public Future write(ByteBuffer src) { - WrapperFuture inner = new WrapperFuture<>(); + WrapperFuture inner = new WrapperFuture<>(); if (!writing.compareAndSet(false, true)) { throw new IllegalStateException(sm.getString("asyncChannelWrapperSecure.concurrentWrite")); @@ -118,9 +118,9 @@ @Override public void write(ByteBuffer[] srcs, int offset, int length, long timeout, TimeUnit unit, - A attachment, CompletionHandler handler) { + A attachment, CompletionHandler handler) { - WrapperFuture future = new WrapperFuture<>(handler, attachment); + WrapperFuture future = new WrapperFuture<>(handler, attachment); if (!writing.compareAndSet(false, true)) { throw new IllegalStateException(sm.getString("asyncChannelWrapperSecure.concurrentWrite")); @@ -135,8 +135,12 @@ public void close() { try { socketChannel.close(); - } catch (IOException e) { - log.info(sm.getString("asyncChannelWrapperSecure.closeFail")); + } catch (IOException ioe) { + if (log.isDebugEnabled()) { + log.debug(sm.getString("asyncChannelWrapperSecure.closeFail"), ioe); + } else { + log.info(sm.getString("asyncChannelWrapperSecure.closeFail")); + } } executor.shutdownNow(); } @@ -144,7 +148,7 @@ @Override public Future handshake() throws SSLException { - WrapperFuture wFuture = new WrapperFuture<>(); + WrapperFuture wFuture = new WrapperFuture<>(); Thread t = new WebSocketSslHandshakeThread(wFuture); t.start(); @@ -164,9 +168,9 @@ private final ByteBuffer[] srcs; private final int offset; private final int length; - private final WrapperFuture future; + private final WrapperFuture future; - WriteTask(ByteBuffer[] srcs, int offset, int length, WrapperFuture future) { + WriteTask(ByteBuffer[] srcs, int offset, int length, WrapperFuture future) { this.srcs = srcs; this.future = future; this.offset = offset; @@ -235,9 +239,9 @@ private class ReadTask implements Runnable { private final ByteBuffer dest; - private final WrapperFuture future; + private final WrapperFuture future; - ReadTask(ByteBuffer dest, WrapperFuture future) { + ReadTask(ByteBuffer dest, WrapperFuture future) { this.dest = dest; this.future = future; } @@ -320,8 +324,8 @@ } else { future.fail(new IllegalStateException(sm.getString("asyncChannelWrapperSecure.wrongStateRead"))); } - } catch (RuntimeException | ReadBufferOverflowException | SSLException | EOFException | ExecutionException - | InterruptedException e) { + } catch (RuntimeException | ReadBufferOverflowException | SSLException | EOFException | ExecutionException | + InterruptedException e) { reading.set(false); future.fail(e); } @@ -331,12 +335,12 @@ private class WebSocketSslHandshakeThread extends Thread { - private final WrapperFuture hFuture; + private final WrapperFuture hFuture; private HandshakeStatus handshakeStatus; private Status resultStatus; - WebSocketSslHandshakeThread(WrapperFuture hFuture) { + WebSocketSslHandshakeThread(WrapperFuture hFuture) { this.hFuture = hFuture; } @@ -423,7 +427,7 @@ private static class WrapperFuture implements Future { - private final CompletionHandler handler; + private final CompletionHandler handler; private final A attachment; private volatile T result = null; @@ -434,7 +438,7 @@ this(null, null); } - WrapperFuture(CompletionHandler handler, A attachment) { + WrapperFuture(CompletionHandler handler, A attachment) { this.handler = handler; this.attachment = attachment; } diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/websocket/Authenticator.java tomcat10-10.1.52/java/org/apache/tomcat/websocket/Authenticator.java --- tomcat10-10.1.40/java/org/apache/tomcat/websocket/Authenticator.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/websocket/Authenticator.java 2026-01-23 19:33:36.000000000 +0000 @@ -66,10 +66,10 @@ * * @return a map of authentication parameter names and values */ - public Map parseAuthenticateHeader(String authenticateHeader) { + public Map parseAuthenticateHeader(String authenticateHeader) { Matcher m = pattern.matcher(authenticateHeader); - Map parameterMap = new HashMap<>(); + Map parameterMap = new HashMap<>(); while (m.find()) { String key = m.group(1); diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/websocket/BasicAuthenticator.java tomcat10-10.1.52/java/org/apache/tomcat/websocket/BasicAuthenticator.java --- tomcat10-10.1.40/java/org/apache/tomcat/websocket/BasicAuthenticator.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/websocket/BasicAuthenticator.java 2026-01-23 19:33:36.000000000 +0000 @@ -36,7 +36,7 @@ validateUsername(userName); validatePassword(userPassword); - Map parameterMap = parseAuthenticateHeader(authenticateHeader); + Map parameterMap = parseAuthenticateHeader(authenticateHeader); String realm = parameterMap.get("realm"); validateRealm(userRealm, realm); diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/websocket/Constants.java tomcat10-10.1.52/java/org/apache/tomcat/websocket/Constants.java --- tomcat10-10.1.40/java/org/apache/tomcat/websocket/Constants.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/websocket/Constants.java 2026-01-23 19:33:36.000000000 +0000 @@ -41,8 +41,8 @@ static final byte INTERNAL_OPCODE_FLUSH = 0x18; // Buffers - static final int DEFAULT_BUFFER_SIZE = Integer - .getInteger("org.apache.tomcat.websocket.DEFAULT_BUFFER_SIZE", 8 * 1024).intValue(); + static final int DEFAULT_BUFFER_SIZE = + Integer.getInteger("org.apache.tomcat.websocket.DEFAULT_BUFFER_SIZE", 8 * 1024).intValue(); // Client connection /** @@ -108,8 +108,8 @@ public static final int PROXY_AUTHENTICATION_REQUIRED = 407; // Configuration for Origin header in client - static final String DEFAULT_ORIGIN_HEADER_VALUE = System - .getProperty("org.apache.tomcat.websocket.DEFAULT_ORIGIN_HEADER_VALUE"); + static final String DEFAULT_ORIGIN_HEADER_VALUE = + System.getProperty("org.apache.tomcat.websocket.DEFAULT_ORIGIN_HEADER_VALUE"); // Configuration for blocking sends public static final String BLOCKING_SEND_TIMEOUT_PROPERTY = "org.apache.tomcat.websocket.BLOCKING_SEND_TIMEOUT"; @@ -122,7 +122,8 @@ public static final long DEFAULT_SESSION_CLOSE_TIMEOUT = TimeUnit.SECONDS.toMillis(30); // Configuration for session close timeout - public static final String ABNORMAL_SESSION_CLOSE_SEND_TIMEOUT_PROPERTY = "org.apache.tomcat.websocket.ABNORMAL_SESSION_CLOSE_SEND_TIMEOUT"; + public static final String ABNORMAL_SESSION_CLOSE_SEND_TIMEOUT_PROPERTY = + "org.apache.tomcat.websocket.ABNORMAL_SESSION_CLOSE_SEND_TIMEOUT"; // Default is 50 milliseconds - setting is in milliseconds public static final long DEFAULT_ABNORMAL_SESSION_CLOSE_SEND_TIMEOUT = 50; @@ -133,19 +134,21 @@ public static final String WRITE_IDLE_TIMEOUT_MS = "org.apache.tomcat.websocket.WRITE_IDLE_TIMEOUT_MS"; // Configuration for background processing checks intervals - static final int DEFAULT_PROCESS_PERIOD = Integer - .getInteger("org.apache.tomcat.websocket.DEFAULT_PROCESS_PERIOD", 10).intValue(); + static final int DEFAULT_PROCESS_PERIOD = + Integer.getInteger("org.apache.tomcat.websocket.DEFAULT_PROCESS_PERIOD", 10).intValue(); public static final String WS_AUTHENTICATION_USER_NAME = "org.apache.tomcat.websocket.WS_AUTHENTICATION_USER_NAME"; public static final String WS_AUTHENTICATION_PASSWORD = "org.apache.tomcat.websocket.WS_AUTHENTICATION_PASSWORD"; public static final String WS_AUTHENTICATION_REALM = "org.apache.tomcat.websocket.WS_AUTHENTICATION_REALM"; - public static final String WS_AUTHENTICATION_PROXY_USER_NAME = "org.apache.tomcat.websocket.WS_AUTHENTICATION_PROXY_USER_NAME"; - public static final String WS_AUTHENTICATION_PROXY_PASSWORD = "org.apache.tomcat.websocket.WS_AUTHENTICATION_PROXY_PASSWORD"; - public static final String WS_AUTHENTICATION_PROXY_REALM = "org.apache.tomcat.websocket.WS_AUTHENTICATION_PROXY_REALM"; + public static final String WS_AUTHENTICATION_PROXY_USER_NAME = + "org.apache.tomcat.websocket.WS_AUTHENTICATION_PROXY_USER_NAME"; + public static final String WS_AUTHENTICATION_PROXY_PASSWORD = + "org.apache.tomcat.websocket.WS_AUTHENTICATION_PROXY_PASSWORD"; + public static final String WS_AUTHENTICATION_PROXY_REALM = + "org.apache.tomcat.websocket.WS_AUTHENTICATION_PROXY_REALM"; - public static final List INSTALLED_EXTENSIONS = - List.of(new WsExtension("permessage-deflate")); + public static final List INSTALLED_EXTENSIONS = List.of(new WsExtension("permessage-deflate")); private Constants() { // Hide default constructor diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/websocket/DigestAuthenticator.java tomcat10-10.1.52/java/org/apache/tomcat/websocket/DigestAuthenticator.java --- tomcat10-10.1.40/java/org/apache/tomcat/websocket/DigestAuthenticator.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/websocket/DigestAuthenticator.java 2026-01-23 19:33:36.000000000 +0000 @@ -46,7 +46,7 @@ validateUsername(userName); validatePassword(userPassword); - Map parameterMap = parseAuthenticateHeader(authenticateHeader); + Map parameterMap = parseAuthenticateHeader(authenticateHeader); String realm = parameterMap.get("realm"); validateRealm(userRealm, realm); @@ -79,7 +79,8 @@ try { challenge.append("response=\""); - challenge.append(calculateRequestDigest(requestUri, userName, userPassword, realm, nonce, messageQop, algorithm)); + challenge.append( + calculateRequestDigest(requestUri, userName, userPassword, realm, nonce, messageQop, algorithm)); challenge.append("\","); } diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/websocket/LocalStrings.properties tomcat10-10.1.52/java/org/apache/tomcat/websocket/LocalStrings.properties --- tomcat10-10.1.40/java/org/apache/tomcat/websocket/LocalStrings.properties 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/websocket/LocalStrings.properties 2026-01-23 19:33:36.000000000 +0000 @@ -73,6 +73,7 @@ wsFrame.invalidUtf8=A WebSocket text frame was received that could not be decoded to UTF-8 because it contained invalid byte sequences wsFrame.invalidUtf8Close=A WebSocket close frame was received with a close reason that contained invalid UTF-8 byte sequences wsFrame.ioeTriggeredClose=An unrecoverable IOException occurred so the connection was closed +wsFrame.masked=The server frame was masked but server frames must not be masked wsFrame.messageTooBig=The message was [{0}] bytes long but the MessageHandler has a limit of [{1}] bytes wsFrame.noContinuation=A new message was started when a continuation frame was expected wsFrame.notMasked=The client frame was not masked but all client frames must be masked @@ -96,7 +97,7 @@ wsRemoteEndpoint.closedDuringMessage=The remainder of the message will not be sent because the WebSocket session has been closed wsRemoteEndpoint.closedOutputStream=This method may not be called as the OutputStream has been closed wsRemoteEndpoint.closedWriter=This method may not be called as the Writer has been closed -wsRemoteEndpoint.encoderDestoryFailed=Failed to destroy the encoder of type [{0}] +wsRemoteEndpoint.encoderDestroyFailed=Failed to destroy the encoder of type [{0}] wsRemoteEndpoint.encoderError=Encoding error [{0}] wsRemoteEndpoint.flushOnCloseFailed=Batched messages still enabled after session has been closed. Unable to flush remaining batched message. wsRemoteEndpoint.invalidEncoder=The specified encoder of type [{0}] could not be instantiated diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/websocket/LocalStrings_es.properties tomcat10-10.1.52/java/org/apache/tomcat/websocket/LocalStrings_es.properties --- tomcat10-10.1.40/java/org/apache/tomcat/websocket/LocalStrings_es.properties 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/websocket/LocalStrings_es.properties 2026-01-23 19:33:36.000000000 +0000 @@ -25,6 +25,7 @@ util.unknownDecoderType=No se reconoce el decodificador tipo [{0}] wsFrame.closed=Nuevo cuadro recibido luego de cerrar el cuadro de control +wsFrame.controlPayloadTooBig=Se envió una trama de control con una carga útil de tamaño [{0}], que es mayor que el máximo permitido de 125 bytes wsFrame.illegalReadState=Estado de lectura inesperado [{0}] wsFrame.notMasked=El cuadro del cliente no fue enmascarado, pero todos los cuadros de clientes deben ser enmascarados wsFrame.wrongRsv=El rango del cliente fija los bits reservados a [{0}] para un mensaje con opCode [{1}] el cual no fue soportado por este endpoint\n @@ -44,6 +45,8 @@ wsSession.duplicateHandlerText=Un manejador de mensaje de texto ya ha sido configurado wsSession.instanceNew=Falló la registración de la instancia del dispoitivo final +wsWebSocketContainer.asynchronousSocketChannelFail=No se pudo abrir una conexión con el servidor +wsWebSocketContainer.failedAuthentication=Error al manejar el código de respuesta HTTP [{0}]. El encabezado [{1}] no fue aceptado por el servidor.\n wsWebSocketContainer.missingAuthenticateHeader=Fallo al manejar el código de respuesta HTTP [{0}]. No existe la cabecera [{1}] en la respuesta wsWebSocketContainer.pathNoHost=No se especificó ningún host en URI wsWebSocketContainer.sessionCloseFail=La sesión con ID [{0}] no se cerró correctamente diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/websocket/LocalStrings_fr.properties tomcat10-10.1.52/java/org/apache/tomcat/websocket/LocalStrings_fr.properties --- tomcat10-10.1.40/java/org/apache/tomcat/websocket/LocalStrings_fr.properties 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/websocket/LocalStrings_fr.properties 2026-01-23 19:33:36.000000000 +0000 @@ -73,6 +73,7 @@ wsFrame.invalidUtf8=Une trame texte Websocket a été reçue et n'a pu 6etre traitée car elle contenait des séquence d'octets UTF-8 invalides wsFrame.invalidUtf8Close=Une trame de fermeture Websocket a été reçue avec une cause qui contenait des séquences UTF-8 invalides wsFrame.ioeTriggeredClose=Une IOException non récupérable est survenue donc la connection a été fermée +wsFrame.masked=La trame du serveur a été masquée mais les trames ne serveur ne doivent pas l'être wsFrame.messageTooBig=Le message fait [{0}] octets mais le MessageHandler a une limite de [{1}] octets wsFrame.noContinuation=Un nouveau message a été démarré quand une trame de continuation était attendue wsFrame.notMasked=La trame du client n'a pas de masque alors que toutes les trames des clients doivent en avoir un @@ -96,7 +97,7 @@ wsRemoteEndpoint.closedDuringMessage=Le reste du message ne sera pas envoyé parce que la session WebSocket est déjà fermée. wsRemoteEndpoint.closedOutputStream=La méthode ne peut pas être appelée alors que l'OutputStream a été fermée wsRemoteEndpoint.closedWriter=Cette méthode ne doit pas être appelée car le Writer a été fermé -wsRemoteEndpoint.encoderDestoryFailed=Echec de la destruction de l''encodeur de type [{0}] +wsRemoteEndpoint.encoderDestroyFailed=Echec de la destruction de l''encodeur de type [{0}] wsRemoteEndpoint.encoderError=Erreur d''encodage [{0}] wsRemoteEndpoint.flushOnCloseFailed=Le groupement de messages est toujours actif après fermeture de la session, impossible d'envoyer les messages restants wsRemoteEndpoint.invalidEncoder=L''encodeur spécifié de type [{0}] n''a pu être instancié diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/websocket/LocalStrings_ja.properties tomcat10-10.1.52/java/org/apache/tomcat/websocket/LocalStrings_ja.properties --- tomcat10-10.1.40/java/org/apache/tomcat/websocket/LocalStrings_ja.properties 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/websocket/LocalStrings_ja.properties 2026-01-23 19:33:36.000000000 +0000 @@ -73,6 +73,7 @@ wsFrame.invalidUtf8=無効なバイトシーケンスが含まれていたため、UTF-8にデコードできなかったWebSocketテキストフレームが受信されました。 wsFrame.invalidUtf8Close=WebSocket は無効な UTF-8 バイト列を含むことを原因とするクローズフレームを受信しました。 wsFrame.ioeTriggeredClose=回復不能なIOException が発生したためコネクションを切断します。 +wsFrame.masked=サーバーフレームがマスクされましたが、サーバーフレームはマスクされてはいけません wsFrame.messageTooBig=メッセージは [{0}] バイトの長さでしたが、MessageHandlerには [{1}] バイトの制限があります wsFrame.noContinuation=continuation フレームが予想されたときに新しいメッセージが開始されました。 wsFrame.notMasked=クライアントのフレームはマスクされていませんが、全てのクライアントのフレームはマスクしなければなりません。 @@ -96,7 +97,7 @@ wsRemoteEndpoint.closedDuringMessage=WebSocket セッションが切断されているため残りのメッセージは送信できません wsRemoteEndpoint.closedOutputStream=このメソッドは、OutputStreamが閉じられたときに呼び出されない場合があります。 wsRemoteEndpoint.closedWriter=Writerがクローズされているため、このメソッドを呼び出すことはできません。 -wsRemoteEndpoint.encoderDestoryFailed=タイプ [{0}] のエンコーダーの破棄に失敗しました +wsRemoteEndpoint.encoderDestroyFailed=タイプ [{0}] のエンコーダーの破棄に失敗しました wsRemoteEndpoint.encoderError=エンコードエラー [{0}] wsRemoteEndpoint.flushOnCloseFailed=セッションが閉じられた後にまだ可能であったバッチメッセージ。残りのバッチメッセージをフラッシュできません。 wsRemoteEndpoint.invalidEncoder=指定されたタイプ [{0}] のエンコーダをインスタンス化できませんでした diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/websocket/LocalStrings_ko.properties tomcat10-10.1.52/java/org/apache/tomcat/websocket/LocalStrings_ko.properties --- tomcat10-10.1.40/java/org/apache/tomcat/websocket/LocalStrings_ko.properties 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/websocket/LocalStrings_ko.properties 2026-01-23 19:33:36.000000000 +0000 @@ -93,7 +93,7 @@ wsRemoteEndpoint.closedDuringMessage=웹소켓 세션이 이미 닫혔기 때문에, 메시지의 나머지 부분은 전달되지 않을 것입니다. wsRemoteEndpoint.closedOutputStream=OutputStream이 이미 닫혀 있으므로, 이 메소드는 호출될 수 없습니다. wsRemoteEndpoint.closedWriter=Writer가 이미 닫혔기 때문에, 이 메소드는 호출될 수 없습니다. -wsRemoteEndpoint.encoderDestoryFailed=[{0}] 타입의 인코더를 소멸시키지 못했습니다. +wsRemoteEndpoint.encoderDestroyFailed=[{0}] 타입의 인코더를 소멸시키지 못했습니다. wsRemoteEndpoint.flushOnCloseFailed=세션이 이미 종료된 이후에도, 메시지들이 배치(batch)에 포함되어 있습니다. 배치에 남아있는 메시지들을 배출할 수 없습니다. wsRemoteEndpoint.invalidEncoder=지정된 타입 [{0}]의 Encoder의 인스턴스를 생성할 수 없었습니다. wsRemoteEndpoint.noEncoder=클래스 [{0}]의 객체를 위한 인코더가 지정되지 않았습니다. diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/websocket/LocalStrings_zh_CN.properties tomcat10-10.1.52/java/org/apache/tomcat/websocket/LocalStrings_zh_CN.properties --- tomcat10-10.1.40/java/org/apache/tomcat/websocket/LocalStrings_zh_CN.properties 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/websocket/LocalStrings_zh_CN.properties 2026-01-23 19:33:36.000000000 +0000 @@ -95,7 +95,7 @@ wsRemoteEndpoint.closedDuringMessage=因为 WebSocket session 被关闭,消息的剩余部分将不会被送达 wsRemoteEndpoint.closedOutputStream=由于OutputStream已关闭,不应该调用此方法。 wsRemoteEndpoint.closedWriter=此方法不能调用,因为编写器已关闭。 -wsRemoteEndpoint.encoderDestoryFailed=未能销毁[{0}]类型的编码器 +wsRemoteEndpoint.encoderDestroyFailed=未能销毁[{0}]类型的编码器 wsRemoteEndpoint.flushOnCloseFailed=会话关闭后仍然启用批处理消息。无法刷新剩余的批量消息 wsRemoteEndpoint.invalidEncoder=无法实例化类型为[{0}]的指定编码器 wsRemoteEndpoint.noEncoder=没有为类 [{0}] 的对象指定编码器 diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/websocket/PerMessageDeflate.java tomcat10-10.1.52/java/org/apache/tomcat/websocket/PerMessageDeflate.java --- tomcat10-10.1.40/java/org/apache/tomcat/websocket/PerMessageDeflate.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/websocket/PerMessageDeflate.java 2026-01-23 19:33:36.000000000 +0000 @@ -44,6 +44,13 @@ public static final String NAME = "permessage-deflate"; + public static final TransformationBuilder BUILDER = new TransformationBuilder() { + @Override + public Transformation build(List> preferences, boolean isServer) { + return PerMessageDeflate.build(preferences, isServer); + } + }; + private final boolean serverContextTakeover; private final int serverMaxWindowBits; private final boolean clientContextTakeover; @@ -61,7 +68,7 @@ // Flag to track if a message is completely empty private volatile boolean emptyMessage = true; - static PerMessageDeflate negotiate(List> preferences, boolean isServer) { + static PerMessageDeflate build(List> preferences, boolean isServer) { // Accept the first preference that the endpoint is able to support for (List preference : preferences) { boolean ok = true; @@ -194,7 +201,8 @@ written = inflater.inflate(dest.array(), dest.arrayOffset() + dest.position(), dest.remaining()); } catch (DataFormatException e) { throw new IOException(sm.getString("perMessageDeflate.deflateFailed"), e); - } catch (NullPointerException e) { + } catch (IllegalStateException | NullPointerException e) { + // As of Java 25, the JRE throws an ISE rather than an NPE throw new IOException(sm.getString("perMessageDeflate.alreadyClosed"), e); } dest.position(dest.position() + written); @@ -354,7 +362,8 @@ compressedPayload.arrayOffset() + compressedPayload.position(), compressedPayload.remaining(), flush); compressedPayload.position(compressedPayload.position() + written); - } catch (NullPointerException e) { + } catch (IllegalStateException | NullPointerException e) { + // As of Java 25, the JRE throws an ISE rather than an NPE throw new IOException(sm.getString("perMessageDeflate.alreadyClosed"), e); } @@ -394,14 +403,14 @@ compressedPart = new MessagePart(false, getRsv(uncompressedPart), opCode, compressedPayload, uncompressedIntermediateHandler, uncompressedIntermediateHandler, blockingWriteTimeoutExpiry); - } else if (!fin && full/* note: needsInput is true here*/) { + } else if (!fin && full/* note: needsInput is true here */) { // Write buffer full and input message not fully read. // Output and get more data. compressedPart = new MessagePart(false, getRsv(uncompressedPart), opCode, compressedPayload, uncompressedIntermediateHandler, uncompressedIntermediateHandler, blockingWriteTimeoutExpiry); deflateRequired = false; - } else if (fin && full/* note: needsInput is true here*/) { + } else if (fin && full/* note: needsInput is true here */) { // Write buffer full. Input fully read. Deflater may be // in one of four states: // - output complete (just happened to align with end of diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/websocket/TransformationBuilder.java tomcat10-10.1.52/java/org/apache/tomcat/websocket/TransformationBuilder.java --- tomcat10-10.1.40/java/org/apache/tomcat/websocket/TransformationBuilder.java 1970-01-01 00:00:00.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/websocket/TransformationBuilder.java 2026-01-23 19:33:36.000000000 +0000 @@ -0,0 +1,26 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.tomcat.websocket; + +import java.util.List; + +import jakarta.websocket.Extension; + +public interface TransformationBuilder { + + Transformation build(List> preferences, boolean isServer); +} diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/websocket/TransformationFactory.java tomcat10-10.1.52/java/org/apache/tomcat/websocket/TransformationFactory.java --- tomcat10-10.1.40/java/org/apache/tomcat/websocket/TransformationFactory.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/websocket/TransformationFactory.java 2026-01-23 19:33:36.000000000 +0000 @@ -16,7 +16,12 @@ */ package org.apache.tomcat.websocket; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; import java.util.List; +import java.util.Map; +import java.util.Set; import jakarta.websocket.Extension; @@ -24,18 +29,46 @@ private static final TransformationFactory factory = new TransformationFactory(); + private Map builders = new HashMap<>(); + + private TransformationFactory() { // Hide default constructor + + // Configure the built-in transformations + builders.put(PerMessageDeflate.NAME, PerMessageDeflate.BUILDER); } + public static TransformationFactory getInstance() { return factory; } + public Transformation create(String name, List> preferences, boolean isServer) { - if (PerMessageDeflate.NAME.equals(name)) { - return PerMessageDeflate.negotiate(preferences, isServer); + TransformationBuilder builder = builders.get(name); + if (builder != null) { + return builder.build(preferences, isServer); } return null; } + + + public void registerExtension(String name, TransformationBuilder builder) { + builders.put(name, builder); + } + + + public Set getInstalledExtensionNames() { + return new HashSet<>(builders.keySet()); + } + + + public Set getInstalledExtensions() { + Set result = new HashSet<>(); + for (String extensionName : builders.keySet()) { + result.add(new WsExtension(extensionName)); + } + return Collections.unmodifiableSet(result); + } } diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/websocket/Util.java tomcat10-10.1.52/java/org/apache/tomcat/websocket/Util.java --- tomcat10-10.1.40/java/org/apache/tomcat/websocket/Util.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/websocket/Util.java 2026-01-23 19:33:36.000000000 +0000 @@ -222,8 +222,8 @@ // the interface of interest // Map that unknown type to the generic types defined in this class ParameterizedType superClassType = (ParameterizedType) clazz.getGenericSuperclass(); - TypeResult result = getTypeParameter(clazz, - superClassType.getActualTypeArguments()[superClassTypeResult.getIndex()]); + TypeResult result = + getTypeParameter(clazz, superClassType.getActualTypeArguments()[superClassTypeResult.getIndex()]); result.incrementDimension(superClassTypeResult.getDimension()); if (result.getClazz() != null && result.getDimension() > 0) { superClassTypeResult = result; @@ -285,8 +285,8 @@ return true; } else { return clazz.equals(Boolean.class) || clazz.equals(Byte.class) || clazz.equals(Character.class) || - clazz.equals(Double.class) || clazz.equals(Float.class) || clazz.equals(Integer.class) || - clazz.equals(Long.class) || clazz.equals(Short.class); + clazz.equals(Double.class) || clazz.equals(Float.class) || clazz.equals(Integer.class) || + clazz.equals(Long.class) || clazz.equals(Short.class); } } @@ -343,8 +343,8 @@ // Don't need this instance, so destroy it instanceManager.destroyInstance(instance); } - } catch (ReflectiveOperationException | IllegalArgumentException | SecurityException - | NamingException e) { + } catch (ReflectiveOperationException | IllegalArgumentException | SecurityException | + NamingException e) { throw new DeploymentException( sm.getString("pojoMethodMapping.invalidDecoder", decoderClazz.getName()), e); } @@ -378,13 +378,16 @@ // the types expected by the frame handling code } else if (byte[].class.isAssignableFrom(target)) { boolean whole = MessageHandler.Whole.class.isAssignableFrom(listener.getClass()); - MessageHandlerResult result = new MessageHandlerResult(whole - ? new PojoMessageHandlerWholeBinary(listener, getOnMessageMethod(listener), session, endpointConfig, - matchDecoders(target, endpointConfig, true, ((WsSession) session).getInstanceManager()), - new Object[1], 0, true, -1, false, -1) - : new PojoMessageHandlerPartialBinary(listener, getOnMessagePartialMethod(listener), session, - new Object[2], 0, true, 1, -1, -1), - MessageHandlerResultType.BINARY); + MessageHandlerResult result = + new MessageHandlerResult(whole ? + new PojoMessageHandlerWholeBinary(listener, getOnMessageMethod(listener), session, + endpointConfig, + matchDecoders(target, endpointConfig, true, + ((WsSession) session).getInstanceManager()), + new Object[1], 0, true, -1, false, -1) : + new PojoMessageHandlerPartialBinary(listener, getOnMessagePartialMethod(listener), session, + new Object[2], 0, true, 1, -1, -1), + MessageHandlerResultType.BINARY); results.add(result); } else if (InputStream.class.isAssignableFrom(target)) { MessageHandlerResult result = new MessageHandlerResult( @@ -403,8 +406,8 @@ } else { // Handler needs wrapping and requires decoder to convert it to one // of the types expected by the frame handling code - DecoderMatch decoderMatch = matchDecoders(target, endpointConfig, - ((WsSession) session).getInstanceManager()); + DecoderMatch decoderMatch = + matchDecoders(target, endpointConfig, ((WsSession) session).getInstanceManager()); Method m = getOnMessageMethod(listener); if (!decoderMatch.getBinaryDecoders().isEmpty()) { MessageHandlerResult result = new MessageHandlerResult( diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/websocket/WsFrameBase.java tomcat10-10.1.52/java/org/apache/tomcat/websocket/WsFrameBase.java --- tomcat10-10.1.40/java/org/apache/tomcat/websocket/WsFrameBase.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/websocket/WsFrameBase.java 2026-01-23 19:33:36.000000000 +0000 @@ -200,9 +200,12 @@ continuationExpected = !fin; } b = inputBuffer.get(); - // Client data must be masked if ((b & 0x80) == 0 && isMasked()) { + // Client data must be masked throw new WsIOException(new CloseReason(CloseCodes.PROTOCOL_ERROR, sm.getString("wsFrame.notMasked"))); + } else if ((b & 0x80) != 0 && !isMasked()) { + // Server data must not masked + throw new WsIOException(new CloseReason(CloseCodes.PROTOCOL_ERROR, sm.getString("wsFrame.masked"))); } payloadLength = b & 0x7F; state = State.PARTIAL_HEADER; diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/websocket/WsFrameClient.java tomcat10-10.1.52/java/org/apache/tomcat/websocket/WsFrameClient.java --- tomcat10-10.1.40/java/org/apache/tomcat/websocket/WsFrameClient.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/websocket/WsFrameClient.java 2026-01-23 19:33:36.000000000 +0000 @@ -34,7 +34,7 @@ private static final StringManager sm = StringManager.getManager(WsFrameClient.class); private final AsyncChannelWrapper channel; - private final CompletionHandler handler; + private final CompletionHandler handler; // Not final as it may need to be re-sized private volatile ByteBuffer response; @@ -50,8 +50,8 @@ void startInputProcessing() { try { processSocketRead(); - } catch (IOException e) { - close(e); + } catch (IOException ioe) { + close(ioe); } } @@ -143,7 +143,7 @@ return log; } - private class WsFrameClientCompletionHandler implements CompletionHandler { + private class WsFrameClientCompletionHandler implements CompletionHandler { @Override public void completed(Integer result, Void attachment) { @@ -206,7 +206,7 @@ private void resumeProcessing(boolean checkOpenOnError) { try { processSocketRead(); - } catch (IOException e) { + } catch (IOException ioe) { if (checkOpenOnError) { // Only send a close message on an IOException if the client // has not yet received a close control message from the server @@ -215,12 +215,12 @@ // control message. if (isOpen()) { if (log.isDebugEnabled()) { - log.debug(sm.getString("wsFrameClient.ioe"), e); + log.debug(sm.getString("wsFrameClient.ioe"), ioe); } - close(e); + close(ioe); } } else { - close(e); + close(ioe); } } } diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/websocket/WsHandshakeResponse.java tomcat10-10.1.52/java/org/apache/tomcat/websocket/WsHandshakeResponse.java --- tomcat10-10.1.40/java/org/apache/tomcat/websocket/WsHandshakeResponse.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/websocket/WsHandshakeResponse.java 2026-01-23 19:33:36.000000000 +0000 @@ -30,15 +30,15 @@ */ public class WsHandshakeResponse implements HandshakeResponse { - private final Map> headers = new CaseInsensitiveKeyMap<>(); + private final Map> headers = new CaseInsensitiveKeyMap<>(); public WsHandshakeResponse() { } - public WsHandshakeResponse(Map> headers) { - for (Entry> entry : headers.entrySet()) { + public WsHandshakeResponse(Map> headers) { + for (Entry> entry : headers.entrySet()) { if (this.headers.containsKey(entry.getKey())) { this.headers.get(entry.getKey()).addAll(entry.getValue()); } else { @@ -50,7 +50,7 @@ @Override - public Map> getHeaders() { + public Map> getHeaders() { return headers; } } diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/websocket/WsRemoteEndpointImplBase.java tomcat10-10.1.52/java/org/apache/tomcat/websocket/WsRemoteEndpointImplBase.java --- tomcat10-10.1.40/java/org/apache/tomcat/websocket/WsRemoteEndpointImplBase.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/websocket/WsRemoteEndpointImplBase.java 2026-01-23 19:33:36.000000000 +0000 @@ -208,8 +208,8 @@ throw new IllegalArgumentException(sm.getString("wsRemoteEndpoint.nullHandler")); } stateMachine.textStart(); - TextMessageSendHandler tmsh = new TextMessageSendHandler(handler, CharBuffer.wrap(text), true, encoder, - encoderBuffer, this); + TextMessageSendHandler tmsh = + new TextMessageSendHandler(handler, CharBuffer.wrap(text), true, encoder, encoderBuffer, this); tmsh.write(); // TextMessageSendHandler will update stateMachine when it completes } @@ -260,8 +260,8 @@ void sendMessageBlock(byte opCode, ByteBuffer payload, boolean last, long timeout) throws IOException { /* - * Get the timeout before we send the message. The message may trigger a session close and depending on timing - * the client session may close before we can read the timeout. + * Get the timeout before we send the message. The message may trigger a session close and depending on timing + * the client session may close before we can read the timeout. */ sendMessageBlockInternal(opCode, payload, last, getTimeoutExpiry(timeout)); } @@ -512,9 +512,9 @@ if (getBatchingAllowed() || isMasked()) { // Need to write via output buffer - OutputBufferSendHandler obsh = new OutputBufferSendHandler(mp.getEndHandler(), - mp.getBlockingWriteTimeoutExpiry(), headerBuffer, mp.getPayload(), mask, outputBuffer, - !getBatchingAllowed(), this); + OutputBufferSendHandler obsh = + new OutputBufferSendHandler(mp.getEndHandler(), mp.getBlockingWriteTimeoutExpiry(), headerBuffer, + mp.getPayload(), mask, outputBuffer, !getBatchingAllowed(), this); obsh.write(); } else { // Can write directly @@ -573,10 +573,9 @@ /** * If a transformation needs to split a {@link MessagePart} into multiple {@link MessagePart}s, it uses this handler - * as the end handler for each of the additional {@link MessagePart}s. This handler notifies this class that - * the {@link MessagePart} has been processed and that the next {@link MessagePart} in the queue should be started. - * The final {@link MessagePart} will use the {@link EndMessageHandler} provided with the original - * {@link MessagePart}. + * as the end handler for each of the additional {@link MessagePart}s. This handler notifies this class that the + * {@link MessagePart} has been processed and that the next {@link MessagePart} in the queue should be started. The + * final {@link MessagePart} will use the {@link EndMessageHandler} provided with the original {@link MessagePart}. */ private static class IntermediateMessageHandler implements SendHandler { @@ -740,7 +739,7 @@ try { instanceManager.destroyInstance(entry); } catch (IllegalAccessException | InvocationTargetException e) { - log.warn(sm.getString("wsRemoteEndpoint.encoderDestoryFailed", encoder.getClass()), e); + log.warn(sm.getString("wsRemoteEndpoint.encoderDestroyFailed", encoder.getClass()), e); } } } @@ -1001,9 +1000,7 @@ @Override public void write(int b) throws IOException { - if (closed) { - throw new IllegalStateException(sm.getString("wsRemoteEndpoint.closedOutputStream")); - } + checkOpen(); used = true; if (buffer.remaining() == 0) { @@ -1014,9 +1011,7 @@ @Override public void write(byte[] b, int off, int len) throws IOException { - if (closed) { - throw new IllegalStateException(sm.getString("wsRemoteEndpoint.closedOutputStream")); - } + checkOpen(); if ((off < 0) || (off > b.length) || (len < 0) || ((off + len) > b.length) || ((off + len) < 0)) { throw new IndexOutOfBoundsException(); } @@ -1044,9 +1039,7 @@ @Override public void flush() throws IOException { - if (closed) { - throw new IllegalStateException(sm.getString("wsRemoteEndpoint.closedOutputStream")); - } + checkOpen(); // Optimisation. If there is no data to flush then do not send an // empty message. @@ -1067,6 +1060,12 @@ doWrite(true); } + private void checkOpen() throws IOException { + if (closed) { + throw new IOException(sm.getString("wsRemoteEndpoint.closedOutputStream")); + } + } + private void doWrite(boolean last) throws IOException { if (used) { buffer.flip(); @@ -1092,9 +1091,7 @@ @Override public void write(char[] cbuf, int off, int len) throws IOException { - if (closed) { - throw new IllegalStateException(sm.getString("wsRemoteEndpoint.closedWriter")); - } + checkOpen(); if ((off < 0) || (off > cbuf.length) || (len < 0) || ((off + len) > cbuf.length) || ((off + len) < 0)) { throw new IndexOutOfBoundsException(); } @@ -1122,9 +1119,7 @@ @Override public void flush() throws IOException { - if (closed) { - throw new IllegalStateException(sm.getString("wsRemoteEndpoint.closedWriter")); - } + checkOpen(); if (buffer.position() > 0) { doWrite(false); @@ -1143,6 +1138,12 @@ doWrite(true); } + private void checkOpen() throws IOException { + if (closed) { + throw new IOException(sm.getString("wsRemoteEndpoint.closedWriter")); + } + } + private void doWrite(boolean last) throws IOException { if (used) { buffer.flip(); diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/websocket/WsSession.java tomcat10-10.1.52/java/org/apache/tomcat/websocket/WsSession.java --- tomcat10-10.1.40/java/org/apache/tomcat/websocket/WsSession.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/websocket/WsSession.java 2026-01-23 19:33:36.000000000 +0000 @@ -81,8 +81,8 @@ // be sufficient to pass the validation tests. ServerEndpointConfig.Builder builder = ServerEndpointConfig.Builder.create(Object.class, "/"); ServerEndpointConfig sec = builder.build(); - SEC_CONFIGURATOR_USES_IMPL_DEFAULT = sec.getConfigurator().getClass() - .equals(DefaultServerEndpointConfigurator.class); + SEC_CONFIGURATOR_USES_IMPL_DEFAULT = + sec.getConfigurator().getClass().equals(DefaultServerEndpointConfigurator.class); } private final Endpoint localEndpoint; @@ -92,14 +92,14 @@ private final ClassLoader applicationClassLoader; private final WsWebSocketContainer webSocketContainer; private final URI requestUri; - private final Map> requestParameterMap; + private final Map> requestParameterMap; private final String queryString; private final Principal userPrincipal; private final EndpointConfig endpointConfig; private final List negotiatedExtensions; private final String subProtocol; - private final Map pathParameters; + private final Map pathParameters; private final boolean secure; private final String httpSessionId; private final String id; @@ -110,13 +110,13 @@ private volatile MessageHandler binaryMessageHandler = null; private volatile MessageHandler.Whole pongMessageHandler = null; private final AtomicReference state = new AtomicReference<>(State.OPEN); - private final Map userProperties = new ConcurrentHashMap<>(); + private final Map userProperties = new ConcurrentHashMap<>(); private volatile int maxBinaryMessageBufferSize = Constants.DEFAULT_BUFFER_SIZE; private volatile int maxTextMessageBufferSize = Constants.DEFAULT_BUFFER_SIZE; private volatile long maxIdleTimeout = 0; private volatile long lastActiveRead = System.currentTimeMillis(); private volatile long lastActiveWrite = System.currentTimeMillis(); - private final Map futures = new ConcurrentHashMap<>(); + private final Map futures = new ConcurrentHashMap<>(); private volatile Long sessionCloseTimeoutExpiry; @@ -139,7 +139,7 @@ */ public WsSession(ClientEndpointHolder clientEndpointHolder, WsRemoteEndpointImplBase wsRemoteEndpoint, WsWebSocketContainer wsWebSocketContainer, List negotiatedExtensions, String subProtocol, - Map pathParameters, boolean secure, ClientEndpointConfig clientEndpointConfig) + Map pathParameters, boolean secure, ClientEndpointConfig clientEndpointConfig) throws DeploymentException { this.wsRemoteEndpoint = wsRemoteEndpoint; this.wsRemoteEndpoint.setSession(this); @@ -201,9 +201,9 @@ * @throws DeploymentException if an invalid encode is specified */ public WsSession(WsRemoteEndpointImplBase wsRemoteEndpoint, WsWebSocketContainer wsWebSocketContainer, - URI requestUri, Map> requestParameterMap, String queryString, Principal userPrincipal, + URI requestUri, Map> requestParameterMap, String queryString, Principal userPrincipal, String httpSessionId, List negotiatedExtensions, String subProtocol, - Map pathParameters, boolean secure, ServerEndpointConfig serverEndpointConfig) + Map pathParameters, boolean secure, ServerEndpointConfig serverEndpointConfig) throws DeploymentException { this.wsRemoteEndpoint = wsRemoteEndpoint; @@ -269,8 +269,7 @@ if (configurator.getClass().equals(DefaultServerEndpointConfigurator.class)) { return true; } - return SEC_CONFIGURATOR_USES_IMPL_DEFAULT && - configurator.getClass().equals(Configurator.class); + return SEC_CONFIGURATOR_USES_IMPL_DEFAULT && configurator.getClass().equals(Configurator.class); } @@ -633,9 +632,9 @@ closeConnection(); } else if (state.compareAndSet(State.OUTPUT_CLOSING, State.CLOSING)) { /* - * The local endpoint sent a close message at the same time as the remote endpoint. The local close is - * still being processed. Update the state so the local close process will also close the network - * connection once it has finished sending a close message. + * The local endpoint sent a close message at the same time as the remote endpoint. The local close is still + * being processed. Update the state so the local close process will also close the network connection once + * it has finished sending a close message. */ } else if (state.compareAndSet(State.OUTPUT_CLOSED, State.CLOSED)) { /* @@ -908,7 +907,7 @@ @Override - public Map> getRequestParameterMap() { + public Map> getRequestParameterMap() { checkState(); return requestParameterMap; } @@ -934,7 +933,7 @@ @Override - public Map getPathParameters() { + public Map getPathParameters() { checkState(); return pathParameters; } @@ -947,7 +946,7 @@ @Override - public Map getUserProperties() { + public Map getUserProperties() { checkState(); return userProperties; } diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/websocket/WsWebSocketContainer.java tomcat10-10.1.52/java/org/apache/tomcat/websocket/WsWebSocketContainer.java --- tomcat10-10.1.40/java/org/apache/tomcat/websocket/WsWebSocketContainer.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/websocket/WsWebSocketContainer.java 2026-01-23 19:33:36.000000000 +0000 @@ -38,6 +38,7 @@ import java.util.Collections; import java.util.HashMap; import java.util.HashSet; +import java.util.Iterator; import java.util.List; import java.util.Locale; import java.util.Map; @@ -92,8 +93,8 @@ private final Log log = LogFactory.getLog(WsWebSocketContainer.class); // must not be static // Server side uses the endpoint path as the key // Client side uses the client endpoint instance - private final Map> endpointSessionMap = new HashMap<>(); - private final Map sessions = new ConcurrentHashMap<>(); + private final Map> endpointSessionMap = new HashMap<>(); + private final Map sessions = new ConcurrentHashMap<>(); private final Object endPointSessionMapLock = new Object(); private long defaultAsyncTimeout = -1; @@ -156,8 +157,7 @@ if (configurator != null) { builder.configurator(configurator); } - return builder.decoders(Arrays.asList(annotation.decoders())) - .encoders(Arrays.asList(annotation.encoders())) + return builder.decoders(Arrays.asList(annotation.decoders())).encoders(Arrays.asList(annotation.encoders())) .preferredSubprotocols(Arrays.asList(annotation.subprotocols())).build(); } @@ -239,7 +239,7 @@ } } - Map userProperties = clientEndpointConfiguration.getUserProperties(); + Map userProperties = clientEndpointConfiguration.getUserProperties(); // If sa is null, no proxy is configured so need to create sa if (sa == null) { @@ -250,7 +250,7 @@ } // Create the initial HTTP request to open the WebSocket connection - Map> reqHeaders = createRequestHeaders(host, port, secure, clientEndpointConfiguration); + Map> reqHeaders = createRequestHeaders(host, port, secure, clientEndpointConfiguration); clientEndpointConfiguration.getConfigurator().beforeRequest(reqHeaders); if (Constants.DEFAULT_ORIGIN_HEADER_VALUE != null && !reqHeaders.containsKey(Constants.ORIGIN_HEADER_NAME)) { List originValues = new ArrayList<>(1); @@ -341,8 +341,8 @@ if (httpResponse.status != 101) { if (isRedirectStatus(httpResponse.status)) { - List locationHeader = httpResponse.getHandshakeResponse().getHeaders() - .get(Constants.LOCATION_HEADER_NAME); + List locationHeader = + httpResponse.getHandshakeResponse().getHeaders().get(Constants.LOCATION_HEADER_NAME); if (locationHeader == null || locationHeader.isEmpty() || locationHeader.get(0) == null || locationHeader.get(0).isEmpty()) { @@ -422,8 +422,8 @@ } success = true; - } catch (ExecutionException | InterruptedException | SSLException | EOFException | TimeoutException - | URISyntaxException | AuthenticationException e) { + } catch (ExecutionException | InterruptedException | SSLException | EOFException | TimeoutException | + URISyntaxException | AuthenticationException e) { throw new DeploymentException(sm.getString("wsWebSocketContainer.httpRequestFailed", path), e); } finally { if (!success) { @@ -469,7 +469,7 @@ private Session processAuthenticationChallenge(ClientEndpointHolder clientEndpointHolder, ClientEndpointConfig clientEndpointConfiguration, URI path, Set redirectSet, - Map userProperties, ByteBuffer request, HttpResponse httpResponse, + Map userProperties, ByteBuffer request, HttpResponse httpResponse, AuthenticationType authenticationType) throws DeploymentException, AuthenticationException { if (userProperties.get(authenticationType.getAuthorizationHeaderName()) != null) { @@ -477,8 +477,8 @@ Integer.valueOf(httpResponse.status), authenticationType.getAuthorizationHeaderName())); } - List authenticateHeaders = httpResponse.getHandshakeResponse().getHeaders() - .get(authenticationType.getAuthenticateHeaderName()); + List authenticateHeaders = + httpResponse.getHandshakeResponse().getHeaders().get(authenticationType.getAuthenticateHeaderName()); if (authenticateHeaders == null || authenticateHeaders.isEmpty() || authenticateHeaders.get(0) == null || authenticateHeaders.get(0).isEmpty()) { @@ -619,13 +619,13 @@ return result; } - private static Map> createRequestHeaders(String host, int port, boolean secure, + private static Map> createRequestHeaders(String host, int port, boolean secure, ClientEndpointConfig clientEndpointConfiguration) { - Map> headers = new HashMap<>(); + Map> headers = new HashMap<>(); List extensions = clientEndpointConfiguration.getExtensions(); List subProtocols = clientEndpointConfiguration.getPreferredSubprotocols(); - Map userProperties = clientEndpointConfiguration.getUserProperties(); + Map userProperties = clientEndpointConfiguration.getUserProperties(); if (userProperties.get(Constants.AUTHORIZATION_HEADER_NAME) != null) { List authValues = new ArrayList<>(1); @@ -670,8 +670,20 @@ } // WebSocket extensions - if (extensions != null && !extensions.isEmpty()) { - headers.put(Constants.WS_EXTENSIONS_HEADER_NAME, generateExtensionHeaders(extensions)); + if (extensions != null) { + // Filter the requested extensions to remove any that are not supported by the client container. + Set installed = TransformationFactory.getInstance().getInstalledExtensionNames(); + List availableExtensions = new ArrayList<>(extensions); + Iterator availableExtensionsIter = availableExtensions.iterator(); + while (availableExtensionsIter.hasNext()) { + Extension e = availableExtensionsIter.next(); + if (!installed.contains(e.getName())) { + availableExtensionsIter.remove(); + } + } + if (!availableExtensions.isEmpty()) { + headers.put(Constants.WS_EXTENSIONS_HEADER_NAME, generateExtensionHeaders(availableExtensions)); + } } return headers; @@ -705,7 +717,7 @@ } - private static ByteBuffer createRequest(URI uri, Map> reqHeaders) { + private static ByteBuffer createRequest(URI uri, Map> reqHeaders) { ByteBuffer result = ByteBuffer.allocate(4 * 1024); // Request line @@ -724,7 +736,7 @@ result.put(HTTP_VERSION_BYTES); // Headers - for (Entry> entry : reqHeaders.entrySet()) { + for (Entry> entry : reqHeaders.entrySet()) { result = addHeader(result, entry.getKey(), entry.getValue()); } @@ -779,7 +791,7 @@ private HttpResponse processResponse(ByteBuffer response, AsyncChannelWrapper channel, long timeout) throws InterruptedException, ExecutionException, DeploymentException, EOFException, TimeoutException { - Map> headers = new CaseInsensitiveKeyMap<>(); + Map> headers = new CaseInsensitiveKeyMap<>(); int status = 0; boolean readStatus = false; @@ -845,7 +857,7 @@ } - private void parseHeaders(String line, Map> headers) { + private void parseHeaders(String line, Map> headers) { // Treat headers as single values by default. int index = line.indexOf(':'); @@ -884,7 +896,7 @@ private SSLEngine createSSLEngine(ClientEndpointConfig clientEndpointConfig, String host, int port) throws DeploymentException { - Map userProperties = clientEndpointConfig.getUserProperties(); + Map userProperties = clientEndpointConfig.getUserProperties(); try { // See if a custom SSLContext has been provided SSLContext sslContext = clientEndpointConfig.getSSLContext(); @@ -913,8 +925,8 @@ KeyStoreUtil.load(ks, is, sslTrustStorePwdValue.toCharArray()); } - TrustManagerFactory tmf = TrustManagerFactory - .getInstance(TrustManagerFactory.getDefaultAlgorithm()); + TrustManagerFactory tmf = + TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); tmf.init(ks); sslContext.init(null, tmf.getTrustManagers(), null); @@ -988,7 +1000,7 @@ */ @Override public Set getInstalledExtensions() { - return Collections.emptySet(); + return TransformationFactory.getInstance().getInstalledExtensions(); } @@ -1021,7 +1033,9 @@ try { session.close(cr); } catch (IOException ioe) { - log.debug(sm.getString("wsWebSocketContainer.sessionCloseFail", session.getId()), ioe); + if (log.isDebugEnabled()) { + log.debug(sm.getString("wsWebSocketContainer.sessionCloseFail", session.getId()), ioe); + } } } diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/websocket/pojo/PojoEndpointBase.java tomcat10-10.1.52/java/org/apache/tomcat/websocket/pojo/PojoEndpointBase.java --- tomcat10-10.1.40/java/org/apache/tomcat/websocket/pojo/PojoEndpointBase.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/websocket/pojo/PojoEndpointBase.java 2026-01-23 19:33:36.000000000 +0000 @@ -42,11 +42,11 @@ private static final StringManager sm = StringManager.getManager(PojoEndpointBase.class); private Object pojo; - private final Map pathParameters; + private final Map pathParameters; private PojoMethodMapping methodMapping; - protected PojoEndpointBase(Map pathParameters) { + protected PojoEndpointBase(Map pathParameters) { this.pathParameters = pathParameters; } diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/websocket/pojo/PojoEndpointServer.java tomcat10-10.1.52/java/org/apache/tomcat/websocket/pojo/PojoEndpointServer.java --- tomcat10-10.1.40/java/org/apache/tomcat/websocket/pojo/PojoEndpointServer.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/websocket/pojo/PojoEndpointServer.java 2026-01-23 19:33:36.000000000 +0000 @@ -28,7 +28,7 @@ */ public class PojoEndpointServer extends PojoEndpointBase { - public PojoEndpointServer(Map pathParameters, Object pojo) { + public PojoEndpointServer(Map pathParameters, Object pojo) { super(pathParameters); setPojo(pojo); } @@ -39,8 +39,8 @@ ServerEndpointConfig sec = (ServerEndpointConfig) endpointConfig; - PojoMethodMapping methodMapping = (PojoMethodMapping) sec.getUserProperties() - .get(Constants.POJO_METHOD_MAPPING_KEY); + PojoMethodMapping methodMapping = + (PojoMethodMapping) sec.getUserProperties().get(Constants.POJO_METHOD_MAPPING_KEY); setMethodMapping(methodMapping); doOnOpen(session, endpointConfig); diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/websocket/pojo/PojoMethodMapping.java tomcat10-10.1.52/java/org/apache/tomcat/websocket/pojo/PojoMethodMapping.java --- tomcat10-10.1.40/java/org/apache/tomcat/websocket/pojo/PojoMethodMapping.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/websocket/pojo/PojoMethodMapping.java 2026-01-23 19:33:36.000000000 +0000 @@ -229,7 +229,7 @@ } - public Object[] getOnOpenArgs(Map pathParameters, Session session, EndpointConfig config) + public Object[] getOnOpenArgs(Map pathParameters, Session session, EndpointConfig config) throws DecodeException { return buildArgs(onOpenParams, pathParameters, session, config, null, null); } @@ -240,7 +240,7 @@ } - public Object[] getOnCloseArgs(Map pathParameters, Session session, CloseReason closeReason) + public Object[] getOnCloseArgs(Map pathParameters, Session session, CloseReason closeReason) throws DecodeException { return buildArgs(onCloseParams, pathParameters, session, null, null, closeReason); } @@ -251,7 +251,7 @@ } - public Object[] getOnErrorArgs(Map pathParameters, Session session, Throwable throwable) + public Object[] getOnErrorArgs(Map pathParameters, Session session, Throwable throwable) throws DecodeException { return buildArgs(onErrorParams, pathParameters, session, null, throwable, null); } @@ -262,7 +262,7 @@ } - public Set getMessageHandlers(Object pojo, Map pathParameters, Session session, + public Set getMessageHandlers(Object pojo, Map pathParameters, Session session, EndpointConfig config) { Set result = new HashSet<>(); for (MessageHandlerInfo messageMethod : onMessage) { @@ -314,7 +314,7 @@ } - private static Object[] buildArgs(PojoPathParam[] pathParams, Map pathParameters, Session session, + private static Object[] buildArgs(PojoPathParam[] pathParams, Map pathParameters, Session session, EndpointConfig config, Throwable throwable, CloseReason closeReason) throws DecodeException { Object[] result = new Object[pathParams.length]; for (int i = 0; i < pathParams.length; i++) { @@ -354,7 +354,7 @@ private int indexInputStream = -1; private int indexReader = -1; private int indexPrimitive = -1; - private final Map indexPathParams = new HashMap<>(); + private final Map indexPathParams = new HashMap<>(); private int indexPayload = -1; private DecoderMatch decoderMatch = null; private final long maxMessageSize; @@ -574,11 +574,11 @@ } - public Set getMessageHandlers(Object pojo, Map pathParameters, Session session, + public Set getMessageHandlers(Object pojo, Map pathParameters, Session session, EndpointConfig config) { Object[] params = new Object[m.getParameterTypes().length]; - for (Map.Entry entry : indexPathParams.entrySet()) { + for (Map.Entry entry : indexPathParams.entrySet()) { PojoPathParam pathParam = entry.getValue(); String valueString = pathParameters.get(pathParam.getName()); Object value; @@ -630,8 +630,8 @@ results.add(mh); } } else { - MessageHandler mh = new PojoMessageHandlerWholePong(pojo, m, session, params, indexPong, false, - indexSession); + MessageHandler mh = + new PojoMessageHandlerWholePong(pojo, m, session, params, indexPong, false, indexSession); results.add(mh); } } else { diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/websocket/server/Constants.java tomcat10-10.1.52/java/org/apache/tomcat/websocket/server/Constants.java --- tomcat10-10.1.40/java/org/apache/tomcat/websocket/server/Constants.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/websocket/server/Constants.java 2026-01-23 19:33:36.000000000 +0000 @@ -21,8 +21,10 @@ */ public class Constants { - public static final String BINARY_BUFFER_SIZE_SERVLET_CONTEXT_INIT_PARAM = "org.apache.tomcat.websocket.binaryBufferSize"; - public static final String TEXT_BUFFER_SIZE_SERVLET_CONTEXT_INIT_PARAM = "org.apache.tomcat.websocket.textBufferSize"; + public static final String BINARY_BUFFER_SIZE_SERVLET_CONTEXT_INIT_PARAM = + "org.apache.tomcat.websocket.binaryBufferSize"; + public static final String TEXT_BUFFER_SIZE_SERVLET_CONTEXT_INIT_PARAM = + "org.apache.tomcat.websocket.textBufferSize"; public static final String SERVER_CONTAINER_SERVLET_CONTEXT_ATTRIBUTE = "jakarta.websocket.server.ServerContainer"; diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/websocket/server/UpgradeUtil.java tomcat10-10.1.52/java/org/apache/tomcat/websocket/server/UpgradeUtil.java --- tomcat10-10.1.40/java/org/apache/tomcat/websocket/server/UpgradeUtil.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/websocket/server/UpgradeUtil.java 2026-01-23 19:33:36.000000000 +0000 @@ -38,6 +38,7 @@ import jakarta.websocket.HandshakeResponse; import jakarta.websocket.server.ServerEndpointConfig; +import org.apache.tomcat.util.http.Method; import org.apache.tomcat.util.res.StringManager; import org.apache.tomcat.util.security.ConcurrentMessageDigest; import org.apache.tomcat.websocket.Constants; @@ -50,8 +51,8 @@ public class UpgradeUtil { private static final StringManager sm = StringManager.getManager(UpgradeUtil.class.getPackage().getName()); - private static final byte[] WS_ACCEPT = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11" - .getBytes(StandardCharsets.ISO_8859_1); + private static final byte[] WS_ACCEPT = + "258EAFA5-E914-47DA-95CA-C5AB0DC85B11".getBytes(StandardCharsets.ISO_8859_1); private UpgradeUtil() { // Utility class. Hide default constructor. @@ -74,12 +75,12 @@ return ((request instanceof HttpServletRequest) && (response instanceof HttpServletResponse) && headerContainsToken((HttpServletRequest) request, Constants.UPGRADE_HEADER_NAME, Constants.UPGRADE_HEADER_VALUE) && - "GET".equals(((HttpServletRequest) request).getMethod())); + Method.GET.equals(((HttpServletRequest) request).getMethod())); } public static void doUpgrade(WsServerContainer sc, HttpServletRequest req, HttpServletResponse resp, - ServerEndpointConfig sec, Map pathParams) throws ServletException, IOException { + ServerEndpointConfig sec, Map pathParams) throws ServletException, IOException { // Validate the rest of the headers and reject the request if that // validation fails @@ -130,8 +131,8 @@ installedExtensions.addAll(sec.getExtensions()); installedExtensions.addAll(Constants.INSTALLED_EXTENSIONS); } - List negotiatedExtensionsPhase1 = sec.getConfigurator().getNegotiatedExtensions(installedExtensions, - extensionsRequested); + List negotiatedExtensionsPhase1 = + sec.getConfigurator().getNegotiatedExtensions(installedExtensions, extensionsRequested); // Negotiation phase 2. Create the Transformations that will be applied // to this connection. Note than an extension may be dropped at this @@ -211,7 +212,7 @@ wsRequest.finished(); // Add any additional headers - for (Entry> entry : wsResponse.getHeaders().entrySet()) { + for (Entry> entry : wsResponse.getHeaders().entrySet()) { for (String headerValue : entry.getValue()) { resp.addHeader(entry.getKey(), headerValue); } @@ -253,7 +254,7 @@ TransformationFactory factory = TransformationFactory.getInstance(); - LinkedHashMap>> extensionPreferences = new LinkedHashMap<>(); + LinkedHashMap>> extensionPreferences = new LinkedHashMap<>(); // Result will likely be smaller than this List result = new ArrayList<>(negotiatedExtensions.size()); @@ -263,7 +264,7 @@ .add(extension.getParameters()); } - for (Map.Entry>> entry : extensionPreferences.entrySet()) { + for (Map.Entry>> entry : extensionPreferences.entrySet()) { Transformation transformation = factory.create(entry.getKey(), entry.getValue(), true); if (transformation != null) { result.add(transformation); diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/websocket/server/UriTemplate.java tomcat10-10.1.52/java/org/apache/tomcat/websocket/server/UriTemplate.java --- tomcat10-10.1.40/java/org/apache/tomcat/websocket/server/UriTemplate.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/websocket/server/UriTemplate.java 2026-01-23 19:33:36.000000000 +0000 @@ -43,8 +43,8 @@ public UriTemplate(String path) throws DeploymentException { - if (path == null || !path.startsWith("/") || path.contains("/../") || - path.contains("/./") || path.contains("//")) { + if (path == null || !path.startsWith("/") || path.contains("/../") || path.contains("/./") || + path.contains("//")) { throw new DeploymentException(sm.getString("uriTemplate.invalidPath", path)); } @@ -97,9 +97,9 @@ } - public Map match(UriTemplate candidate) { + public Map match(UriTemplate candidate) { - Map result = new HashMap<>(); + Map result = new HashMap<>(); // Should not happen but for safety if (candidate.getSegmentCount() != getSegmentCount()) { diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/websocket/server/WsFrameServer.java tomcat10-10.1.52/java/org/apache/tomcat/websocket/server/WsFrameServer.java --- tomcat10-10.1.40/java/org/apache/tomcat/websocket/server/WsFrameServer.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/websocket/server/WsFrameServer.java 2026-01-23 19:33:36.000000000 +0000 @@ -162,9 +162,9 @@ } try { return doOnDataAvailable(); - } catch (IOException e) { + } catch (IOException ioe) { changeReadState(ReadState.CLOSING); - throw e; + throw ioe; } case SUSPENDING_WAIT: if (!changeReadState(ReadState.SUSPENDING_WAIT, ReadState.SUSPENDED)) { diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/websocket/server/WsHandshakeRequest.java tomcat10-10.1.52/java/org/apache/tomcat/websocket/server/WsHandshakeRequest.java --- tomcat10-10.1.40/java/org/apache/tomcat/websocket/server/WsHandshakeRequest.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/websocket/server/WsHandshakeRequest.java 2026-01-23 19:33:36.000000000 +0000 @@ -41,16 +41,16 @@ private static final StringManager sm = StringManager.getManager(WsHandshakeRequest.class); private final URI requestUri; - private final Map> parameterMap; + private final Map> parameterMap; private final String queryString; private final Principal userPrincipal; - private final Map> headers; + private final Map> headers; private final Object httpSession; private volatile HttpServletRequest request; - public WsHandshakeRequest(HttpServletRequest request, Map pathParams) { + public WsHandshakeRequest(HttpServletRequest request, Map pathParams) { this.request = request; @@ -60,18 +60,18 @@ requestUri = buildRequestUri(request); // ParameterMap - Map originalParameters = request.getParameterMap(); - Map> newParameters = new HashMap<>(originalParameters.size()); - for (Entry entry : originalParameters.entrySet()) { + Map originalParameters = request.getParameterMap(); + Map> newParameters = new HashMap<>(originalParameters.size()); + for (Entry entry : originalParameters.entrySet()) { newParameters.put(entry.getKey(), Collections.unmodifiableList(Arrays.asList(entry.getValue()))); } - for (Entry entry : pathParams.entrySet()) { + for (Entry entry : pathParams.entrySet()) { newParameters.put(entry.getKey(), Collections.singletonList(entry.getValue())); } parameterMap = Collections.unmodifiableMap(newParameters); // Headers - Map> newHeaders = new CaseInsensitiveKeyMap<>(); + Map> newHeaders = new CaseInsensitiveKeyMap<>(); Enumeration headerNames = request.getHeaderNames(); while (headerNames.hasMoreElements()) { @@ -89,7 +89,7 @@ } @Override - public Map> getParameterMap() { + public Map> getParameterMap() { return parameterMap; } @@ -104,7 +104,7 @@ } @Override - public Map> getHeaders() { + public Map> getHeaders() { return headers; } diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/websocket/server/WsHttpUpgradeHandler.java tomcat10-10.1.52/java/org/apache/tomcat/websocket/server/WsHttpUpgradeHandler.java --- tomcat10-10.1.40/java/org/apache/tomcat/websocket/server/WsHttpUpgradeHandler.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/websocket/server/WsHttpUpgradeHandler.java 2026-01-23 19:33:36.000000000 +0000 @@ -63,7 +63,7 @@ private List negotiatedExtensions; private String subProtocol; private Transformation transformation; - private Map pathParameters; + private Map pathParameters; private boolean secure; private WebConnection connection; @@ -85,7 +85,7 @@ public void preInit(ServerEndpointConfig serverEndpointConfig, WsServerContainer wsc, WsHandshakeRequest handshakeRequest, List negotiatedExtensionsPhase2, String subProtocol, - Transformation transformation, Map pathParameters, boolean secure) { + Transformation transformation, Map pathParameters, boolean secure) { this.serverEndpointConfig = serverEndpointConfig; this.webSocketContainer = wsc; this.handshakeRequest = handshakeRequest; @@ -117,8 +117,8 @@ ClassLoader cl = t.getContextClassLoader(); t.setContextClassLoader(applicationClassLoader); try { - wsRemoteEndpointServer = new WsRemoteEndpointImplServer(socketWrapper, upgradeInfo, webSocketContainer, - connection); + wsRemoteEndpointServer = + new WsRemoteEndpointImplServer(socketWrapper, upgradeInfo, webSocketContainer, connection); wsSession = new WsSession(wsRemoteEndpointServer, webSocketContainer, handshakeRequest.getRequestURI(), handshakeRequest.getParameterMap(), handshakeRequest.getQueryString(), handshakeRequest.getUserPrincipal(), httpSessionId, negotiatedExtensions, subProtocol, @@ -162,8 +162,8 @@ wsRemoteEndpointServer.onWritePossible(false); break; case STOP: - CloseReason cr = new CloseReason(CloseCodes.GOING_AWAY, - sm.getString("wsHttpUpgradeHandler.serverStop")); + CloseReason cr = + new CloseReason(CloseCodes.GOING_AWAY, sm.getString("wsHttpUpgradeHandler.serverStop")); try { wsSession.close(cr); } catch (IOException ioe) { diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/websocket/server/WsMappingResult.java tomcat10-10.1.52/java/org/apache/tomcat/websocket/server/WsMappingResult.java --- tomcat10-10.1.40/java/org/apache/tomcat/websocket/server/WsMappingResult.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/websocket/server/WsMappingResult.java 2026-01-23 19:33:36.000000000 +0000 @@ -23,10 +23,10 @@ class WsMappingResult { private final ServerEndpointConfig config; - private final Map pathParams; + private final Map pathParams; - WsMappingResult(ServerEndpointConfig config, Map pathParams) { + WsMappingResult(ServerEndpointConfig config, Map pathParams) { this.config = config; this.pathParams = pathParams; } @@ -37,7 +37,7 @@ } - Map getPathParams() { + Map getPathParams() { return pathParams; } } diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/websocket/server/WsPerSessionServerEndpointConfig.java tomcat10-10.1.52/java/org/apache/tomcat/websocket/server/WsPerSessionServerEndpointConfig.java --- tomcat10-10.1.40/java/org/apache/tomcat/websocket/server/WsPerSessionServerEndpointConfig.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/websocket/server/WsPerSessionServerEndpointConfig.java 2026-01-23 19:33:36.000000000 +0000 @@ -33,7 +33,7 @@ class WsPerSessionServerEndpointConfig implements ServerEndpointConfig { private final ServerEndpointConfig perEndpointConfig; - private final Map perSessionUserProperties = new ConcurrentHashMap<>(); + private final Map perSessionUserProperties = new ConcurrentHashMap<>(); WsPerSessionServerEndpointConfig(ServerEndpointConfig perEndpointConfig) { this.perEndpointConfig = perEndpointConfig; @@ -51,7 +51,7 @@ } @Override - public Map getUserProperties() { + public Map getUserProperties() { return perSessionUserProperties; } diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/websocket/server/WsRemoteEndpointImplServer.java tomcat10-10.1.52/java/org/apache/tomcat/websocket/server/WsRemoteEndpointImplServer.java --- tomcat10-10.1.40/java/org/apache/tomcat/websocket/server/WsRemoteEndpointImplServer.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/websocket/server/WsRemoteEndpointImplServer.java 2026-01-23 19:33:36.000000000 +0000 @@ -105,7 +105,9 @@ /* * Special handling is required only when all of the following are true: + * * - A close message is being sent + * * - This thread currently holds the socketWrapper lock (i.e. the thread is current processing a socket event) * * Special handling is only possible if the socketWrapper lock is a ReentrantLock (it will be by default) @@ -169,7 +171,7 @@ } } socketWrapper.write(block ? BlockingMode.BLOCK : BlockingMode.SEMI_BLOCK, timeout, TimeUnit.MILLISECONDS, - null, SocketWrapperBase.COMPLETE_WRITE_WITH_COMPLETION, new CompletionHandler() { + null, SocketWrapperBase.COMPLETE_WRITE_WITH_COMPLETION, new CompletionHandler() { @Override public void completed(Long result, Void attachment) { if (block) { @@ -226,8 +228,8 @@ socketWrapper.setWriteTimeout(timeout); socketWrapper.flush(true); handler.onResult(SENDRESULT_OK); - } catch (IOException e) { - SendResult sr = new SendResult(e); + } catch (IOException ioe) { + SendResult sr = new SendResult(ioe); handler.onResult(sr); } } diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/websocket/server/WsServerContainer.java tomcat10-10.1.52/java/org/apache/tomcat/websocket/server/WsServerContainer.java --- tomcat10-10.1.40/java/org/apache/tomcat/websocket/server/WsServerContainer.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/websocket/server/WsServerContainer.java 2026-01-23 19:33:36.000000000 +0000 @@ -66,9 +66,10 @@ private final WsWriteTimeout wsWriteTimeout = new WsWriteTimeout(); private final ServletContext servletContext; - private final Map configExactMatchMap = new ConcurrentHashMap<>(); - private final Map> configTemplateMatchMap = new ConcurrentHashMap<>(); - private final Map> authenticatedSessions = new ConcurrentHashMap<>(); + private final Map configExactMatchMap = new ConcurrentHashMap<>(); + private final Map> configTemplateMatchMap = + new ConcurrentHashMap<>(); + private final Map> authenticatedSessions = new ConcurrentHashMap<>(); private volatile boolean endpointsRegistered = false; private volatile boolean deploymentFailed = false; @@ -139,7 +140,7 @@ UriTemplate uriTemplate = new UriTemplate(path); if (uriTemplate.hasParameters()) { Integer key = Integer.valueOf(uriTemplate.getSegmentCount()); - ConcurrentSkipListMap templateMatches = configTemplateMatchMap.get(key); + ConcurrentSkipListMap templateMatches = configTemplateMatchMap.get(key); if (templateMatches == null) { // Ensure that if concurrent threads execute this block they // all end up using the same ConcurrentSkipListMap instance @@ -260,7 +261,7 @@ @Override public void upgradeHttpToWebSocket(Object httpServletRequest, Object httpServletResponse, ServerEndpointConfig sec, - Map pathParameters) throws IOException, DeploymentException { + Map pathParameters) throws IOException, DeploymentException { try { UpgradeUtil.doUpgrade(this, (HttpServletRequest) httpServletRequest, (HttpServletResponse) httpServletResponse, sec, pathParameters); @@ -289,7 +290,7 @@ // Number of segments has to match Integer key = Integer.valueOf(pathUriTemplate.getSegmentCount()); - ConcurrentSkipListMap templateMatches = configTemplateMatchMap.get(key); + ConcurrentSkipListMap templateMatches = configTemplateMatchMap.get(key); if (templateMatches == null) { // No templates with an equal number of segments so there will be @@ -300,7 +301,7 @@ // List is in alphabetical order of normalised templates. // Correct match is the first one that matches. ServerEndpointConfig sec = null; - Map pathParams = null; + Map pathParams = null; for (TemplatePathMatch templateMatch : templateMatches.values()) { pathParams = templateMatch.getUriTemplate().match(pathUriTemplate); if (pathParams != null) { @@ -383,7 +384,7 @@ for (WsSession wsSession : wsSessions) { try { wsSession.close(AUTHENTICATED_HTTP_SESSION_CLOSED); - } catch (IOException e) { + } catch (IOException ignore) { // Any IOExceptions during close will have been caught and the // onError method called. } diff -Nru tomcat10-10.1.40/java/org/apache/tomcat/websocket/server/WsWriteTimeout.java tomcat10-10.1.52/java/org/apache/tomcat/websocket/server/WsWriteTimeout.java --- tomcat10-10.1.40/java/org/apache/tomcat/websocket/server/WsWriteTimeout.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/java/org/apache/tomcat/websocket/server/WsWriteTimeout.java 2026-01-23 19:33:36.000000000 +0000 @@ -34,8 +34,8 @@ /** * Note: The comparator imposes orderings that are inconsistent with equals */ - private final Set endpoints = new ConcurrentSkipListSet<>( - Comparator.comparingLong(WsRemoteEndpointImplServer::getTimeoutExpiry)); + private final Set endpoints = + new ConcurrentSkipListSet<>(Comparator.comparingLong(WsRemoteEndpointImplServer::getTimeoutExpiry)); private final AtomicInteger count = new AtomicInteger(0); private int backgroundProcessCount = 0; private volatile int processPeriod = 1; diff -Nru tomcat10-10.1.40/modules/cxf/.gitignore tomcat10-10.1.52/modules/cxf/.gitignore --- tomcat10-10.1.40/modules/cxf/.gitignore 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/modules/cxf/.gitignore 2026-01-23 19:33:36.000000000 +0000 @@ -1,3 +1,19 @@ +# ----------------------------------------------------------------------------- +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ----------------------------------------------------------------------------- target/ pom.xml.tag pom.xml.releaseBackup diff -Nru tomcat10-10.1.40/modules/cxf/pom.xml tomcat10-10.1.52/modules/cxf/pom.xml --- tomcat10-10.1.40/modules/cxf/pom.xml 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/modules/cxf/pom.xml 2026-01-23 19:33:36.000000000 +0000 @@ -29,14 +29,14 @@ Apache CXF for Apache Tomcat CDI Apache CXF packaged for Apache Tomcat CDI - 4.1.1 + 4.1.4 jar 4.0.1 2.1.3 3.0.1 - 2.0.1 + 2.0.2 diff -Nru tomcat10-10.1.40/modules/jdbc-pool/NOTICE tomcat10-10.1.52/modules/jdbc-pool/NOTICE --- tomcat10-10.1.40/modules/jdbc-pool/NOTICE 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/modules/jdbc-pool/NOTICE 2026-01-23 19:33:36.000000000 +0000 @@ -1,5 +1,5 @@ Apache Tomcat JDBC Pool -Copyright 2008-2025 The Apache Software Foundation +Copyright 2008-2026 The Apache Software Foundation This product includes software developed at The Apache Software Foundation (http://www.apache.org/). diff -Nru tomcat10-10.1.40/modules/jdbc-pool/doc/changelog.xml tomcat10-10.1.52/modules/jdbc-pool/doc/changelog.xml --- tomcat10-10.1.40/modules/jdbc-pool/doc/changelog.xml 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/modules/jdbc-pool/doc/changelog.xml 2026-01-23 19:33:36.000000000 +0000 @@ -24,7 +24,6 @@ &project; - Filip Hanik Changelog diff -Nru tomcat10-10.1.40/modules/jdbc-pool/doc/jdbc-pool.xml tomcat10-10.1.52/modules/jdbc-pool/doc/jdbc-pool.xml --- tomcat10-10.1.40/modules/jdbc-pool/doc/jdbc-pool.xml 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/modules/jdbc-pool/doc/jdbc-pool.xml 2026-01-23 19:33:36.000000000 +0000 @@ -23,7 +23,6 @@ &project; - Filip Hanik The Tomcat JDBC Connection Pool diff -Nru tomcat10-10.1.40/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/naming/GenericNamingResourcesFactory.java tomcat10-10.1.52/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/naming/GenericNamingResourcesFactory.java --- tomcat10-10.1.40/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/naming/GenericNamingResourcesFactory.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/naming/GenericNamingResourcesFactory.java 2026-01-23 19:33:36.000000000 +0000 @@ -75,7 +75,7 @@ if (setProperty(o, param, value)) { } else { - log.debug("Property not configured["+param+"]. No setter found on["+o+"]."); + log.debug("Property not configured[" + param + "]. No setter found on[" + type + "]."); } } return o; @@ -83,8 +83,8 @@ @SuppressWarnings("null") // setPropertyMethodVoid can't be null when used private static boolean setProperty(Object o, String name, String value) { - if (log.isDebugEnabled()) { - log.debug("IntrospectionUtils: setProperty(" + + if (log.isTraceEnabled()) { + log.trace("IntrospectionUtils: setProperty(" + o.getClass() + " " + name + "=" + value + ")"); } diff -Nru tomcat10-10.1.40/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/ConnectionPool.java tomcat10-10.1.52/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/ConnectionPool.java --- tomcat10-10.1.40/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/ConnectionPool.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/ConnectionPool.java 2026-01-23 19:33:36.000000000 +0000 @@ -439,7 +439,9 @@ interceptor.setProperties(proxies[i].getProperties()); interceptor.poolClosed(this); }catch (Exception x) { - log.debug("Unable to inform interceptor of pool closure.",x); + if (log.isDebugEnabled()) { + log.debug("Unable to inform interceptor of pool closure.",x); + } } } } //closePool @@ -796,7 +798,7 @@ } catch (Exception e) { error = true; if (log.isDebugEnabled()) { - log.debug("Unable to create a new JDBC connection.", e); + log.debug("Unable to create a new JDBC connection.", e); } if (e instanceof SQLException) { throw (SQLException)e; @@ -807,7 +809,7 @@ } } finally { // con can never be null here - if (error ) { + if (error) { release(con); } con.unlock(); @@ -955,6 +957,14 @@ if (con.isDiscarded()) { return true; } + try { + if (con.isClosed()) { + return true; + } + } catch (SQLException e) { + log.warn("Unable to check if connection is closed", e); + return true; + } if (isClosed()) { return true; } @@ -1110,7 +1120,9 @@ } } //while } catch (ConcurrentModificationException e) { - log.debug("checkAbandoned failed." ,e); + if (log.isDebugEnabled()) { + log.debug("checkAbandoned failed." ,e); + } } catch (Exception e) { log.warn("checkAbandoned failed, it will be retried.",e); } @@ -1158,7 +1170,9 @@ } } //while } catch (ConcurrentModificationException e) { - log.debug("checkIdle failed." ,e); + if (log.isDebugEnabled()) { + log.debug("checkIdle failed." ,e); + } } catch (Exception e) { log.warn("checkIdle failed, it will be retried.",e); } @@ -1217,7 +1231,9 @@ } } //while } catch (ConcurrentModificationException e) { - log.debug("testAllIdle failed." ,e); + if (log.isDebugEnabled()) { + log.debug("testAllIdle failed." ,e); + } } catch (Exception e) { log.warn("testAllIdle failed, it will be retried.",e); } @@ -1616,7 +1632,7 @@ pool.testAllIdle(true); } } catch (Exception x) { - log.error("", x); + log.error(x.toString(), x); } } } diff -Nru tomcat10-10.1.40/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/DataSourceFactory.java tomcat10-10.1.52/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/DataSourceFactory.java --- tomcat10-10.1.40/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/DataSourceFactory.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/DataSourceFactory.java 2026-01-23 19:33:36.000000000 +0000 @@ -51,8 +51,6 @@ *

    • jmxEnabled - true of false, whether to register the pool with JMX.
    • *
    • fairQueue - true of false, whether the pool should sacrifice a little bit of performance for true fairness.
    • * - * @author Craig R. McClanahan - * @author Dirk Verbeeck */ public class DataSourceFactory implements ObjectFactory { private static final Log log = LogFactory.getLog(DataSourceFactory.class); @@ -571,14 +569,16 @@ log.warn("dataSourceJNDI property is configured, but local JNDI context is null."); } } catch (NamingException e) { - log.debug("The name \""+poolProperties.getDataSourceJNDI()+"\" cannot be found in the local context."); + if (log.isDebugEnabled()) { + log.debug("The name \""+poolProperties.getDataSourceJNDI()+"\" cannot be found in the local context.", e); + } } if (jndiDS==null) { try { context = new InitialContext(); jndiDS = context.lookup(poolProperties.getDataSourceJNDI()); } catch (NamingException e) { - log.warn("The name \""+poolProperties.getDataSourceJNDI()+"\" cannot be found in the InitialContext."); + log.warn("The name \""+poolProperties.getDataSourceJNDI()+"\" cannot be found in the InitialContext.", e); } } if (jndiDS!=null) { diff -Nru tomcat10-10.1.40/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/PoolProperties.java tomcat10-10.1.52/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/PoolProperties.java --- tomcat10-10.1.40/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/PoolProperties.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/PoolProperties.java 2026-01-23 19:33:36.000000000 +0000 @@ -627,9 +627,11 @@ } } buf.append(']'); - }catch (Exception x) { + } catch (Exception x) { //shouldn't happen - log.debug("toString() call failed", x); + if (log.isDebugEnabled()) { + log.debug("toString() call failed", x); + } } return buf.toString(); } @@ -939,8 +941,8 @@ if (propText != null) { try { props.load(new ByteArrayInputStream(propText.replace(';', '\n').getBytes())); - }catch (IOException x) { - throw new RuntimeException(x); + }catch (IOException ioe) { + throw new RuntimeException(ioe); } } return props; diff -Nru tomcat10-10.1.40/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/PooledConnection.java tomcat10-10.1.52/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/PooledConnection.java --- tomcat10-10.1.40/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/PooledConnection.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/PooledConnection.java 2026-01-23 19:33:36.000000000 +0000 @@ -214,7 +214,9 @@ try { this.disconnect(false); } catch (Exception x) { - log.debug("Unable to disconnect previous connection.", x); + if (log.isDebugEnabled()) { + log.debug("Unable to disconnect previous connection.", x); + } } //catch } //end if //if (poolProperties.getDataSource()==null && poolProperties.getDataSourceJNDI()!=null) { @@ -415,7 +417,7 @@ } else { xaConnection.close(); } - }catch (Exception ignore) { + } catch (Exception ignore) { if (log.isDebugEnabled()) { log.debug("Unable to close underlying SQL connection",ignore); } diff -Nru tomcat10-10.1.40/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/Validator.java tomcat10-10.1.52/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/Validator.java --- tomcat10-10.1.40/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/Validator.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/Validator.java 2026-01-23 19:33:36.000000000 +0000 @@ -20,8 +20,6 @@ /** * Interface to be implemented by custom validator classes. - * - * @author mpassell */ public interface Validator { /** diff -Nru tomcat10-10.1.40/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/interceptor/StatementDecoratorInterceptor.java tomcat10-10.1.52/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/interceptor/StatementDecoratorInterceptor.java --- tomcat10-10.1.40/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/interceptor/StatementDecoratorInterceptor.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/interceptor/StatementDecoratorInterceptor.java 2026-01-23 19:33:36.000000000 +0000 @@ -32,7 +32,6 @@ /** * Implementation of JdbcInterceptor that proxies resultSets and statements. - * @author Guillermo Fernandes */ public class StatementDecoratorInterceptor extends AbstractCreateStatementInterceptor { diff -Nru tomcat10-10.1.40/modules/jdbc-pool/src/test/java/org/apache/tomcat/jdbc/test/TestValidation.java tomcat10-10.1.52/modules/jdbc-pool/src/test/java/org/apache/tomcat/jdbc/test/TestValidation.java --- tomcat10-10.1.40/modules/jdbc-pool/src/test/java/org/apache/tomcat/jdbc/test/TestValidation.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/modules/jdbc-pool/src/test/java/org/apache/tomcat/jdbc/test/TestValidation.java 2026-01-23 19:33:36.000000000 +0000 @@ -33,6 +33,8 @@ import org.junit.Before; import org.junit.Test; +import org.apache.tomcat.jdbc.pool.ConnectionPool; + public class TestValidation extends DefaultTestCase { public static final Boolean WITHAUTOCOMMIT = Boolean.TRUE; @@ -142,6 +144,27 @@ } @Test + public void returnClosedConnection() throws SQLException { + ConnectionPool pool = datasource.createPool(); + pool.resetStats(); + Assert.assertFalse(datasource.getPoolProperties().isTestOnBorrow()); + Assert.assertFalse(datasource.getPoolProperties().isTestOnReturn()); + Assert.assertFalse(datasource.getPoolProperties().isTestWhileIdle()); + try (Connection connection = datasource.getConnection()) { + Assert.assertEquals("size", 1, pool.getSize()); + Connection realConnection = ((PooledConnection) connection).getConnection(); + Assert.assertNotSame(connection, realConnection); + realConnection.close(); + Assert.assertTrue(realConnection.isClosed()); + Assert.assertFalse(connection.isClosed()); + } + Assert.assertEquals("borrowed", 1, pool.getBorrowedCount()); + Assert.assertEquals("returned", 1, pool.getReturnedCount()); + Assert.assertEquals("released", 1, pool.getReleasedCount()); + Assert.assertEquals("size", 0, pool.getSize()); + } + + @Test public void testOnConnectValidationSuccessWithValidationQueryAndAutoCommitEnabled() throws SQLException { checkOnConnectValidationWithOutcome(ValidationOutcome.SUCCESS, WITHVALIDATIONQUERY, WITHAUTOCOMMIT); } @@ -644,4 +667,4 @@ } } -} \ No newline at end of file +} diff -Nru tomcat10-10.1.40/modules/jdbc-pool/src/test/java/org/apache/tomcat/jdbc/test/driver/Connection.java tomcat10-10.1.52/modules/jdbc-pool/src/test/java/org/apache/tomcat/jdbc/test/driver/Connection.java --- tomcat10-10.1.40/modules/jdbc-pool/src/test/java/org/apache/tomcat/jdbc/test/driver/Connection.java 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/modules/jdbc-pool/src/test/java/org/apache/tomcat/jdbc/test/driver/Connection.java 2026-01-23 19:33:36.000000000 +0000 @@ -38,6 +38,7 @@ public class Connection implements java.sql.Connection { Properties info; + private boolean closed = false; public Connection(Properties info) { this.info = info; @@ -57,6 +58,7 @@ @Override public void close() throws SQLException { + closed = true; Driver.disconnectCount.incrementAndGet(); } @@ -156,7 +158,7 @@ @Override public boolean isClosed() throws SQLException { - return false; + return closed; } @Override diff -Nru tomcat10-10.1.40/modules/owb/.gitignore tomcat10-10.1.52/modules/owb/.gitignore --- tomcat10-10.1.40/modules/owb/.gitignore 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/modules/owb/.gitignore 2026-01-23 19:33:36.000000000 +0000 @@ -1,3 +1,19 @@ +# ----------------------------------------------------------------------------- +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ----------------------------------------------------------------------------- target/ pom.xml.tag pom.xml.releaseBackup diff -Nru tomcat10-10.1.40/modules/stuffed/.gitignore tomcat10-10.1.52/modules/stuffed/.gitignore --- tomcat10-10.1.40/modules/stuffed/.gitignore 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/modules/stuffed/.gitignore 2026-01-23 19:33:36.000000000 +0000 @@ -1 +1,17 @@ +# ----------------------------------------------------------------------------- +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ----------------------------------------------------------------------------- target/ diff -Nru tomcat10-10.1.40/modules/stuffed/conf/.gitignore tomcat10-10.1.52/modules/stuffed/conf/.gitignore --- tomcat10-10.1.40/modules/stuffed/conf/.gitignore 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/modules/stuffed/conf/.gitignore 2026-01-23 19:33:36.000000000 +0000 @@ -1,3 +1,19 @@ +# ----------------------------------------------------------------------------- +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ----------------------------------------------------------------------------- # Ignore everything in this directory * # Except this file diff -Nru tomcat10-10.1.40/modules/stuffed/webapps/.gitignore tomcat10-10.1.52/modules/stuffed/webapps/.gitignore --- tomcat10-10.1.40/modules/stuffed/webapps/.gitignore 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/modules/stuffed/webapps/.gitignore 2026-01-23 19:33:36.000000000 +0000 @@ -1,3 +1,19 @@ +# ----------------------------------------------------------------------------- +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ----------------------------------------------------------------------------- # Ignore everything in this directory * # Except this file diff -Nru tomcat10-10.1.40/res/bnd/tomcat-embed-core.jar.tmp.bnd tomcat10-10.1.52/res/bnd/tomcat-embed-core.jar.tmp.bnd --- tomcat10-10.1.40/res/bnd/tomcat-embed-core.jar.tmp.bnd 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/res/bnd/tomcat-embed-core.jar.tmp.bnd 2026-01-23 19:33:36.000000000 +0000 @@ -64,6 +64,7 @@ org.apache.tomcat.util.codec.binary,\ org.apache.tomcat.util.collections,\ org.apache.tomcat.util.compat,\ + org.apache.tomcat.util.concurrent,\ org.apache.tomcat.util.descriptor,\ org.apache.tomcat.util.descriptor.tagplugin,\ org.apache.tomcat.util.descriptor.web,\ diff -Nru tomcat10-10.1.40/res/bnd/tomcat-util.jar.tmp.bnd tomcat10-10.1.52/res/bnd/tomcat-util.jar.tmp.bnd --- tomcat10-10.1.40/res/bnd/tomcat-util.jar.tmp.bnd 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/res/bnd/tomcat-util.jar.tmp.bnd 2026-01-23 19:33:36.000000000 +0000 @@ -23,6 +23,7 @@ org.apache.tomcat.util.codec.binary,\ org.apache.tomcat.util.collections,\ org.apache.tomcat.util.compat,\ + org.apache.tomcat.util.concurrent,\ org.apache.tomcat.util.file,\ org.apache.tomcat.util.res,\ org.apache.tomcat.util.security,\ diff -Nru tomcat10-10.1.40/res/checkstyle/header-al2.txt tomcat10-10.1.52/res/checkstyle/header-al2.txt --- tomcat10-10.1.40/res/checkstyle/header-al2.txt 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/res/checkstyle/header-al2.txt 2026-01-23 19:33:36.000000000 +0000 @@ -9,7 +9,7 @@ ^(rem)?\W*\(the "License"\); you may not use this file except in compliance with$ ^(rem)?\W*the License\. You may obtain a copy of the License at$ ^(rem)?\W*$ -^(rem)?\W*http://www.apache.org/licenses/LICENSE-2\.0$ +^(rem)?\W*http(s)?://www.apache.org/licenses/LICENSE-2\.0$ ^(rem)?\W*$ ^(rem)?\W*Unless required by applicable law or agreed to in writing, software$ ^(rem)?\W*distributed under the License is distributed on an "AS IS" BASIS,$ diff -Nru tomcat10-10.1.40/res/checkstyle/org-import-control.xml tomcat10-10.1.52/res/checkstyle/org-import-control.xml --- tomcat10-10.1.40/res/checkstyle/org-import-control.xml 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/res/checkstyle/org-import-control.xml 2026-01-23 19:33:36.000000000 +0000 @@ -128,6 +128,7 @@ + @@ -193,4 +194,4 @@ - \ No newline at end of file + diff -Nru tomcat10-10.1.40/res/ide-support/eclipse/formatting-asf-tomcat.xml tomcat10-10.1.52/res/ide-support/eclipse/formatting-asf-tomcat.xml --- tomcat10-10.1.40/res/ide-support/eclipse/formatting-asf-tomcat.xml 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/res/ide-support/eclipse/formatting-asf-tomcat.xml 2026-01-23 19:33:36.000000000 +0000 @@ -166,7 +166,7 @@ - + @@ -181,6 +181,7 @@ + @@ -215,6 +216,7 @@ + @@ -295,6 +297,7 @@ + @@ -325,6 +328,7 @@ + diff -Nru tomcat10-10.1.40/res/ide-support/idea/codeStyles/Project.xml tomcat10-10.1.52/res/ide-support/idea/codeStyles/Project.xml --- tomcat10-10.1.40/res/ide-support/idea/codeStyles/Project.xml 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/res/ide-support/idea/codeStyles/Project.xml 2026-01-23 19:33:36.000000000 +0000 @@ -17,9 +17,102 @@ --> +

    Request Values
    -
    +

    diff -Nru tomcat10-10.1.40/webapps/manager/WEB-INF/jsp/connectorCiphers.jsp tomcat10-10.1.52/webapps/manager/WEB-INF/jsp/connectorCiphers.jsp --- tomcat10-10.1.40/webapps/manager/WEB-INF/jsp/connectorCiphers.jsp 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/webapps/manager/WEB-INF/jsp/connectorCiphers.jsp 2026-01-23 19:33:36.000000000 +0000 @@ -32,9 +32,10 @@ - + Configured ciphers per Connector +

    Configured ciphers per Connector

    @@ -68,7 +69,7 @@ - +

    diff -Nru tomcat10-10.1.40/webapps/manager/WEB-INF/jsp/connectorTrustedCerts.jsp tomcat10-10.1.52/webapps/manager/WEB-INF/jsp/connectorTrustedCerts.jsp --- tomcat10-10.1.40/webapps/manager/WEB-INF/jsp/connectorTrustedCerts.jsp 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/webapps/manager/WEB-INF/jsp/connectorTrustedCerts.jsp 2026-01-23 19:33:36.000000000 +0000 @@ -32,9 +32,10 @@ - + Trusted certificates per Connector +

    Trusted certificates per Connector

    @@ -68,7 +69,7 @@ - +

    diff -Nru tomcat10-10.1.40/webapps/manager/WEB-INF/jsp/sessionDetail.jsp tomcat10-10.1.52/webapps/manager/WEB-INF/jsp/sessionDetail.jsp --- tomcat10-10.1.40/webapps/manager/WEB-INF/jsp/sessionDetail.jsp 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/webapps/manager/WEB-INF/jsp/sessionDetail.jsp 2026-01-23 19:33:36.000000000 +0000 @@ -50,10 +50,10 @@ - - + Sessions Administration: details for <%= currentSessionId %> + <% if (currentHttpSession == null) { %> @@ -100,7 +100,7 @@ - +
    @@ -147,7 +147,7 @@ %> - +
    @@ -173,7 +173,7 @@ <% } // endif%> - +

    diff -Nru tomcat10-10.1.40/webapps/manager/WEB-INF/jsp/sessionsList.jsp tomcat10-10.1.52/webapps/manager/WEB-INF/jsp/sessionsList.jsp --- tomcat10-10.1.40/webapps/manager/WEB-INF/jsp/sessionsList.jsp 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/webapps/manager/WEB-INF/jsp/sessionsList.jsp 2026-01-23 19:33:36.000000000 +0000 @@ -41,10 +41,10 @@ - - + Sessions Administration for <%= JspHelper.escapeXml(cn.getDisplayName()) %> +

    Sessions Administration for <%= JspHelper.escapeXml(cn.getDisplayName()) %>

    @@ -58,7 +58,7 @@
    <%= JspHelper.escapeXml(request.getAttribute("error")) %>
    <%= JspHelper.escapeXml(request.getAttribute("message")) %>
    - +
    Active HttpSessions information "/> @@ -146,7 +146,7 @@
    -
    +

    diff -Nru tomcat10-10.1.40/webapps/manager/images/asf-logo.svg tomcat10-10.1.52/webapps/manager/images/asf-logo.svg --- tomcat10-10.1.40/webapps/manager/images/asf-logo.svg 2025-04-01 18:12:59.000000000 +0000 +++ tomcat10-10.1.52/webapps/manager/images/asf-logo.svg 2026-01-23 19:33:36.000000000 +0000 @@ -1,4 +1,4 @@ - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file Binary files /srv/release.debian.org/tmp/V7LJZ_rShX/tomcat10-10.1.40/webapps/manager/images/favicon.ico and /srv/release.debian.org/tmp/dJm1BNZuE4/tomcat10-10.1.52/webapps/manager/images/favicon.ico differ