This is an automated email from the ASF dual-hosted git repository. rmaucher pushed a commit to branch main in repository https://gitbox.apache.org/repos/asf/tomcat.git
commit d9a86ce59faf8f44ad30d6c1710246457e99ca3b Author: opencode <[email protected]> AuthorDate: Sat Oct 31 15:34:28 2026 +0100 Localize the pool's exception and log messages The pool carried its diagnostics as string literals at each throw and log call, leaving its reporting path untranslatable while every other Tomcat component reads its messages from a LocalStrings bundle. Add org.apache.tomcat.jdbc.pool.util.MessageFactory, modeled on org.apache.el.util.MessageFactory, and route every exception message and every info, warn and error log message through it. Debug and trace messages stay literals, as elsewhere in Tomcat, and a message that carries nothing but a passed-through exception's own text has nothing to localize. The keys follow the main tree's convention of lowercaseClassName.camelCaseKey, and the default bundle keeps the English text exactly as it was: pool code scans the borrow-timeout message for NoWait, and the tests assert the slow-query report's format, so the wording is load-bearing. Those tests pass unchanged. The bundle sits with the sources, like the LocalStrings files elsewhere in the tree. The Maven build gains a resources section so the bundle reaches the test class path and the jars, and the module's Ant build copies it into the classes directory so the built tomcat-jdbc.jar ships it too. One blank line goes with them from a test's javadoc, where the checkstyle run this change passes required the comment's content to start beside the opening delimiter. --- modules/jdbc-pool/build.xml | 7 + modules/jdbc-pool/pom.xml | 11 ++ .../jdbc/naming/GenericNamingResourcesFactory.java | 36 ++-- .../apache/tomcat/jdbc/pool/ClassLoaderUtil.java | 6 +- .../apache/tomcat/jdbc/pool/ConnectionPool.java | 117 ++++++------ .../org/apache/tomcat/jdbc/pool/DataSource.java | 8 +- .../apache/tomcat/jdbc/pool/DataSourceFactory.java | 35 ++-- .../apache/tomcat/jdbc/pool/DataSourceProxy.java | 34 ++-- .../jdbc/pool/DisposableConnectionFacade.java | 4 +- .../apache/tomcat/jdbc/pool/FairBlockingQueue.java | 31 ++-- .../apache/tomcat/jdbc/pool/PoolProperties.java | 17 +- .../apache/tomcat/jdbc/pool/PooledConnection.java | 52 +++--- .../apache/tomcat/jdbc/pool/ProxyConnection.java | 17 +- .../apache/tomcat/jdbc/pool/StatementFacade.java | 11 +- .../org/apache/tomcat/jdbc/pool/TrapException.java | 8 +- .../org/apache/tomcat/jdbc/pool/XADataSource.java | 18 +- .../AbstractCreateStatementInterceptor.java | 12 +- .../jdbc/pool/interceptor/AbstractQueryReport.java | 17 +- .../jdbc/pool/interceptor/ConnectionState.java | 23 ++- .../pool/interceptor/QueryTimeoutInterceptor.java | 13 +- .../jdbc/pool/interceptor/ResetAbandonedTimer.java | 12 +- .../jdbc/pool/interceptor/SlowQueryReport.java | 11 +- .../jdbc/pool/interceptor/SlowQueryReportJmx.java | 21 +-- .../jdbc/pool/interceptor/StatementCache.java | 7 +- .../interceptor/StatementDecoratorInterceptor.java | 3 +- .../jdbc/pool/interceptor/StatementFinalizer.java | 5 +- .../tomcat/jdbc/pool/jmx/ConnectionPool.java | 5 +- .../org/apache/tomcat/jdbc/pool/jmx/JmxUtil.java | 5 +- .../tomcat/jdbc/pool/util/LocalStrings.properties | 199 +++++++++++++++++++++ .../tomcat/jdbc/pool/util/MessageFactory.java | 116 ++++++++++++ .../interceptor/TestSlowQueryReportLogging.java | 1 - 31 files changed, 591 insertions(+), 271 deletions(-) diff --git a/modules/jdbc-pool/build.xml b/modules/jdbc-pool/build.xml index 9a10965c59..f3a13345d9 100644 --- a/modules/jdbc-pool/build.xml +++ b/modules/jdbc-pool/build.xml @@ -154,6 +154,13 @@ <include name="org/apache/tomcat/jdbc/**" /> </javac> + <!-- Localized messages are stored with the sources --> + <copy todir="${tomcat.classes}"> + <fileset dir="${basedir}/src/main/java"> + <include name="org/apache/tomcat/jdbc/**/*.properties" /> + </fileset> + </copy> + <!-- connection pool JAR File --> <jar jarfile="${tomcat-jdbc.jar}" update="true" diff --git a/modules/jdbc-pool/pom.xml b/modules/jdbc-pool/pom.xml index ef1cde32af..c06eb6ed03 100644 --- a/modules/jdbc-pool/pom.xml +++ b/modules/jdbc-pool/pom.xml @@ -81,6 +81,17 @@ </dependency> </dependencies> <build> + <resources> + <!-- Localized messages are stored with the sources. Copy them, like + the Ant build, to make them available on the runtime and test + class paths. --> + <resource> + <directory>src/main/java</directory> + <includes> + <include>**/*.properties</include> + </includes> + </resource> + </resources> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> diff --git a/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/naming/GenericNamingResourcesFactory.java b/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/naming/GenericNamingResourcesFactory.java index 6ab84058e4..294ec4c4e6 100644 --- a/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/naming/GenericNamingResourcesFactory.java +++ b/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/naming/GenericNamingResourcesFactory.java @@ -37,6 +37,7 @@ import javax.naming.spi.ObjectFactory; import org.apache.juli.logging.Log; import org.apache.juli.logging.LogFactory; import org.apache.tomcat.jdbc.pool.ClassLoaderUtil; +import org.apache.tomcat.jdbc.pool.util.MessageFactory; /** * Simple way of configuring generic resources by using reflection. Example usage: @@ -82,8 +83,8 @@ public class GenericNamingResourcesFactory implements ObjectFactory { String type = ref.getClassName(); if (type == null || type.isEmpty()) { - throw new NamingException("No resource type (the \"type\" attribute) is defined for reference [" + name + - "]; GenericNamingResourcesFactory needs the class of the " + "object to create."); + throw new NamingException( + MessageFactory.get("genericNamingResourcesFactory.noResourceType", name)); } Object o; try { @@ -91,7 +92,8 @@ public class GenericNamingResourcesFactory implements ObjectFactory { Thread.currentThread().getContextClassLoader()); o = clazz.getConstructor().newInstance(); } catch (ClassNotFoundException e) { - NamingException ne = new NamingException("Class [" + type + "] of reference [" + name + "] was not found"); + NamingException ne = + new NamingException(MessageFactory.get("genericNamingResourcesFactory.classNotFound", type, name)); ne.setRootCause(e); throw ne; } catch (InvocationTargetException e) { @@ -103,16 +105,17 @@ public class GenericNamingResourcesFactory implements ObjectFactory { if (cause instanceof VirtualMachineError) { throw (VirtualMachineError) cause; } - NamingException ne = new NamingException("The constructor of class [" + type + "] of reference [" + name + - "] threw an exception and the object cannot be created"); + NamingException ne = + new NamingException(MessageFactory.get("genericNamingResourcesFactory.constructorThrew", type, name)); ne.setRootCause(e); throw ne; } catch (ReflectiveOperationException e) { // No public no-arg constructor (NoSuchMethodException), or the // class cannot be instantiated (abstract, interface, illegal // access). - NamingException ne = new NamingException("Class [" + type + "] of reference [" + name + - "] has no usable public no-argument constructor and " + "cannot be created by this factory"); + NamingException ne = + new NamingException(MessageFactory.get("genericNamingResourcesFactory.noUsableConstructor", + type, name)); ne.setRootCause(e); throw ne; } @@ -129,8 +132,7 @@ public class GenericNamingResourcesFactory implements ObjectFactory { value = addr.getContent().toString(); } if (!setProperty(o, param, value)) { - log.warn("Property [" + param + "] was not applied to [" + type + "]: no usable setter found, or the " + - "configured value could not be applied."); + log.warn(MessageFactory.get("genericNamingResourcesFactory.propertyNotApplied", param, type)); } } return o; @@ -279,14 +281,14 @@ public class GenericNamingResourcesFactory implements ObjectFactory { } } catch (IllegalArgumentException ex2) { - log.warn("Unable to set property [" + name + "] with value [" + value + "] on [" + o.getClass().getName() + - "]", ex2); + log.warn(MessageFactory.get("genericNamingResourcesFactory.unableToSetProperty", + name, value, o.getClass().getName()), ex2); } catch (SecurityException ex1) { - log.warn("SecurityException setting property [" + name + "] with value [" + value + "] on [" + - o.getClass().getName() + "]", ex1); + log.warn(MessageFactory.get("genericNamingResourcesFactory.securityExceptionSettingProperty", + name, value, o.getClass().getName()), ex1); } catch (IllegalAccessException iae) { - log.warn("IllegalAccessException setting property [" + name + "] with value [" + value + "] on [" + - o.getClass().getName() + "]", iae); + log.warn(MessageFactory.get("genericNamingResourcesFactory.illegalAccessExceptionSettingProperty", + name, value, o.getClass().getName()), iae); } catch (InvocationTargetException ie) { // In the spirit of ExceptionUtils.handleThrowable(), which is not // available to tomcat-jdbc.jar: propagate the fatal @@ -295,8 +297,8 @@ public class GenericNamingResourcesFactory implements ObjectFactory { if (cause instanceof VirtualMachineError) { throw (VirtualMachineError) cause; } - log.warn("Setter for property [" + name + "] with value [" + value + "] threw an exception on [" + - o.getClass().getName() + "]", ie); + log.warn(MessageFactory.get("genericNamingResourcesFactory.setterThrew", + name, value, o.getClass().getName()), ie); } return false; } diff --git a/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/ClassLoaderUtil.java b/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/ClassLoaderUtil.java index 92e796f150..e425b2d60a 100644 --- a/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/ClassLoaderUtil.java +++ b/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/ClassLoaderUtil.java @@ -19,6 +19,7 @@ package org.apache.tomcat.jdbc.pool; import org.apache.juli.logging.Log; import org.apache.juli.logging.LogFactory; +import org.apache.tomcat.jdbc.pool.util.MessageFactory; /** * Utility class for loading classes using multiple class loaders. @@ -56,7 +57,7 @@ public class ClassLoaderUtil { } return Class.forName(className, true, cl); } else { - throw new ClassNotFoundException("Classloader is null"); + throw new ClassNotFoundException(MessageFactory.get("classLoaderUtil.classLoaderNull")); } } catch (ClassNotFoundException x) { last = x; @@ -72,7 +73,8 @@ public class ClassLoaderUtil { break; } } - throw new ClassNotFoundException("Unable to load class: " + className + " from " + errorMsg, last); + throw new ClassNotFoundException(MessageFactory.get("classLoaderUtil.classLoadFailed", className, errorMsg), + last); } diff --git a/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/ConnectionPool.java b/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/ConnectionPool.java index 6d0ea2b268..244a884f0a 100644 --- a/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/ConnectionPool.java +++ b/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/ConnectionPool.java @@ -50,6 +50,7 @@ import org.apache.juli.logging.Log; import org.apache.juli.logging.LogFactory; import org.apache.tomcat.jdbc.pool.interceptor.QueryTimeoutInterceptor; import org.apache.tomcat.jdbc.pool.interceptor.StatementCache; +import org.apache.tomcat.jdbc.pool.util.MessageFactory; /** * Implementation of simple connection pool. The ConnectionPool uses a {@link PoolProperties} object for storing all the @@ -211,12 +212,11 @@ public class ConnectionPool { // future will never hand out a connection. Reject the borrow the // same way a synchronous borrow on a closed pool does, rather than // handing out a future that only ever fails with a cancellation. - throw new SQLException("Connection pool closed."); + throw new SQLException(MessageFactory.get("connectionPool.poolClosed")); } return new ConnectionFuture(pcf); } else { - throw new SQLException( - "Connection pool is misconfigured, doesn't support async retrieval. Set the 'fair' property to 'true'"); + throw new SQLException(MessageFactory.get("connectionPool.poolMisconfigured")); } } @@ -365,7 +365,7 @@ public class ConnectionPool { try { con.createMBean(); } catch (Exception x) { - SQLException sx = new SQLException("Unable to register the pooled connection MBean."); + SQLException sx = new SQLException(MessageFactory.get("connectionPool.unableToRegisterMBean")); sx.initCause(x); // Nothing has been done to the connection, it can go back to the pool abandonSetup(con, sx, false); @@ -386,7 +386,7 @@ public class ConnectionPool { // Configure the last one to be held by the connection handler = interceptor; } catch (Exception x) { - SQLException sx = new SQLException("Unable to instantiate interceptor chain."); + SQLException sx = new SQLException(MessageFactory.get("connectionPool.unableToInstantiateInterceptorChain")); sx.initCause(x); // Nothing has been done to the connection, it can go back to the pool abandonSetup(con, sx, false); @@ -404,8 +404,8 @@ public class ConnectionPool { next = next.getNext(); } } catch (Exception x) { - SQLException sx = new SQLException( - "Unable to reset interceptor [" + (next != null ? next.getClass().getName() : "unknown") + "]."); + SQLException sx = new SQLException(MessageFactory.get("connectionPool.unableToResetInterceptor", + (next != null ? next.getClass().getName() : "unknown"))); sx.initCause(x); // The state of the connection is unknown, discard it so its partially reset chain is dropped abandonSetup(con, sx, true); @@ -500,10 +500,10 @@ public class ConnectionPool { try { hint.invoke(connection); } catch (InvocationTargetException x) { - log.warn("The request boundary hint [" + hint.getName() + "] was refused by the driver", + log.warn(MessageFactory.get("connectionPool.requestHintRefused", hint.getName()), x.getTargetException()); } catch (ReflectiveOperationException | IllegalArgumentException x) { - log.warn("Unable to send the request boundary hint [" + hint.getName() + "]", x); + log.warn(MessageFactory.get("connectionPool.unableToSendRequestHint", hint.getName()), x); } } @@ -598,7 +598,7 @@ public class ConnectionPool { } catch (Throwable x) { // One failing connection must not leave the // remaining idle and busy connections undisconnected - log.warn("Unable to close pooled connection.", x); + log.warn(MessageFactory.get("connectionPool.unableToClosePooledConnection"), x); } if (!pool.isEmpty()) { con = pool.poll(1000, TimeUnit.MILLISECONDS); @@ -685,7 +685,7 @@ public class ConnectionPool { interceptor.setProperties(proxies[i].getProperties()); interceptor.poolStarted(this); } catch (Exception x) { - log.error("Unable to inform interceptor of pool start.", x); + log.error(MessageFactory.get("connectionPool.unableToInformInterceptorOfPoolStart"), x); org.apache.tomcat.jdbc.pool.jmx.ConnectionPool jmx = jmxPool; if (jmx != null) { jmx.notify(org.apache.tomcat.jdbc.pool.jmx.ConnectionPool.NOTIFY_INIT, getStackTrace(x)); @@ -710,7 +710,7 @@ public class ConnectionPool { } } catch (SQLException x) { - log.error("Unable to create initial connections of pool.", x); + log.error(MessageFactory.get("connectionPool.unableToCreateInitialConnections"), x); if (!poolProperties.isIgnoreExceptionOnPreLoad()) { org.apache.tomcat.jdbc.pool.jmx.ConnectionPool jmx = jmxPool; if (jmx != null) { @@ -768,11 +768,7 @@ public class ConnectionPool { } } if (firstCache >= 0 && lastTimeout > firstCache) { - log.warn("The [StatementCache] interceptor is configured before [QueryTimeoutInterceptor]. " - + "A statement cache hit is answered by the cache without invoking the timeout interceptor, " - + "and a statement recycled into the cache carries no timeout, so cached statements run " - + "without a query timeout. List QueryTimeoutInterceptor before StatementCache in the " - + "jdbcInterceptors configuration."); + log.warn(MessageFactory.get("connectionPool.statementCacheBeforeQueryTimeout")); } } @@ -785,29 +781,28 @@ public class ConnectionPool { public void checkPoolConfiguration(PoolConfiguration properties) { // Make sure the pool is properly configured if (properties.getMaxActive() < 1) { - log.warn("maxActive is smaller than 1, setting maxActive to: " + PoolProperties.DEFAULT_MAX_ACTIVE); + log.warn(MessageFactory.get("connectionPool.maxActiveTooSmall", PoolProperties.DEFAULT_MAX_ACTIVE)); properties.setMaxActive(PoolProperties.DEFAULT_MAX_ACTIVE); } if (properties.getMaxActive() < properties.getInitialSize()) { - log.warn("initialSize is larger than maxActive, setting initialSize to: " + properties.getMaxActive()); + log.warn(MessageFactory.get("connectionPool.initialSizeTooLarge", properties.getMaxActive())); properties.setInitialSize(properties.getMaxActive()); } if (properties.getMinIdle() > properties.getMaxActive()) { - log.warn("minIdle is larger than maxActive, setting minIdle to: " + properties.getMaxActive()); + log.warn(MessageFactory.get("connectionPool.minIdleTooLarge", properties.getMaxActive())); properties.setMinIdle(properties.getMaxActive()); } if (properties.getMaxIdle() > properties.getMaxActive()) { - log.warn("maxIdle is larger than maxActive, setting maxIdle to: " + properties.getMaxActive()); + log.warn(MessageFactory.get("connectionPool.maxIdleTooLarge", properties.getMaxActive())); properties.setMaxIdle(properties.getMaxActive()); } if (properties.getMaxIdle() < properties.getMinIdle()) { - log.warn("maxIdle is smaller than minIdle, setting maxIdle to: " + properties.getMinIdle()); + log.warn(MessageFactory.get("connectionPool.maxIdleTooSmall", properties.getMinIdle())); properties.setMaxIdle(properties.getMinIdle()); } if (properties.getMaxAge() > 0 && properties.isPoolSweeperEnabled() && properties.getTimeBetweenEvictionRunsMillis() > properties.getMaxAge()) { - log.warn("timeBetweenEvictionRunsMillis is larger than maxAge, setting timeBetweenEvictionRunsMillis to: " + - properties.getMaxAge()); + log.warn(MessageFactory.get("connectionPool.timeBetweenEvictionRunsTooLarge", properties.getMaxAge())); properties.setTimeBetweenEvictionRunsMillis((int) properties.getMaxAge()); } } @@ -856,7 +851,7 @@ public class ConnectionPool { con.lock(); String trace = con.getStackTrace(); if (getPoolProperties().isLogAbandoned()) { - log.warn("Connection has been abandoned " + con + ":" + trace); + log.warn(MessageFactory.get("connectionPool.connectionAbandoned", con, trace)); } org.apache.tomcat.jdbc.pool.jmx.ConnectionPool jmx = jmxPool; if (jmx != null) { @@ -888,8 +883,8 @@ public class ConnectionPool { con.lock(); String trace = con.getStackTrace(); if (getPoolProperties().isLogAbandoned()) { - log.warn("Connection has been marked suspect, possibly abandoned " + con + "[" + - (System.currentTimeMillis() - con.getTimestamp()) + " ms.]:" + trace); + log.warn(MessageFactory.get("connectionPool.connectionSuspect", + con, (System.currentTimeMillis() - con.getTimestamp()), trace)); } org.apache.tomcat.jdbc.pool.jmx.ConnectionPool jmx = jmxPool; if (jmx != null) { @@ -940,8 +935,7 @@ public class ConnectionPool { // queue the placeholder while it is open. if (destroyed && !isClosed() && waitcount.get() > 0) { if (!idle.offer(create(true))) { - log.warn("Failed to add a new connection to the pool after releasing a connection " + - "when at least one thread was waiting for a connection."); + log.warn(MessageFactory.get("connectionPool.failedToAddNewConnection")); } } } @@ -961,7 +955,7 @@ public class ConnectionPool { private PooledConnection borrowConnection(int wait, String username, String password) throws SQLException { if (isClosed()) { - throw new SQLException("Connection pool closed."); + throw new SQLException(MessageFactory.get("connectionPool.poolClosed")); } // Get the current time stamp @@ -1029,7 +1023,7 @@ public class ConnectionPool { if (getPoolProperties().getPropagateInterruptState()) { Thread.currentThread().interrupt(); } - SQLException sx = new SQLException("Pool wait interrupted."); + SQLException sx = new SQLException(MessageFactory.get("connectionPool.poolWaitInterrupted")); sx.initCause(ex); throw sx; } finally { @@ -1040,9 +1034,8 @@ public class ConnectionPool { if (jmx != null) { jmx.notify(org.apache.tomcat.jdbc.pool.jmx.ConnectionPool.POOL_EMPTY, "Pool empty - no wait."); } - throw new PoolExhaustedException("[" + Thread.currentThread().getName() + "] " + - "NoWait: Pool empty. Unable to fetch a connection, none available[" + busy.size() + - " in use]."); + throw new PoolExhaustedException(MessageFactory.get("connectionPool.poolEmptyNoWait", + Thread.currentThread().getName(), busy.size())); } // We didn't get a connection, lets see if we timed out if (con == null) { @@ -1052,10 +1045,9 @@ public class ConnectionPool { jmx.notify(org.apache.tomcat.jdbc.pool.jmx.ConnectionPool.POOL_EMPTY, "Pool empty - timeout."); } - throw new PoolExhaustedException("[" + Thread.currentThread().getName() + "] " + - "Timeout: Pool empty. Unable to fetch a connection in " + (maxWait / 1000) + - " seconds, none available[size:" + size.get() + "; busy:" + busy.size() + "; idle:" + - idle.size() + "; lastwait:" + timetowait + "]."); + throw new PoolExhaustedException(MessageFactory.get("connectionPool.poolEmptyTimeout", + Thread.currentThread().getName(), (maxWait / 1000), size.get(), busy.size(), + idle.size(), timetowait)); } else { // No timeout, lets try again continue; @@ -1096,7 +1088,7 @@ public class ConnectionPool { // being created; the shutdown drain has already passed over // the queues, so neither hand the connection out nor register // it in busy - the error path below disconnects it - throw new SQLException("Connection pool closed."); + throw new SQLException(MessageFactory.get("connectionPool.poolClosed")); } if (con.validate(PooledConnection.VALIDATE_INIT)) { // No need to lock a new one, its not contented @@ -1112,7 +1104,7 @@ public class ConnectionPool { } else { // Validation failed, make sure we disconnect // and clean up - throw new SQLException("Validation Query Failed, enable logValidationErrors for more details."); + throw new SQLException(MessageFactory.get("connectionPool.validationQueryFailed")); } } catch (Exception e) { error = true; @@ -1205,7 +1197,7 @@ public class ConnectionPool { return con; } else { // Validation failed. - throw new SQLException("Failed to validate a newly established connection."); + throw new SQLException(MessageFactory.get("connectionPool.failedToValidateNewConnection")); } } catch (Exception x) { release(con); @@ -1270,7 +1262,7 @@ public class ConnectionPool { } return true; } catch (SQLException x) { - log.warn("Unable to terminate transaction, connection will be closed.", x); + log.warn(MessageFactory.get("connectionPool.unableToTerminateTransaction"), x); return false; } @@ -1296,7 +1288,7 @@ public class ConnectionPool { return true; } } catch (SQLException e) { - log.warn("Unable to check if connection is closed", e); + log.warn(MessageFactory.get("connectionPool.unableToCheckClosed"), e); return true; } if (isClosed()) { @@ -1342,7 +1334,7 @@ public class ConnectionPool { return false; } } catch (Exception e) { - log.error("Failed to re-connect connection [" + this + "] that expired because of maxAge", e); + log.error(MessageFactory.get("connectionPool.failedToReconnectExpired", this), e); return false; } } @@ -1370,9 +1362,8 @@ public class ConnectionPool { con.lock(); if (con.isSuspect()) { if (poolProperties.isLogAbandoned() && log.isInfoEnabled()) { - log.info("Connection(" + con + ") that has been marked suspect was returned." + - " The processing time is " + (System.currentTimeMillis() - con.getTimestamp()) + - " ms."); + log.info(MessageFactory.get("connectionPool.suspectConnectionReturned", + con, (System.currentTimeMillis() - con.getTimestamp()))); } org.apache.tomcat.jdbc.pool.jmx.ConnectionPool jmx = jmxPool; if (jmx != null) { @@ -1430,7 +1421,7 @@ public class ConnectionPool { // the driver that failed. con.setDiscarded(true); release(con); - log.warn("Unable to return connection [" + con + "] to the pool, closing it.", x); + log.warn(MessageFactory.get("connectionPool.unableToReturnConnection", con), x); } } else { if (log.isDebugEnabled()) { @@ -1512,7 +1503,7 @@ public class ConnectionPool { log.debug("checkAbandoned failed.", e); } } catch (Exception e) { - log.warn("checkAbandoned failed, it will be retried.", e); + log.warn(MessageFactory.get("connectionPool.checkAbandonedFailed"), e); } } @@ -1574,7 +1565,7 @@ public class ConnectionPool { log.debug("checkIdle failed.", e); } } catch (Exception e) { - log.warn("checkIdle failed, it will be retried.", e); + log.warn(MessageFactory.get("connectionPool.checkIdleFailed"), e); } } @@ -1664,7 +1655,7 @@ public class ConnectionPool { // service instead, as a failed check already does. con.setDiscarded(true); release(con); - log.warn("Unable to test idle connection [" + con + "], closing it.", x); + log.warn(MessageFactory.get("connectionPool.unableToTestIdleConnection", con), x); continue; } if (keep) { @@ -1700,7 +1691,7 @@ public class ConnectionPool { log.debug("testAllIdle failed.", e); } } catch (Exception e) { - log.warn("testAllIdle failed, it will be retried.", e); + log.warn(MessageFactory.get("connectionPool.testAllIdleFailed"), e); } } @@ -1796,8 +1787,8 @@ public class ConnectionPool { } catch (Throwable t) { // One broken interceptor must not stop the rest of the // chain from being reset - log.warn("Interceptor [" + handler.getClass().getName() + "] threw an exception from reset(); " + - "continuing with the rest of the chain.", t); + log.warn(MessageFactory.get("connectionPool.interceptorResetFailed", + handler.getClass().getName()), t); } handler = next; } @@ -1820,8 +1811,8 @@ public class ConnectionPool { } catch (Throwable t) { // One broken interceptor must not stop the rest of the // chain from being notified - log.warn("Interceptor [" + handler.getClass().getName() + "] threw an exception from disconnected(); " + - "continuing with the rest of the chain.", t); + log.warn(MessageFactory.get("connectionPool.interceptorDisconnectedFailed", + handler.getClass().getName()), t); } handler = next; } @@ -1843,8 +1834,7 @@ public class ConnectionPool { try { jmxPool = new org.apache.tomcat.jdbc.pool.jmx.ConnectionPool(this); } catch (Exception x) { - log.warn("Unable to start JMX integration for connection pool. Instance[" + getName() + - "] can't be monitored.", x); + log.warn(MessageFactory.get("connectionPool.unableToStartJmx", getName()), x); } } @@ -2137,10 +2127,7 @@ public class ConnectionPool { // fails the caller instead. Every caller released on the // latch below reports what this publishes, and an // ExecutionException with no cause tells them nothing. - cause = new SQLException("The pooled connection served to" + - " this asynchronous borrow was released before it" + - " could be set up; no connection was borrowed," + - " borrow the pool again."); + cause = new SQLException(MessageFactory.get("connectionPool.asyncBorrowConnectionReleased")); } } catch (SQLException x) { cause = x; @@ -2207,7 +2194,7 @@ public class ConnectionPool { } } } catch (Exception x) { - log.error("Unable to cancel ConnectionFuture.", x); + log.error(MessageFactory.get("connectionPool.unableToCancelConnectionFuture"), x); } finally { // Whatever came out of it, the callers waiting on the claim are // done waiting @@ -2311,10 +2298,10 @@ public class ConnectionPool { this.pool = new WeakReference<>(pool); this.sleepTime = sleepTime; if (sleepTime <= 0) { - log.warn("Database connection pool evicter thread interval is set to 0, defaulting to 30 seconds"); + log.warn(MessageFactory.get("connectionPool.evicterIntervalZero")); this.sleepTime = 1000 * 30; } else if (sleepTime < 1000) { - log.warn("Database connection pool evicter thread interval is set to lower than 1 second."); + log.warn(MessageFactory.get("connectionPool.evicterIntervalTooLow")); } } diff --git a/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/DataSource.java b/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/DataSource.java index 76edea778d..a7f2a420bc 100644 --- a/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/DataSource.java +++ b/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/DataSource.java @@ -26,6 +26,7 @@ import javax.management.ObjectName; import org.apache.juli.logging.Log; import org.apache.juli.logging.LogFactory; import org.apache.tomcat.jdbc.pool.jmx.JmxUtil; +import org.apache.tomcat.jdbc.pool.util.MessageFactory; /** @@ -152,14 +153,14 @@ public class DataSource extends DataSourceProxy implements javax.sql.DataSource, } } catch (MalformedObjectNameException x) { this.oname = null; - log.error("Unable to create object name for JDBC pool.", x); + log.error(MessageFactory.get("dataSource.unableToCreateObjectName"), x); } catch (RuntimeException x) { // Never break the caller's MBean registration because of // pool-side state (for instance a pool that has not been // created yet); preRegister throwing aborts the whole // registration in the MBean server. this.oname = null; - log.error("Unable to register JDBC pool MBean.", x); + log.error(MessageFactory.get("dataSource.unableToRegisterMBean"), x); } return name; } @@ -207,8 +208,7 @@ public class DataSource extends DataSourceProxy implements javax.sql.DataSource, // spurious error log final org.apache.tomcat.jdbc.pool.jmx.ConnectionPool jmx = p == null ? null : p.getJmxPool(); if (jmx == null) { - log.warn("JDBC pool MBean [" + oname + "] not registered: the pool " + - "has not been created yet or has already been closed."); + log.warn(MessageFactory.get("dataSource.mbeanNotRegistered", oname)); // oname is the handle postDeregister() unregisters; do not keep // one that was never registered this.oname = null; diff --git a/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/DataSourceFactory.java b/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/DataSourceFactory.java index 80f21f7f69..767a9e34ad 100644 --- a/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/DataSourceFactory.java +++ b/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/DataSourceFactory.java @@ -38,6 +38,7 @@ import javax.sql.DataSource; import org.apache.juli.logging.Log; import org.apache.juli.logging.LogFactory; +import org.apache.tomcat.jdbc.pool.util.MessageFactory; /** * <p> @@ -421,7 +422,7 @@ public class DataSourceFactory implements ObjectFactory { } if (!ok) { - log.warn(ref.getClassName() + " is not a valid class name/type for this JNDI factory."); + log.warn(MessageFactory.get("dataSourceFactory.invalidClassName", ref.getClassName())); return null; } @@ -457,7 +458,7 @@ public class DataSourceFactory implements ObjectFactory { String addressName = addresses.nextElement().getType(); if (!ALL_PROPERTY_NAMES.contains(addressName) && !RESERVED_JNDI_ADDRESS_NAMES.contains(addressName)) { - log.warn(addressName + " is not a valid property, it will be ignored."); + log.warn(MessageFactory.get("dataSourceFactory.invalidProperty", addressName)); } } @@ -589,7 +590,7 @@ public class DataSourceFactory implements ObjectFactory { value = properties.getProperty(PROP_NUMTESTSPEREVICTIONRUN); if (value != null) { - log.warn(PROP_NUMTESTSPEREVICTIONRUN + " is not a valid setting, it will have no effect."); + log.warn(MessageFactory.get("dataSourceFactory.invalidSetting", PROP_NUMTESTSPEREVICTIONRUN)); poolProperties.setNumTestsPerEvictionRun(Integer.parseInt(value)); } @@ -643,7 +644,7 @@ public class DataSourceFactory implements ObjectFactory { value = properties.getProperty(PROP_ACCESSTOUNDERLYINGCONNECTIONALLOWED); if (value != null) { - log.warn(PROP_ACCESSTOUNDERLYINGCONNECTIONALLOWED + " is not a valid setting, it will have no effect."); + log.warn(MessageFactory.get("dataSourceFactory.invalidSetting", PROP_ACCESSTOUNDERLYINGCONNECTIONALLOWED)); Boolean b = parseBoolean(PROP_ACCESSTOUNDERLYINGCONNECTIONALLOWED, value); if (b != null) { poolProperties.setAccessToUnderlyingConnectionAllowed(b.booleanValue()); @@ -673,12 +674,12 @@ public class DataSourceFactory implements ObjectFactory { value = properties.getProperty(PROP_POOLPREPAREDSTATEMENTS); if (value != null) { - log.warn(PROP_POOLPREPAREDSTATEMENTS + " is not a valid setting, it will have no effect."); + log.warn(MessageFactory.get("dataSourceFactory.invalidSetting", PROP_POOLPREPAREDSTATEMENTS)); } value = properties.getProperty(PROP_MAXOPENPREPAREDSTATEMENTS); if (value != null) { - log.warn(PROP_MAXOPENPREPAREDSTATEMENTS + " is not a valid setting, it will have no effect."); + log.warn(MessageFactory.get("dataSourceFactory.invalidSetting", PROP_MAXOPENPREPAREDSTATEMENTS)); } value = properties.getProperty(PROP_CONNECTIONPROPERTIES); @@ -762,10 +763,8 @@ public class DataSourceFactory implements ObjectFactory { // point: getObjectInstance hands an actual javax.sql.DataSource // RefAddr content straight to the pool instead of stringifying it. // A string cannot be turned into a data source here. - throw new IllegalArgumentException("Can't set dataSource property as a string \"" + value + - "\". Either carry the javax.sql.DataSource object itself under the dataSource attribute" + - " of the Reference, or use the dataSourceJNDI attribute to name a data source bound in" + - " JNDI."); + throw new IllegalArgumentException(MessageFactory.get("dataSourceFactory.cannotSetDataSourceString", + value)); } value = properties.getProperty(PROP_DATASOURCE_JNDI); @@ -868,7 +867,7 @@ public class DataSourceFactory implements ObjectFactory { if ("false".equalsIgnoreCase(trimmed)) { return Boolean.FALSE; } - throw new IllegalArgumentException("Invalid boolean value '" + value + "' for property " + name); + throw new IllegalArgumentException(MessageFactory.get("dataSourceFactory.invalidBoolean", value, name)); } /** @@ -951,7 +950,7 @@ public class DataSourceFactory implements ObjectFactory { if (context != null) { jndiDS = context.lookup(poolProperties.getDataSourceJNDI()); } else { - log.warn("dataSourceJNDI property is configured, but local JNDI context is null."); + log.warn(MessageFactory.get("dataSourceFactory.jndiContextNull")); } } catch (NamingException e) { if (log.isDebugEnabled()) { @@ -967,19 +966,17 @@ public class DataSourceFactory implements ObjectFactory { jndiDS = context.lookup(poolProperties.getDataSourceJNDI()); } catch (NamingException e) { initialContextFailure = e; - log.warn("The name \"" + poolProperties.getDataSourceJNDI() + - "\" cannot be found in the InitialContext.", e); + log.warn(MessageFactory.get("dataSourceFactory.jndiNameNotFound", + poolProperties.getDataSourceJNDI()), e); } } if (jndiDS != null) { poolProperties.setDataSource(jndiDS); return; } - NamingException failure = new NamingException("Unable to create the connection pool: the name [" + - poolProperties.getDataSourceJNDI() + "] configured through the 'dataSourceJNDI' attribute was" + - " not found in the local JNDI context nor in the InitialContext. The pool is built around the" + - " data source that name refers to; check that the name is correct and that the data source is" + - " bound and visible to the application before the pool is created."); + NamingException failure = + new NamingException(MessageFactory.get("dataSourceFactory.jndiLookupFailed", + poolProperties.getDataSourceJNDI())); if (initialContextFailure != null) { failure.setRootCause(initialContextFailure); } diff --git a/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/DataSourceProxy.java b/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/DataSourceProxy.java index 82cddbb5ec..5aaec9cdf8 100644 --- a/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/DataSourceProxy.java +++ b/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/DataSourceProxy.java @@ -30,6 +30,7 @@ import javax.sql.XAConnection; import org.apache.juli.logging.Log; import org.apache.juli.logging.LogFactory; import org.apache.tomcat.jdbc.pool.PoolProperties.InterceptorDefinition; +import org.apache.tomcat.jdbc.pool.util.MessageFactory; /** * The DataSource proxy lets us implements methods that don't exist in the current compiler JDK but might be methods @@ -91,7 +92,7 @@ public class DataSourceProxy implements PoolConfiguration { */ public DataSourceProxy(PoolConfiguration poolProperties) { if (poolProperties == null) { - throw new NullPointerException("PoolConfiguration cannot be null."); + throw new NullPointerException(MessageFactory.get("dataSourceProxy.poolConfigurationNull")); } this.poolProperties = poolProperties; } @@ -155,7 +156,7 @@ public class DataSourceProxy implements PoolConfiguration { // The Wrapper contract asks for a failure, not for a silent null // that turns into an unrelated NullPointerException at the caller's // first use of the "unwrapped" value. - throw new SQLException("Not a wrapper of " + iface.getName()); + throw new SQLException(MessageFactory.get("dataSourceProxy.notAWrapper", iface.getName())); } /** @@ -177,10 +178,7 @@ public class DataSourceProxy implements PoolConfiguration { return createPool().getConnection(username, password); } else { if (connectionWithoutCredentialsWarningIssued.compareAndSet(false, true)) { - log.warn(String.format( - "alternateUsernameAllowed is set to false so the provided user name [%s] and associated " + - "password have been ignored", - username)); + log.warn(MessageFactory.get("dataSourceProxy.alternateUsernameIgnored", username)); } return getConnection(); } @@ -229,7 +227,7 @@ public class DataSourceProxy implements PoolConfiguration { // Returning null is not possible here: either the closed flag // rejects the caller or a pool is published and returned. if (closed) { - throw new SQLException("DataSource has been closed."); + throw new SQLException(MessageFactory.get("dataSourceProxy.dataSourceClosed")); } synchronized (poolCreationLock) { // Re-check under the gate: a close completed while this thread @@ -237,7 +235,7 @@ public class DataSourceProxy implements PoolConfiguration { // gate has already published its pool. The gate also keeps this // the only construction the shared poolProperties ever faces. if (closed) { - throw new SQLException("DataSource has been closed."); + throw new SQLException(MessageFactory.get("dataSourceProxy.dataSourceClosed")); } final ConnectionPool existing = pool; if (existing != null) { @@ -269,9 +267,9 @@ public class DataSourceProxy implements PoolConfiguration { try { fresh.close(true); } catch (Exception x) { - log.warn("Error during connection pool closure.", x); + log.warn(MessageFactory.get("dataSourceProxy.errorClosingPool"), x); } - throw new SQLException("DataSource has been closed."); + throw new SQLException(MessageFactory.get("dataSourceProxy.dataSourceClosed")); } return fresh; } @@ -321,7 +319,7 @@ public class DataSourceProxy implements PoolConfiguration { } catch (Exception ignore) { // Ignore } - throw new SQLException("Connection from pool does not implement javax.sql.XAConnection"); + throw new SQLException(MessageFactory.get("dataSourceProxy.connectionNotXA")); } } @@ -345,7 +343,7 @@ public class DataSourceProxy implements PoolConfiguration { } catch (Exception ignore) { // Ignore } - throw new SQLException("Connection from pool does not implement javax.sql.XAConnection"); + throw new SQLException(MessageFactory.get("dataSourceProxy.connectionNotXA")); } } @@ -389,7 +387,7 @@ public class DataSourceProxy implements PoolConfiguration { // a normal lifecycle state, not a creation failure. return null; } - log.error("Error during connection pool creation.", x); + log.error(MessageFactory.get("dataSourceProxy.errorCreatingPool"), x); return null; } } @@ -430,7 +428,7 @@ public class DataSourceProxy implements PoolConfiguration { try { p.close(all); } catch (Exception x) { - log.warn("Error during connection pool closure.", x); + log.warn(MessageFactory.get("dataSourceProxy.errorClosingPool"), x); } } } @@ -474,7 +472,7 @@ public class DataSourceProxy implements PoolConfiguration { // accessors would silently degrade. The class invariant is that this // field is never null, so reject the misuse at its site. if (poolProperties == null) { - throw new NullPointerException("PoolConfiguration cannot be null."); + throw new NullPointerException(MessageFactory.get("dataSourceProxy.poolConfigurationNull")); } this.poolProperties = poolProperties; } @@ -710,7 +708,7 @@ public class DataSourceProxy implements PoolConfiguration { // interface (PoolProperties itself and the pool's JMX wrapper). getPoolProperties().setConnectionProperties(properties); } catch (RuntimeException x) { - log.error("Unable to parse connection properties.", x); + log.error(MessageFactory.get("dataSourceProxy.unableToParseConnectionProperties"), x); throw x; } } @@ -1454,7 +1452,7 @@ public class DataSourceProxy implements PoolConfiguration { try { createPool().purge(); } catch (SQLException x) { - log.error("Unable to purge pool.", x); + log.error(MessageFactory.get("dataSourceProxy.unableToPurgePool"), x); } } @@ -1465,7 +1463,7 @@ public class DataSourceProxy implements PoolConfiguration { try { createPool().purgeOnReturn(); } catch (SQLException x) { - log.error("Unable to purge pool.", x); + log.error(MessageFactory.get("dataSourceProxy.unableToPurgePool"), x); } } } diff --git a/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/DisposableConnectionFacade.java b/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/DisposableConnectionFacade.java index 8b1bf25434..65f2220ba7 100644 --- a/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/DisposableConnectionFacade.java +++ b/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/DisposableConnectionFacade.java @@ -20,6 +20,8 @@ import java.lang.reflect.Method; import java.lang.reflect.Proxy; import java.sql.SQLException; +import org.apache.tomcat.jdbc.pool.util.MessageFactory; + /** * A DisposableConnectionFacade object is the top most interceptor that wraps an object of type * {@link PooledConnection}. The DisposableConnectionFacade intercepts three methods: @@ -123,7 +125,7 @@ public class DisposableConnectionFacade extends JdbcInterceptor { if (compare(TOSTRING_VAL, method)) { return "DisposableConnectionFacade[null]"; } - throw new SQLException("PooledConnection has already been closed."); + throw new SQLException(MessageFactory.get("disposableConnectionFacade.pooledConnectionClosed")); } throw e; diff --git a/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/FairBlockingQueue.java b/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/FairBlockingQueue.java index f261ad9254..c07cff065a 100644 --- a/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/FairBlockingQueue.java +++ b/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/FairBlockingQueue.java @@ -32,6 +32,8 @@ import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; import java.util.concurrent.locks.ReentrantLock; +import org.apache.tomcat.jdbc.pool.util.MessageFactory; + /** * A simple implementation of a blocking queue with fairness waiting. invocations to method poll(...) will get handed * out in the order they were received. Locking is fine grained, a shared lock is only used during the first level of @@ -354,7 +356,7 @@ public class FairBlockingQueue<E> implements BlockingQueue<E> { */ @Override public int drainTo(Collection<? super E> c, int maxElements) { - throw new UnsupportedOperationException("int drainTo(Collection<? super E> c, int maxElements)"); + throw new UnsupportedOperationException(MessageFactory.get("fairBlockingQueue.unsupportedDrainTo")); } /** @@ -401,7 +403,7 @@ public class FairBlockingQueue<E> implements BlockingQueue<E> { */ @Override public void clear() { - throw new UnsupportedOperationException("void clear()"); + throw new UnsupportedOperationException(MessageFactory.get("fairBlockingQueue.unsupportedClear")); } @@ -412,7 +414,7 @@ public class FairBlockingQueue<E> implements BlockingQueue<E> { */ @Override public boolean containsAll(Collection<?> c) { - throw new UnsupportedOperationException("boolean containsAll(Collection<?> c)"); + throw new UnsupportedOperationException(MessageFactory.get("fairBlockingQueue.unsupportedContainsAll")); } @Override @@ -427,7 +429,7 @@ public class FairBlockingQueue<E> implements BlockingQueue<E> { */ @Override public boolean removeAll(Collection<?> c) { - throw new UnsupportedOperationException("boolean removeAll(Collection<?> c)"); + throw new UnsupportedOperationException(MessageFactory.get("fairBlockingQueue.unsupportedRemoveAll")); } /** @@ -437,7 +439,7 @@ public class FairBlockingQueue<E> implements BlockingQueue<E> { */ @Override public boolean retainAll(Collection<?> c) { - throw new UnsupportedOperationException("boolean retainAll(Collection<?> c)"); + throw new UnsupportedOperationException(MessageFactory.get("fairBlockingQueue.unsupportedRetainAll")); } /** @@ -447,7 +449,7 @@ public class FairBlockingQueue<E> implements BlockingQueue<E> { */ @Override public Object[] toArray() { - throw new UnsupportedOperationException("Object[] toArray()"); + throw new UnsupportedOperationException(MessageFactory.get("fairBlockingQueue.unsupportedToArray")); } /** @@ -457,7 +459,7 @@ public class FairBlockingQueue<E> implements BlockingQueue<E> { */ @Override public <T> T[] toArray(T[] a) { - throw new UnsupportedOperationException("<T> T[] toArray(T[] a)"); + throw new UnsupportedOperationException(MessageFactory.get("fairBlockingQueue.unsupportedToArrayT")); } /** @@ -467,7 +469,7 @@ public class FairBlockingQueue<E> implements BlockingQueue<E> { */ @Override public E element() { - throw new UnsupportedOperationException("E element()"); + throw new UnsupportedOperationException(MessageFactory.get("fairBlockingQueue.unsupportedElement")); } /** @@ -477,7 +479,7 @@ public class FairBlockingQueue<E> implements BlockingQueue<E> { */ @Override public E peek() { - throw new UnsupportedOperationException("E peek()"); + throw new UnsupportedOperationException(MessageFactory.get("fairBlockingQueue.unsupportedPeek")); } /** @@ -487,7 +489,7 @@ public class FairBlockingQueue<E> implements BlockingQueue<E> { */ @Override public E remove() { - throw new UnsupportedOperationException("E remove()"); + throw new UnsupportedOperationException(MessageFactory.get("fairBlockingQueue.unsupportedRemove")); } @@ -591,7 +593,8 @@ public class FairBlockingQueue<E> implements BlockingQueue<E> { } return latch.getItem(); } else { - throw new ExecutionException("ItemFuture incorrectly instantiated. Bug in the code?", new Exception()); + throw new ExecutionException(MessageFactory.get("fairBlockingQueue.itemFutureInstantiationError"), + new Exception()); } } @@ -661,7 +664,8 @@ public class FairBlockingQueue<E> implements BlockingQueue<E> { return latch.getItem(); } } else { - throw new ExecutionException("ItemFuture incorrectly instantiated. Bug in the code?", new Exception()); + throw new ExecutionException(MessageFactory.get("fairBlockingQueue.itemFutureInstantiationError"), + new Exception()); } } @@ -683,8 +687,7 @@ public class FairBlockingQueue<E> implements BlockingQueue<E> { * @return the timeout failure to throw */ private TimeoutException abandonedTimeout() { - return new TimeoutException("The waiter of this future timed out on an earlier" + - " get() call and was deregistered from the queue; the future can no" + " longer receive an item"); + return new TimeoutException(MessageFactory.get("fairBlockingQueue.itemFutureAbandoned")); } /** diff --git a/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/PoolProperties.java b/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/PoolProperties.java index d3c744574e..bec02a2305 100644 --- a/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/PoolProperties.java +++ b/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/PoolProperties.java @@ -32,6 +32,7 @@ import java.util.concurrent.atomic.AtomicInteger; import org.apache.juli.logging.Log; import org.apache.juli.logging.LogFactory; +import org.apache.tomcat.jdbc.pool.util.MessageFactory; /** * Implementation of {@link PoolConfiguration} that holds the configuration properties for a connection pool. @@ -477,8 +478,9 @@ public class PoolProperties implements PoolConfiguration, Cloneable, Serializabl } int pidx = prop.indexOf('='); if (pidx < 0) { - throw new IllegalArgumentException("Invalid interceptor property '" + prop.trim() + - "', missing '=', in jdbcInterceptors value [" + interceptorValues[i] + "]"); + throw new IllegalArgumentException(MessageFactory.get( + "poolProperties.invalidInterceptorProperty", prop.trim(), + interceptorValues[i])); } String propName = prop.substring(0, pidx).trim(); String propValue = prop.substring(pidx + 1).trim(); @@ -727,14 +729,13 @@ public class PoolProperties implements PoolConfiguration, Cloneable, Serializabl PoolProperties.class.getClassLoader(), Thread.currentThread().getContextClassLoader()); validator = validatorClass.getConstructor().newInstance(); } catch (ClassNotFoundException e) { - log.warn("The class " + className + " cannot be found.", e); + log.warn(MessageFactory.get("poolProperties.validatorClassNotFound", className), e); } catch (ClassCastException e) { - log.warn("The class " + className + " does not implement the Validator interface.", e); + log.warn(MessageFactory.get("poolProperties.validatorNotValidator", className), e); } catch (IllegalAccessException e) { - log.warn("The class " + className + " or its no-arg constructor are inaccessible.", e); + log.warn(MessageFactory.get("poolProperties.validatorInaccessible", className), e); } catch (ReflectiveOperationException | IllegalArgumentException | SecurityException e) { - log.warn("An object of class " + className + " cannot be instantiated. Make sure that " + - "it includes an implicit or explicit no-arg constructor.", e); + log.warn(MessageFactory.get("poolProperties.validatorCannotInstantiate", className), e); } } @@ -1315,7 +1316,7 @@ public class PoolProperties implements PoolConfiguration, Cloneable, Serializabl @Override public void setDataSource(Object ds) { if (ds instanceof DataSourceProxy) { - throw new IllegalArgumentException("Layered pools are not allowed."); + throw new IllegalArgumentException(MessageFactory.get("poolProperties.layeredPoolsNotAllowed")); } this.dataSource = ds; } diff --git a/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/PooledConnection.java b/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/PooledConnection.java index 78f8fdf872..8ecbf78d54 100644 --- a/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/PooledConnection.java +++ b/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/PooledConnection.java @@ -32,6 +32,7 @@ import org.apache.juli.logging.Log; import org.apache.juli.logging.LogFactory; import org.apache.tomcat.jdbc.pool.interceptor.ConnectionState; import org.apache.tomcat.jdbc.pool.jmx.JmxUtil; +import org.apache.tomcat.jdbc.pool.util.MessageFactory; /** * Represents a pooled connection and holds a reference to the {@link java.sql.Connection} object @@ -235,7 +236,7 @@ public class PooledConnection implements PooledConnectionMBean { */ public void connect() throws SQLException { if (released.get()) { - throw new SQLException("A connection once released, can't be reestablished."); + throw new SQLException(MessageFactory.get("pooledConnection.cannotReestablish")); } if (connection != null) { try { @@ -356,7 +357,7 @@ public class PooledConnection implements PooledConnectionMBean { // Contract-violating provider: a handle without a logical // connection is of no use either. failure = new SQLException( - "XADataSource " + xds + " returned a null connection for the XA connection handle"); + MessageFactory.get("pooledConnection.xaDataSourceNullConnection", xds)); } if (failure != null || failureRuntime != null) { // Do not strand the handle if the logical connection @@ -388,7 +389,7 @@ public class PooledConnection implements PooledConnectionMBean { // when no connection can be provided; keeping that null would // surface later as a misleading validation failure, or as a // null pointer when the default connection state is applied. - throw new SQLException("DataSource " + ds + " returned a null connection"); + throw new SQLException(MessageFactory.get("pooledConnection.dataSourceNullConnection", ds)); } } else if (poolProperties.getDataSource() instanceof javax.sql.ConnectionPoolDataSource) { javax.sql.ConnectionPoolDataSource ds = (javax.sql.ConnectionPoolDataSource) poolProperties.getDataSource(); @@ -410,8 +411,8 @@ public class PooledConnection implements PooledConnectionMBean { if (connection == null && failure == null && failureRuntime == null) { // Contract-violating provider: a handle without a logical // connection is of no use either. - failure = new SQLException("ConnectionPoolDataSource " + ds + - " returned a null connection for the pooled connection handle"); + failure = new SQLException( + MessageFactory.get("pooledConnection.connectionPoolDataSourceNullConnection", ds)); } if (failure != null || failureRuntime != null) { // Do not strand the handle if the logical connection @@ -432,8 +433,8 @@ public class PooledConnection implements PooledConnectionMBean { throw failure; } } else { - throw new SQLException("DataSource is of unknown class:" + - (poolProperties.getDataSource() != null ? poolProperties.getDataSource().getClass() : "null")); + throw new SQLException(MessageFactory.get("pooledConnection.unknownDataSource", + (poolProperties.getDataSource() != null ? poolProperties.getDataSource().getClass() : "null"))); } } @@ -519,7 +520,7 @@ public class PooledConnection implements PooledConnectionMBean { } } if (connection == null) { - throw new SQLException("Driver:" + driver + " returned null for URL:" + driverURL); + throw new SQLException(MessageFactory.get("pooledConnection.driverReturnedNull", driver, driverURL)); } } @@ -575,8 +576,7 @@ public class PooledConnection implements PooledConnectionMBean { // catch only guards against a failure of the walk itself; // an interceptor must not be able to keep the physical // connection from being closed - log.warn("Interceptor threw an exception from the " + "disconnected() event; ignoring it so that the " + - "physical connection can be closed.", x); + log.warn(MessageFactory.get("pooledConnection.interceptorDisconnectedFailed"), x); } try { if (cpdsConnection != null) { @@ -715,7 +715,8 @@ public class PooledConnection implements PooledConnectionMBean { // between the idle and busy queues and strands the pooled // connection - permanently shrinking the pool if (getPoolProperties().getLogValidationErrors()) { - log.error("Custom validation through " + poolProperties.getValidator() + " threw an exception.", x); + log.error(MessageFactory.get("pooledConnection.customValidationThrew", + poolProperties.getValidator()), x); } else if (log.isDebugEnabled()) { log.debug("Custom validation threw an exception.", x); } @@ -726,7 +727,8 @@ public class PooledConnection implements PooledConnectionMBean { return true; } else { if (getPoolProperties().getLogValidationErrors()) { - log.error("Custom validation through " + poolProperties.getValidator() + " failed."); + log.error(MessageFactory.get("pooledConnection.customValidationFailed", + poolProperties.getValidator())); } return false; } @@ -771,7 +773,7 @@ public class PooledConnection implements PooledConnectionMBean { return transactionTerminated; } else { if (getPoolProperties().getLogValidationErrors()) { - log.error("isValid() returned false."); + log.error(MessageFactory.get("pooledConnection.isValidReturnedFalse")); } return false; } @@ -784,7 +786,7 @@ public class PooledConnection implements PooledConnectionMBean { // idle and busy queues and strands the pooled connection - // permanently shrinking the pool if (getPoolProperties().getLogValidationErrors()) { - log.error("isValid() failed.", e); + log.error(MessageFactory.get("pooledConnection.isValidFailed"), e); } else if (e instanceof RuntimeException) { // Unlike the checked failure this anomaly would once // have escaped as the driver's own throw; the caller @@ -793,7 +795,7 @@ public class PooledConnection implements PooledConnectionMBean { // than debug - otherwise at the default log level a // broken driver would fail every validation with no // trace anywhere - log.warn("isValid() failed.", e); + log.warn(MessageFactory.get("pooledConnection.isValidFailed"), e); } else if (log.isDebugEnabled()) { log.debug("isValid() failed.", e); } @@ -841,7 +843,7 @@ public class PooledConnection implements PooledConnectionMBean { return transactionTerminated; } catch (Exception ex) { if (getPoolProperties().getLogValidationErrors()) { - log.error("SQL Validation error", ex); + log.error(MessageFactory.get("pooledConnection.sqlValidationError"), ex); } else if (log.isDebugEnabled()) { log.debug("Unable to validate object:", ex); } @@ -882,14 +884,14 @@ public class PooledConnection implements PooledConnectionMBean { log.debug("Failed to commit transaction", e); } catch (RuntimeException e) { if (getPoolProperties().getLogValidationErrors()) { - log.error("Failed to commit transaction", e); + log.error(MessageFactory.get("pooledConnection.commitFailed"), e); } else { // The unchecked variant is logged at warn rather than debug, // like the rollback helper's: the caller surfaces it only as // the generic validation failure, so at the default log level // a driver that fails to commit would otherwise destroy // connection after connection with no trace anywhere - log.warn("Failed to commit transaction", e); + log.warn(MessageFactory.get("pooledConnection.commitFailed"), e); } } return false; @@ -913,7 +915,7 @@ public class PooledConnection implements PooledConnectionMBean { // converts it, and strand the pooled connection between the // idle and busy queues if (getPoolProperties().getLogValidationErrors()) { - log.error("Failed to rollback transaction", e); + log.error(MessageFactory.get("pooledConnection.rollbackFailed"), e); } else { // The unchecked variant is an anomaly of the same kind as // a throwing custom Validator, and unlike the checked @@ -923,7 +925,7 @@ public class PooledConnection implements PooledConnectionMBean { // level a driver that fails to end a transaction unchecked // would destroy connection after connection with no trace // anywhere - log.warn("Failed to rollback transaction", e); + log.warn(MessageFactory.get("pooledConnection.rollbackFailed"), e); } } return false; @@ -1045,7 +1047,7 @@ public class PooledConnection implements PooledConnectionMBean { */ public void setDiscarded(boolean discarded) { if (this.discarded && !discarded) { - throw new IllegalStateException("Unable to change the state once the connection has been discarded"); + throw new IllegalStateException(MessageFactory.get("pooledConnection.discardedStateChange")); } this.discarded = discarded; } @@ -1199,8 +1201,8 @@ public class PooledConnection implements PooledConnectionMBean { } catch (Throwable t) { // One broken interceptor must not stop the rest of the // chain from being reset - log.warn("Interceptor [" + interceptor.getClass().getName() + - "] threw an exception from reset(); " + "continuing with the rest of the chain.", t); + log.warn(MessageFactory.get("pooledConnection.interceptorResetFailed", + interceptor.getClass().getName()), t); } interceptor = next; } @@ -1278,7 +1280,7 @@ public class PooledConnection implements PooledConnectionMBean { private java.sql.Connection requireConnection() throws SQLException { java.sql.Connection c = connection; if (c == null) { - throw new SQLException("Connection has been disconnected."); + throw new SQLException(MessageFactory.get("pooledConnection.disconnected")); } return c; } @@ -1297,7 +1299,7 @@ public class PooledConnection implements PooledConnectionMBean { try { c.clearWarnings(); } catch (SQLException e) { - log.warn("Unable to clear warnings on the connection.", e); + log.warn(MessageFactory.get("pooledConnection.unableToClearWarnings"), e); } } diff --git a/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/ProxyConnection.java b/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/ProxyConnection.java index 710a853e0a..3119539719 100644 --- a/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/ProxyConnection.java +++ b/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/ProxyConnection.java @@ -23,6 +23,8 @@ import java.sql.SQLException; import javax.sql.XAConnection; +import org.apache.tomcat.jdbc.pool.util.MessageFactory; + /** * A ProxyConnection object is the bottom most interceptor that wraps an object of type {@link PooledConnection}. The * ProxyConnection intercepts, among the calls it forwards, the following methods: @@ -197,7 +199,7 @@ public class ProxyConnection extends JdbcInterceptor { // what isWrapperFor() says and turn into an unrelated // NullPointerException at the caller's first use of the // "unwrapped" value. - throw new SQLException("Not a wrapper of " + iface.getName()); + throw new SQLException(MessageFactory.get("proxyConnection.notAWrapper", iface.getName())); } return connection; } else if (iface == XAConnection.class) { @@ -206,7 +208,7 @@ public class ProxyConnection extends JdbcInterceptor { // The Wrapper contract asks for a failure, not for a silent // null that turns into an unrelated NullPointerException at // the caller's first use of the "unwrapped" value. - throw new SQLException("Not a wrapper of " + iface.getName()); + throw new SQLException(MessageFactory.get("proxyConnection.notAWrapper", iface.getName())); } return xa; } else if (iface.isInstance(connection.getConnection())) { @@ -216,7 +218,7 @@ public class ProxyConnection extends JdbcInterceptor { // unwrapping that far is its answer to give, not ours return connection.getConnection().unwrap(iface); } else { - throw new SQLException("Not a wrapper of " + iface.getName()); + throw new SQLException(MessageFactory.get("proxyConnection.notAWrapper", iface.getName())); } } @@ -349,10 +351,9 @@ public class ProxyConnection extends JdbcInterceptor { // The handle was disconnected while borrowed; report it // the way every other method on this class does, rather // than blaming the XA configuration. - throw new SQLException("Connection has already been closed."); + throw new SQLException(MessageFactory.get("proxyConnection.connectionClosed")); } - throw new SQLException("The pooled connection is not an XA connection; " + "method [" + - method.getName() + "] cannot be dispatched."); + throw new SQLException(MessageFactory.get("proxyConnection.notXAConnection", method.getName())); } try { return method.invoke(xaConnection, args); @@ -365,7 +366,7 @@ public class ProxyConnection extends JdbcInterceptor { } } if (isClosed()) { - throw new SQLException("Connection has already been closed."); + throw new SQLException(MessageFactory.get("proxyConnection.connectionClosed")); } if (compare(UNWRAP_VAL, method)) { Class<?> iface = (Class<?>) args[0]; @@ -392,7 +393,7 @@ public class ProxyConnection extends JdbcInterceptor { if (poolc != null) { return method.invoke(poolc.getConnection(), args); } else { - throw new SQLException("Connection has already been closed."); + throw new SQLException(MessageFactory.get("proxyConnection.connectionClosed")); } } catch (Throwable t) { if (t instanceof InvocationTargetException) { diff --git a/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/StatementFacade.java b/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/StatementFacade.java index e289878f97..d67e5d6d4e 100644 --- a/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/StatementFacade.java +++ b/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/StatementFacade.java @@ -31,6 +31,7 @@ import java.sql.Wrapper; import org.apache.juli.logging.Log; import org.apache.juli.logging.LogFactory; import org.apache.tomcat.jdbc.pool.interceptor.AbstractCreateStatementInterceptor; +import org.apache.tomcat.jdbc.pool.util.MessageFactory; /** * Facade that creates statement and result set proxies. @@ -204,13 +205,12 @@ public class StatementFacade extends AbstractCreateStatementInterceptor { } } if (target == null) { - throw new SQLException("Statement closed."); + throw new SQLException(MessageFactory.get("statementFacade.statementClosed")); } if (ended) { // The delegate is still open, but it is open on a session // that belongs to the next borrower now. - throw new SQLException("Statement closed. The pooled connection this " + - "statement was created from has been returned to the pool."); + throw new SQLException(MessageFactory.get("statementFacade.statementClosedConnectionReturned")); } // The connection a statement reports is the pooled handle the // application created it from, not the driver's own connection. @@ -345,13 +345,12 @@ public class StatementFacade extends AbstractCreateStatementInterceptor { } } if (target == null) { - throw new SQLException("ResultSet closed."); + throw new SQLException(MessageFactory.get("statementFacade.resultSetClosed")); } if (ended) { // The cursor is still open, but it is open on a session that // belongs to the next borrower now. - throw new SQLException("ResultSet closed. The pooled connection this " + - "result set was read from has been returned to the pool."); + throw new SQLException(MessageFactory.get("statementFacade.resultSetClosedConnectionReturned")); } if (compare(GET_STATEMENT, method)) { diff --git a/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/TrapException.java b/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/TrapException.java index 36540b75ef..4a447b4ba8 100644 --- a/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/TrapException.java +++ b/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/TrapException.java @@ -21,6 +21,8 @@ import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.sql.SQLException; +import org.apache.tomcat.jdbc.pool.util.MessageFactory; + /** * Interceptor that traps any unhandled exception types and throws an exception that has been declared by the method * called, or throw an SQLException if it is declared. If the caught exception is not declared, and the method doesn't @@ -50,11 +52,13 @@ public class TrapException extends JdbcInterceptor { Class<?> exceptionClass = exception.getClass(); if (!isDeclaredException(method, exceptionClass)) { if (isDeclaredException(method, SQLException.class)) { - SQLException sqlx = new SQLException("Uncaught underlying exception."); + SQLException sqlx = + new SQLException(MessageFactory.get("trapException.uncaughtUnderlyingException")); sqlx.initCause(exception); exception = sqlx; } else { - RuntimeException rx = new RuntimeException("Uncaught underlying exception."); + RuntimeException rx = + new RuntimeException(MessageFactory.get("trapException.uncaughtUnderlyingException")); rx.initCause(exception); exception = rx; } diff --git a/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/XADataSource.java b/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/XADataSource.java index 15120840db..f0a841fd88 100644 --- a/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/XADataSource.java +++ b/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/XADataSource.java @@ -20,6 +20,8 @@ import java.sql.SQLException; import javax.sql.XAConnection; +import org.apache.tomcat.jdbc.pool.util.MessageFactory; + /** * XA-enabled data source for distributed transaction support. * <p> @@ -93,19 +95,11 @@ public class XADataSource extends DataSource implements javax.sql.XADataSource { // configured pool therefore never becomes a data source at all. String jndiName = getPoolProperties().getDataSourceJNDI(); if (jndiName != null) { - throw new SQLException("The connection pool [" + getName() + "] cannot provide XA connections:" + - " the name \"" + jndiName + "\" set through the 'dataSourceJNDI' attribute has not been" + - " resolved into a data source; the name is only looked up when the pool is created" + - " through the DataSourceFactory. Set the 'dataSource' attribute to a" + - " javax.sql.XADataSource provided by the JDBC driver."); + throw new SQLException(MessageFactory.get("xaDataSource.jndiNotResolved", getName(), jndiName)); } - throw new SQLException("The connection pool [" + getName() + "] cannot provide XA connections:" + - " neither the 'dataSource' nor the 'dataSourceJNDI' attribute is set, so only plain JDBC" + - " connections from a JDBC driver and URL can be pooled. Set the 'dataSource' or" + - " 'dataSourceJNDI' attribute to a javax.sql.XADataSource provided by the JDBC driver."); + throw new SQLException(MessageFactory.get("xaDataSource.noDataSource", getName())); } - throw new SQLException("The connection pool [" + getName() + "] cannot provide XA connections: the data" + - " source configured through the 'dataSource' or 'dataSourceJNDI' attribute (" + - ds.getClass().getName() + ") does not implement javax.sql.XADataSource."); + throw new SQLException(MessageFactory.get("xaDataSource.dataSourceNotXA", getName(), + ds.getClass().getName())); } } diff --git a/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/interceptor/AbstractCreateStatementInterceptor.java b/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/interceptor/AbstractCreateStatementInterceptor.java index 6bd27ccc7b..df48876908 100644 --- a/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/interceptor/AbstractCreateStatementInterceptor.java +++ b/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/interceptor/AbstractCreateStatementInterceptor.java @@ -31,6 +31,7 @@ import org.apache.juli.logging.LogFactory; import org.apache.tomcat.jdbc.pool.ConnectionPool; import org.apache.tomcat.jdbc.pool.JdbcInterceptor; import org.apache.tomcat.jdbc.pool.PooledConnection; +import org.apache.tomcat.jdbc.pool.util.MessageFactory; /** * Abstraction interceptor. This component intercepts all calls to create some type of SQL statement. By extending this @@ -170,8 +171,8 @@ public abstract class AbstractCreateStatementInterceptor extends JdbcInterceptor } catch (ReflectiveOperationException | IllegalArgumentException | LinkageError e) { // An exception escaping the class initializer would surface as an // ExceptionInInitializerError at every use of every subclass. - log.warn("Unable to create the constructor cache entry for index " + idx + " (" + clazz.getName() - + ").", e); + log.warn(MessageFactory.get("abstractCreateStatementInterceptor.unableToCreateConstructorCacheEntry", + idx, clazz.getName()), e); } } @@ -237,10 +238,9 @@ public abstract class AbstractCreateStatementInterceptor extends JdbcInterceptor new Class[] { clazz }); constructors[idx] = proxyClass.getConstructor(new Class[] { InvocationHandler.class }); } else if (!clazz.isAssignableFrom(constructors[idx].getDeclaringClass())) { - throw new IllegalStateException("Constructor cache index " + idx + " is already populated for " - + Arrays.toString(constructors[idx].getDeclaringClass().getInterfaces()) + ", but " - + clazz.getName() + " was requested. Every use of an index must pass an interface the cached" - + " proxy implements."); + throw new IllegalStateException(MessageFactory.get( + "abstractCreateStatementInterceptor.constructorCacheIndexPopulated", + idx, Arrays.toString(constructors[idx].getDeclaringClass().getInterfaces()), clazz.getName())); } return constructors[idx]; } diff --git a/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/interceptor/AbstractQueryReport.java b/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/interceptor/AbstractQueryReport.java index 175bf44d02..e0e06e15d6 100644 --- a/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/interceptor/AbstractQueryReport.java +++ b/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/interceptor/AbstractQueryReport.java @@ -28,6 +28,7 @@ import java.sql.Statement; import org.apache.juli.logging.Log; import org.apache.juli.logging.LogFactory; +import org.apache.tomcat.jdbc.pool.util.MessageFactory; /** * Abstract class that wraps statements and intercepts query executions. @@ -213,7 +214,7 @@ public abstract class AbstractQueryReport extends AbstractCreateStatementInterce result = constructor.newInstance(new Object[] { new StatementProxy(statement, sql) }); return result; } catch (Exception x) { - log.warn("Unable to create statement proxy for slow query report.", x); + log.warn(MessageFactory.get("abstractQueryReport.unableToCreateStatementProxy"), x); } return statement; } @@ -316,7 +317,7 @@ public abstract class AbstractQueryReport extends AbstractCreateStatementInterce } // If we are calling anything else, bail out if (gone) { - throw new SQLException("Statement closed."); + throw new SQLException(MessageFactory.get("abstractQueryReport.statementClosed")); } boolean process = false; // Check to see if we are about to execute a query @@ -358,8 +359,8 @@ public abstract class AbstractQueryReport extends AbstractCreateStatementInterce // Reporting must never disturb the application - // the driver's exception is the one being thrown if (log.isWarnEnabled()) { - log.warn("Unable to process failed query for " + - AbstractQueryReport.this.getClass().getName(), reporting); + log.warn(MessageFactory.get("abstractQueryReport.unableToProcessFailedQuery", + AbstractQueryReport.this.getClass().getName()), reporting); } } } @@ -387,8 +388,8 @@ public abstract class AbstractQueryReport extends AbstractCreateStatementInterce reportSlowQuery(query, args, name, start, delta); } catch (Throwable t) { if (log.isWarnEnabled()) { - log.warn("Unable to process slow query for " + AbstractQueryReport.this.getClass().getName(), - t); + log.warn(MessageFactory.get("abstractQueryReport.unableToProcessSlowQuery", + AbstractQueryReport.this.getClass().getName()), t); } } } else if (process) { @@ -397,8 +398,8 @@ public abstract class AbstractQueryReport extends AbstractCreateStatementInterce } catch (Throwable t) { // Reporting must never disturb the application if (log.isWarnEnabled()) { - log.warn("Unable to process query report for " + AbstractQueryReport.this.getClass().getName(), - t); + log.warn(MessageFactory.get("abstractQueryReport.unableToProcessQueryReport", + AbstractQueryReport.this.getClass().getName()), t); } } } diff --git a/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/interceptor/ConnectionState.java b/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/interceptor/ConnectionState.java index 5494e861ad..d5d1b6b842 100644 --- a/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/interceptor/ConnectionState.java +++ b/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/interceptor/ConnectionState.java @@ -27,6 +27,7 @@ import org.apache.tomcat.jdbc.pool.DataSourceFactory; import org.apache.tomcat.jdbc.pool.JdbcInterceptor; import org.apache.tomcat.jdbc.pool.PoolConfiguration; import org.apache.tomcat.jdbc.pool.PooledConnection; +import org.apache.tomcat.jdbc.pool.util.MessageFactory; /** * Interceptor that keep track of connection state to avoid roundtrips to the database. The @@ -163,8 +164,7 @@ public class ConnectionState extends JdbcInterceptor { // ConnectionPool.setupConnection() catches this, discards the // connection and fails the borrow. throw new IllegalStateException( - "Unable to check for, or terminate, the pending transaction before restoring the configured connection state.", - x); + MessageFactory.get("connectionState.unableToTerminatePendingTransaction"), x); } } if (resetTransactionIsolation) { @@ -189,9 +189,8 @@ public class ConnectionState extends JdbcInterceptor { // Report it here, at refusal time, as no later borrow will log // it again. refusedIsolationLevel = defaultTransactionIsolation; - log.error("Unable to reset transaction isolation state to connection. The configured level " - + defaultTransactionIsolation + " will not be retried on this session; it keeps its " - + "current isolation level.", x); + log.error(MessageFactory.get("connectionState.unableToResetTransactionIsolation", + defaultTransactionIsolation), x); } } if (resetReadOnly) { @@ -207,8 +206,8 @@ public class ConnectionState extends JdbcInterceptor { // that failed, so it must not go to the next borrower. // ConnectionPool.setupConnection() catches this, discards the // connection and fails the borrow. - throw new IllegalStateException("Unable to restore the configured read-only state " - + defaultReadOnly + " on the connection.", x); + throw new IllegalStateException( + MessageFactory.get("connectionState.unableToRestoreReadOnly", defaultReadOnly), x); } } if (resetAutoCommit) { @@ -222,8 +221,8 @@ public class ConnectionState extends JdbcInterceptor { // As for the read-only state above: the driver refused the // configured auto-commit state, so the borrow fails and the // connection is discarded. - throw new IllegalStateException("Unable to restore the configured auto-commit state " - + defaultAutoCommit + " on the connection.", x); + throw new IllegalStateException( + MessageFactory.get("connectionState.unableToRestoreAutoCommit", defaultAutoCommit), x); } } if (resetCatalog) { @@ -238,8 +237,8 @@ public class ConnectionState extends JdbcInterceptor { // configured catalog, so the borrower learns of the // misconfiguration instead of getting a connection that was // never pointed at the database the pool asks it to work in. - throw new IllegalStateException("Unable to restore the configured default catalog " - + defaultCatalog + " on the connection.", x); + throw new IllegalStateException( + MessageFactory.get("connectionState.unableToRestoreCatalog", defaultCatalog), x); } } @@ -327,7 +326,7 @@ public class ConnectionState extends JdbcInterceptor { } } catch (Throwable e) { if (write) { - log.warn("Reset state to null as an exception occurred while calling method[" + name + "].", e); + log.warn(MessageFactory.get("connectionState.resetStateToNull", name), e); switch (index) { case 0: { autoCommit = null; diff --git a/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/interceptor/QueryTimeoutInterceptor.java b/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/interceptor/QueryTimeoutInterceptor.java index cc6a7c2481..367666236e 100644 --- a/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/interceptor/QueryTimeoutInterceptor.java +++ b/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/interceptor/QueryTimeoutInterceptor.java @@ -26,6 +26,7 @@ import org.apache.juli.logging.LogFactory; import org.apache.tomcat.jdbc.pool.ConnectionPool; import org.apache.tomcat.jdbc.pool.PoolProperties.InterceptorProperty; import org.apache.tomcat.jdbc.pool.PooledConnection; +import org.apache.tomcat.jdbc.pool.util.MessageFactory; /** * Interceptor that sets a query timeout on every created {@link Statement}. @@ -95,11 +96,8 @@ public class QueryTimeoutInterceptor extends AbstractCreateStatementInterceptor try { timeout = Integer.parseInt(p.getValue()); } catch (NumberFormatException x) { - log.warn("[QueryTimeoutInterceptor] The configured queryTimeout [" + p.getValue() - + "] is not an integer number of seconds and is not applied: statements created through" - + " this configuration keep the default " + timeout + "-second query timeout. Correct the" - + " value in the jdbcInterceptors configuration to set the timeout that was meant to be" - + " configured."); + log.warn(MessageFactory.get("queryTimeoutInterceptor.invalidQueryTimeout", + p.getValue(), timeout)); } } @@ -142,10 +140,7 @@ public class QueryTimeoutInterceptor extends AbstractCreateStatementInterceptor return; } timeoutRefusalReported = true; - log.warn("[QueryTimeoutInterceptor] Unable to set the query timeout of " + timeout + " seconds on a statement" - + " of this connection: " + x.getMessage() + ". The driver does not apply the timeout, so statements" - + " created on this physical connection run without a query timeout. Refusals are not logged again on" - + " this connection.", x); + log.warn(MessageFactory.get("queryTimeoutInterceptor.queryTimeoutRefused", timeout, x.getMessage()), x); } /** diff --git a/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/interceptor/ResetAbandonedTimer.java b/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/interceptor/ResetAbandonedTimer.java index 43833660d0..1a8767cf8b 100644 --- a/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/interceptor/ResetAbandonedTimer.java +++ b/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/interceptor/ResetAbandonedTimer.java @@ -34,6 +34,7 @@ import org.apache.juli.logging.LogFactory; import org.apache.tomcat.jdbc.pool.ConnectionPool; import org.apache.tomcat.jdbc.pool.PooledConnection; import org.apache.tomcat.jdbc.pool.jmx.JmxUtil; +import org.apache.tomcat.jdbc.pool.util.MessageFactory; /** * Class that resets the abandoned timer on any activity on the Connection, on any query execution and on any read of a @@ -130,7 +131,8 @@ public class ResetAbandonedTimer extends AbstractQueryReport implements ResetAba } return getConstructor(index, type).newInstance(new Object[] { new TimerStatementProxy(result) }); } catch (Exception x) { - log.warn("Unable to create timer statement proxy for " + getClass().getName() + ".", x); + log.warn(MessageFactory.get("resetAbandonedTimer.unableToCreateTimerStatementProxy", + getClass().getName()), x); } return result; } @@ -234,7 +236,7 @@ public class ResetAbandonedTimer extends AbstractQueryReport implements ResetAba return Boolean.TRUE; } if (target == null) { - throw new SQLException("Statement closed."); + throw new SQLException(MessageFactory.get("resetAbandonedTimer.statementClosed")); } Object result; try { @@ -273,8 +275,8 @@ public class ResetAbandonedTimer extends AbstractQueryReport implements ResetAba } catch (Exception x) { // The application just does not get the timer reset // while reading this result set - log.warn("Unable to create timer result set proxy for " + - ResetAbandonedTimer.this.getClass().getName() + ".", x); + log.warn(MessageFactory.get("resetAbandonedTimer.unableToCreateTimerResultSetProxy", + ResetAbandonedTimer.this.getClass().getName()), x); } } return result; @@ -365,7 +367,7 @@ public class ResetAbandonedTimer extends AbstractQueryReport implements ResetAba // result set handle does, rather than by invoking on a // null receiver: that is a NullPointerException, where the // closed contract owes the application a SQLException - throw new SQLException("ResultSet closed."); + throw new SQLException(MessageFactory.get("resetAbandonedTimer.resultSetClosed")); } if (compare(GET_STATEMENT, method)) { return stmt; diff --git a/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/interceptor/SlowQueryReport.java b/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/interceptor/SlowQueryReport.java index ed26310890..fc5e671abe 100644 --- a/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/interceptor/SlowQueryReport.java +++ b/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/interceptor/SlowQueryReport.java @@ -37,6 +37,7 @@ import org.apache.juli.logging.LogFactory; import org.apache.tomcat.jdbc.pool.ConnectionPool; import org.apache.tomcat.jdbc.pool.PoolProperties.InterceptorProperty; import org.apache.tomcat.jdbc.pool.PooledConnection; +import org.apache.tomcat.jdbc.pool.util.MessageFactory; /** * Slow query report interceptor. Tracks timing of query executions. @@ -139,7 +140,7 @@ public class SlowQueryReport extends AbstractQueryReport { // FAILED QUERY notification behind isLogFailed() alone, the two // channels disagreeing on the same event. if (isLogFailed() && log.isWarnEnabled()) { - log.warn("Failed Query Report SQL=" + sql + "; time=" + delta + " ms;"); + log.warn(MessageFactory.get("slowQueryReport.failedQueryReport", sql, delta)); } return sql; } @@ -179,7 +180,7 @@ public class SlowQueryReport extends AbstractQueryReport { // disagreeing on the same event. This mirrors how // reportFailedQuery reports its event. if (isLogSlow() && log.isWarnEnabled()) { - log.warn("Slow Query Report SQL=" + sql + "; time=" + delta + " ms;"); + log.warn(MessageFactory.get("slowQueryReport.slowQueryReport", sql, delta)); } return sql; } @@ -245,9 +246,7 @@ public class SlowQueryReport extends AbstractQueryReport { return registration; }); if (stats.hasOtherLivePools() && log.isWarnEnabled()) { - log.warn("Connection pool name [" + pool.getName() + "] is already in use by " + - "another live pool; SlowQueryReport statistics are keyed by pool name, " + - "so both pools report into the same statistics map."); + log.warn(MessageFactory.get("slowQueryReport.poolNameInUse", pool.getName())); } queries = stats.getQueryStats(); } @@ -315,7 +314,7 @@ public class SlowQueryReport extends AbstractQueryReport { ConcurrentHashMap<String, QueryStats> queries = SlowQueryReport.this.queries; if (queries == null) { if (log.isWarnEnabled()) { - log.warn("Connection has already been closed or abandoned"); + log.warn(MessageFactory.get("slowQueryReport.connectionClosedOrAbandoned")); } return null; } diff --git a/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/interceptor/SlowQueryReportJmx.java b/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/interceptor/SlowQueryReportJmx.java index 84f8bf9e38..f79c457120 100644 --- a/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/interceptor/SlowQueryReportJmx.java +++ b/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/interceptor/SlowQueryReportJmx.java @@ -45,6 +45,7 @@ import org.apache.tomcat.jdbc.pool.ConnectionPool; import org.apache.tomcat.jdbc.pool.PoolProperties.InterceptorProperty; import org.apache.tomcat.jdbc.pool.PooledConnection; import org.apache.tomcat.jdbc.pool.jmx.JmxUtil; +import org.apache.tomcat.jdbc.pool.util.MessageFactory; /** * JMX-enabled slow query report interceptor. Publishes slow and failed query statistics to JMX and provides @@ -231,7 +232,7 @@ public class SlowQueryReportJmx extends SlowQueryReport implements NotificationE "Composite data type for query statistics", QueryStats.getFieldNames(), QueryStats.getFieldDescriptions(), QueryStats.getFieldTypes()); } catch (OpenDataException x) { - log.warn("Unable to initialize composite data type for JMX stats and notifications.", x); + log.warn(MessageFactory.get("slowQueryReportJmx.unableToInitCompositeType"), x); } } return SLOW_QUERY_TYPE; @@ -569,7 +570,7 @@ public class SlowQueryReportJmx extends SlowQueryReport implements NotificationE notifiers.remove(poolName); registrationFailuresLogged.remove(poolName); } catch (MalformedObjectNameException | RuntimeOperationsException e) { - log.warn("Jmx deregistration failed.", e); + log.warn(MessageFactory.get("slowQueryReportJmx.jmxDeregistrationFailed"), e); } } @@ -679,25 +680,19 @@ public class SlowQueryReportJmx extends SlowQueryReport implements NotificationE // Retryable: the name may be held by a stale // or foreign MBean that a later borrow finds // gone - log.warn("Jmx registration of [" + oname + - "] failed: the name is already in use by another MBean." + - " The registration is retried by later borrows;" + - " repeated failures are logged at debug level.", x); + log.warn(MessageFactory.get("slowQueryReportJmx.jmxRegistrationInUse", oname), x); } else { - log.error("Jmx registration of [" + oname + - "] failed, no JMX data will be exposed for the query stats" + - " until a registration succeeds. The registration is" + - " retried by later borrows; repeated failures are" + " logged at debug level.", - x); + log.error(MessageFactory.get("slowQueryReportJmx.jmxRegistrationFailed", oname), x); } } } } } else { - log.warn(SlowQueryReport.class.getName() + "- No JMX support, composite type was not found."); + log.warn(MessageFactory.get("slowQueryReportJmx.noJmxSupport", + SlowQueryReport.class.getName())); } } catch (MalformedObjectNameException | RuntimeOperationsException e) { - log.error("Jmx registration failed, no JMX data will be exposed for the query stats.", e); + log.error(MessageFactory.get("slowQueryReportJmx.jmxRegistrationFailedNoData"), e); } } diff --git a/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/interceptor/StatementCache.java b/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/interceptor/StatementCache.java index c5dd376cf6..04787b3132 100644 --- a/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/interceptor/StatementCache.java +++ b/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/interceptor/StatementCache.java @@ -38,6 +38,7 @@ import org.apache.tomcat.jdbc.pool.JdbcInterceptor; import org.apache.tomcat.jdbc.pool.PoolProperties.InterceptorProperty; import org.apache.tomcat.jdbc.pool.PooledConnection; import org.apache.tomcat.jdbc.pool.jmx.JmxUtil; +import org.apache.tomcat.jdbc.pool.util.MessageFactory; /** * Interceptor that caches {@code PreparedStatement} and/or {@code CallableStatement} instances on a connection. @@ -282,7 +283,7 @@ public class StatementCache extends StatementDecoratorInterceptor implements Sta } CacheKey key = createCacheKey(method, args); if (key == null) { - throw new IllegalArgumentException("Null key"); + throw new IllegalArgumentException(MessageFactory.get("statementCache.nullKey")); } return cache.get(key); } @@ -437,7 +438,7 @@ public class StatementCache extends StatementDecoratorInterceptor implements Sta PooledConnection pCon = this.pcon; if (pCon == null) { if (log.isWarnEnabled()) { - log.warn("Connection has already been closed or abandoned"); + log.warn(MessageFactory.get("statementCache.connectionClosedOrAbandoned")); } return null; } @@ -649,7 +650,7 @@ public class StatementCache extends StatementDecoratorInterceptor implements Sta try { super.closeInvoked(); } catch (SQLException x) { - log.warn("Unable to close statement [" + getSql() + "] that the statement cache is discarding.", x); + log.warn(MessageFactory.get("statementCache.unableToCloseDiscardedStatement", getSql()), x); } } diff --git a/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/interceptor/StatementDecoratorInterceptor.java b/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/interceptor/StatementDecoratorInterceptor.java index d7f135ead1..468a5ce6d7 100644 --- a/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/interceptor/StatementDecoratorInterceptor.java +++ b/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/interceptor/StatementDecoratorInterceptor.java @@ -29,6 +29,7 @@ import java.sql.Statement; import org.apache.juli.logging.Log; import org.apache.juli.logging.LogFactory; +import org.apache.tomcat.jdbc.pool.util.MessageFactory; /** * Implementation of <b>JdbcInterceptor</b> that proxies resultSets and statements. @@ -400,7 +401,7 @@ public class StatementDecoratorInterceptor extends AbstractCreateStatementInterc } // If we are calling anything else, bail out if (gone) { - throw new SQLException("Statement closed."); + throw new SQLException(MessageFactory.get("statementDecoratorInterceptor.statementClosed")); } if (compare(GETCONNECTION_VAL, method)) { // The handle of the current borrow, as bound by diff --git a/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/interceptor/StatementFinalizer.java b/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/interceptor/StatementFinalizer.java index dd4bafa1a7..4223050e9e 100644 --- a/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/interceptor/StatementFinalizer.java +++ b/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/interceptor/StatementFinalizer.java @@ -32,6 +32,7 @@ import org.apache.juli.logging.LogFactory; import org.apache.tomcat.jdbc.pool.ConnectionPool; import org.apache.tomcat.jdbc.pool.PoolProperties; import org.apache.tomcat.jdbc.pool.PooledConnection; +import org.apache.tomcat.jdbc.pool.util.MessageFactory; /** * Keeps track of statements associated with a connection and invokes close upon {@link java.sql.Connection#close()} @@ -113,7 +114,7 @@ public class StatementFinalizer extends AbstractCreateStatementInterceptor { // The statement is still tracked and will be closed when the // connection is returned, but closing it early will no longer // forget it before then. - log.warn("Unable to create statement tracking proxy.", x); + log.warn(MessageFactory.get("statementFinalizer.unableToCreateTrackingProxy"), x); return tracked; } } @@ -216,7 +217,7 @@ public class StatementFinalizer extends AbstractCreateStatementInterceptor { } } if (logCreationStack && shallClose) { - log.warn("Statement created, but was not closed at:", allocationStack); + log.warn(MessageFactory.get("statementFinalizer.statementNotClosed"), allocationStack); } } } diff --git a/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/jmx/ConnectionPool.java b/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/jmx/ConnectionPool.java index 60f6c8c8f5..a8ee86ae21 100644 --- a/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/jmx/ConnectionPool.java +++ b/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/jmx/ConnectionPool.java @@ -37,6 +37,7 @@ import org.apache.tomcat.jdbc.pool.PoolConfiguration; import org.apache.tomcat.jdbc.pool.PoolProperties.InterceptorDefinition; import org.apache.tomcat.jdbc.pool.PoolUtilities; import org.apache.tomcat.jdbc.pool.Validator; +import org.apache.tomcat.jdbc.pool.util.MessageFactory; /** * JMX MBean wrapper for a {@link org.apache.tomcat.jdbc.pool.ConnectionPool}. Provides management and monitoring @@ -260,8 +261,8 @@ public class ConnectionPool extends NotificationBroadcasterSupport implements Co // The delivery queue is full; dropping the notification is the // point of the bound, and must not fail the pool operation that // reported the condition - log.warn("Dropping notification of type [" + type + "] for pool [" + getNotificationSource() + - "]: the notification delivery queue (" + NOTIFY_QUEUE_CAPACITY + " deliveries) is full"); + log.warn(MessageFactory.get("jmxConnectionPool.droppingNotification", + type, getNotificationSource(), NOTIFY_QUEUE_CAPACITY)); return false; } catch (Exception x) { if (log.isDebugEnabled()) { diff --git a/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/jmx/JmxUtil.java b/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/jmx/JmxUtil.java index c554c7652b..145599ee7f 100644 --- a/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/jmx/JmxUtil.java +++ b/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/jmx/JmxUtil.java @@ -24,6 +24,7 @@ import javax.management.ObjectName; import org.apache.juli.logging.Log; import org.apache.juli.logging.LogFactory; +import org.apache.tomcat.jdbc.pool.util.MessageFactory; /** * Utility class for JMX registration of JDBC pool components. @@ -62,7 +63,7 @@ public class JmxUtil { oname = name; } } catch (Exception e) { - log.error("Jmx registration failed.", e); + log.error(MessageFactory.get("jmxUtil.jmxRegistrationFailed"), e); } return oname; } @@ -79,7 +80,7 @@ public class JmxUtil { try { ManagementFactory.getPlatformMBeanServer().unregisterMBean(oname); } catch (Exception e) { - log.error("Jmx unregistration failed.", e); + log.error(MessageFactory.get("jmxUtil.jmxUnregistrationFailed"), e); } } diff --git a/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/util/LocalStrings.properties b/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/util/LocalStrings.properties new file mode 100644 index 0000000000..906f00a192 --- /dev/null +++ b/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/util/LocalStrings.properties @@ -0,0 +1,199 @@ +# 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. + +abstractCreateStatementInterceptor.constructorCacheIndexPopulated=Constructor cache index {0} is already populated for {1}, but {2} was requested. Every use of an index must pass an interface the cached proxy implements. +abstractCreateStatementInterceptor.unableToCreateConstructorCacheEntry=Unable to create the constructor cache entry for index {0} ({1}). + +abstractQueryReport.statementClosed=Statement closed. +abstractQueryReport.unableToCreateStatementProxy=Unable to create statement proxy for slow query report. +abstractQueryReport.unableToProcessFailedQuery=Unable to process failed query for {0} +abstractQueryReport.unableToProcessQueryReport=Unable to process query report for {0} +abstractQueryReport.unableToProcessSlowQuery=Unable to process slow query for {0} + +classLoaderUtil.classLoaderNull=Classloader is null +classLoaderUtil.classLoadFailed=Unable to load class: {0} from {1} + +connectionPool.checkAbandonedFailed=checkAbandoned failed, it will be retried. +connectionPool.checkIdleFailed=checkIdle failed, it will be retried. +connectionPool.connectionAbandoned=Connection has been abandoned {0}:{1} +connectionPool.connectionSuspect=Connection has been marked suspect, possibly abandoned {0}[{1} ms.]:{2} +connectionPool.evicterIntervalTooLow=Database connection pool evicter thread interval is set to lower than 1 second. +connectionPool.evicterIntervalZero=Database connection pool evicter thread interval is set to 0, defaulting to 30 seconds +connectionPool.failedToAddNewConnection=Failed to add a new connection to the pool after releasing a connection when at least one thread was waiting for a connection. +connectionPool.failedToReconnectExpired=Failed to re-connect connection [{0}] that expired because of maxAge +connectionPool.failedToValidateNewConnection=Failed to validate a newly established connection. +connectionPool.interceptorDisconnectedFailed=Interceptor [{0}] threw an exception from disconnected(); continuing with the rest of the chain. +connectionPool.interceptorResetFailed=Interceptor [{0}] threw an exception from reset(); continuing with the rest of the chain. +connectionPool.initialSizeTooLarge=initialSize is larger than maxActive, setting initialSize to: {0} +connectionPool.maxActiveTooSmall=maxActive is smaller than 1, setting maxActive to: {0} +connectionPool.maxIdleTooLarge=maxIdle is larger than maxActive, setting maxIdle to: {0} +connectionPool.maxIdleTooSmall=maxIdle is smaller than minIdle, setting maxIdle to: {0} +connectionPool.minIdleTooLarge=minIdle is larger than maxActive, setting minIdle to: {0} +connectionPool.poolClosed=Connection pool closed. +connectionPool.poolEmptyNoWait=[{0}] NoWait: Pool empty. Unable to fetch a connection, none available[{1} in use]. +connectionPool.poolEmptyTimeout=[{0}] Timeout: Pool empty. Unable to fetch a connection in {1} seconds, none available[size:{2}; busy:{3}; idle:{4}; lastwait:{5}]. +connectionPool.poolMisconfigured=Connection pool is misconfigured, doesn''t support async retrieval. Set the ''fair'' property to ''true'' +connectionPool.poolWaitInterrupted=Pool wait interrupted. +connectionPool.requestHintRefused=The request boundary hint [{0}] was refused by the driver +connectionPool.statementCacheBeforeQueryTimeout=The [StatementCache] interceptor is configured before [QueryTimeoutInterceptor]. A statement cache hit is answered by the cache without invoking the timeout interceptor, and a statement recycled into the cache carries no timeout, so cached statements run without a query timeout. List QueryTimeoutInterceptor before StatementCache in the jdbcInterceptors configuration. +connectionPool.suspectConnectionReturned=Connection({0}) that has been marked suspect was returned. The processing time is {1} ms. +connectionPool.testAllIdleFailed=testAllIdle failed, it will be retried. +connectionPool.timeBetweenEvictionRunsTooLarge=timeBetweenEvictionRunsMillis is larger than maxAge, setting timeBetweenEvictionRunsMillis to: {0} +connectionPool.unableToCancelConnectionFuture=Unable to cancel ConnectionFuture. +connectionPool.unableToCheckClosed=Unable to check if connection is closed +connectionPool.unableToClosePooledConnection=Unable to close pooled connection. +connectionPool.unableToCreateInitialConnections=Unable to create initial connections of pool. +connectionPool.unableToInformInterceptorOfPoolStart=Unable to inform interceptor of pool start. +connectionPool.unableToInstantiateInterceptorChain=Unable to instantiate interceptor chain. +connectionPool.unableToRegisterMBean=Unable to register the pooled connection MBean. +connectionPool.unableToResetInterceptor=Unable to reset interceptor [{0}]. +connectionPool.unableToReturnConnection=Unable to return connection [{0}] to the pool, closing it. +connectionPool.unableToSendRequestHint=Unable to send the request boundary hint [{0}] +connectionPool.unableToStartJmx=Unable to start JMX integration for connection pool. Instance[{0}] can''t be monitored. +connectionPool.unableToTestIdleConnection=Unable to test idle connection [{0}], closing it. +connectionPool.unableToTerminateTransaction=Unable to terminate transaction, connection will be closed. +connectionPool.validationQueryFailed=Validation Query Failed, enable logValidationErrors for more details. + +connectionPool.asyncBorrowConnectionReleased=The pooled connection served to this asynchronous borrow was released before it could be set up; no connection was borrowed, borrow the pool again. + +connectionState.unableToRestoreAutoCommit=Unable to restore the configured auto-commit state {0} on the connection. +connectionState.unableToRestoreCatalog=Unable to restore the configured default catalog {0} on the connection. +connectionState.unableToRestoreReadOnly=Unable to restore the configured read-only state {0} on the connection. +connectionState.unableToResetTransactionIsolation=Unable to reset transaction isolation state to connection. The configured level {0} will not be retried on this session; it keeps its current isolation level. +connectionState.resetStateToNull=Reset state to null as an exception occurred while calling method[{0}]. +connectionState.unableToTerminatePendingTransaction=Unable to check for, or terminate, the pending transaction before restoring the configured connection state. + +dataSource.mbeanNotRegistered=JDBC pool MBean [{0}] not registered: the pool has not been created yet or has already been closed. +dataSource.unableToCreateObjectName=Unable to create object name for JDBC pool. +dataSource.unableToRegisterMBean=Unable to register JDBC pool MBean. + +dataSourceFactory.cannotSetDataSourceString=Can''t set dataSource property as a string "{0}". Either carry the javax.sql.DataSource object itself under the dataSource attribute of the Reference, or use the dataSourceJNDI attribute to name a data source bound in JNDI. +dataSourceFactory.invalidBoolean=Invalid boolean value ''{0}'' for property {1} +dataSourceFactory.invalidClassName={0} is not a valid class name/type for this JNDI factory. +dataSourceFactory.invalidProperty={0} is not a valid property, it will be ignored. +dataSourceFactory.invalidSetting={0} is not a valid setting, it will have no effect. +dataSourceFactory.jndiContextNull=dataSourceJNDI property is configured, but local JNDI context is null. +dataSourceFactory.jndiLookupFailed=Unable to create the connection pool: the name [{0}] configured through the ''dataSourceJNDI'' attribute was not found in the local JNDI context nor in the InitialContext. The pool is built around the data source that name refers to; check that the name is correct and that the data source is bound and visible to the application before the pool is created. +dataSourceFactory.jndiNameNotFound=The name "{0}" cannot be found in the InitialContext. + +dataSourceProxy.alternateUsernameIgnored=alternateUsernameAllowed is set to false so the provided user name [{0}] and associated password have been ignored +dataSourceProxy.connectionNotXA=Connection from pool does not implement javax.sql.XAConnection +dataSourceProxy.dataSourceClosed=DataSource has been closed. +dataSourceProxy.errorClosingPool=Error during connection pool closure. +dataSourceProxy.errorCreatingPool=Error during connection pool creation. +dataSourceProxy.notAWrapper=Not a wrapper of {0} +dataSourceProxy.poolConfigurationNull=PoolConfiguration cannot be null. +dataSourceProxy.unableToParseConnectionProperties=Unable to parse connection properties. +dataSourceProxy.unableToPurgePool=Unable to purge pool. + +disposableConnectionFacade.pooledConnectionClosed=PooledConnection has already been closed. + +fairBlockingQueue.itemFutureAbandoned=The waiter of this future timed out on an earlier get() call and was deregistered from the queue; the future can no longer receive an item +fairBlockingQueue.itemFutureInstantiationError=ItemFuture incorrectly instantiated. Bug in the code? +fairBlockingQueue.unsupportedClear=void clear() +fairBlockingQueue.unsupportedContainsAll=boolean containsAll(Collection<?> c) +fairBlockingQueue.unsupportedDrainTo=int drainTo(Collection<? super E> c, int maxElements) +fairBlockingQueue.unsupportedElement=E element() +fairBlockingQueue.unsupportedPeek=E peek() +fairBlockingQueue.unsupportedRemove=E remove() +fairBlockingQueue.unsupportedRemoveAll=boolean removeAll(Collection<?> c) +fairBlockingQueue.unsupportedRetainAll=boolean retainAll(Collection<?> c) +fairBlockingQueue.unsupportedToArray=Object[] toArray() +fairBlockingQueue.unsupportedToArrayT=<T> T[] toArray(T[] a) + +genericNamingResourcesFactory.classNotFound=Class [{0}] of reference [{1}] was not found +genericNamingResourcesFactory.constructorThrew=The constructor of class [{0}] of reference [{1}] threw an exception and the object cannot be created +genericNamingResourcesFactory.illegalAccessExceptionSettingProperty=IllegalAccessException setting property [{0}] with value [{1}] on [{2}] +genericNamingResourcesFactory.noResourceType=No resource type (the "type" attribute) is defined for reference [{0}]; GenericNamingResourcesFactory needs the class of the object to create. +genericNamingResourcesFactory.noUsableConstructor=Class [{0}] of reference [{1}] has no usable public no-argument constructor and cannot be created by this factory +genericNamingResourcesFactory.propertyNotApplied=Property [{0}] was not applied to [{1}]: no usable setter found, or the configured value could not be applied. +genericNamingResourcesFactory.securityExceptionSettingProperty=SecurityException setting property [{0}] with value [{1}] on [{2}] +genericNamingResourcesFactory.setterThrew=Setter for property [{0}] with value [{1}] threw an exception on [{2}] +genericNamingResourcesFactory.unableToSetProperty=Unable to set property [{0}] with value [{1}] on [{2}] + +jmxConnectionPool.droppingNotification=Dropping notification of type [{0}] for pool [{1}]: the notification delivery queue ({2} deliveries) is full + +jmxUtil.jmxRegistrationFailed=Jmx registration failed. +jmxUtil.jmxUnregistrationFailed=Jmx unregistration failed. + +poolProperties.invalidInterceptorProperty=Invalid interceptor property ''{0}'', missing ''='', in jdbcInterceptors value [{1}] +poolProperties.layeredPoolsNotAllowed=Layered pools are not allowed. +poolProperties.validatorCannotInstantiate=An object of class {0} cannot be instantiated. Make sure that it includes an implicit or explicit no-arg constructor. +poolProperties.validatorClassNotFound=The class {0} cannot be found. +poolProperties.validatorInaccessible=The class {0} or its no-arg constructor are inaccessible. +poolProperties.validatorNotValidator=The class {0} does not implement the Validator interface. + +pooledConnection.cannotReestablish=A connection once released, can''t be reestablished. +pooledConnection.commitFailed=Failed to commit transaction +pooledConnection.connectionPoolDataSourceNullConnection=ConnectionPoolDataSource {0} returned a null connection for the pooled connection handle +pooledConnection.customValidationFailed=Custom validation through {0} failed. +pooledConnection.customValidationThrew=Custom validation through {0} threw an exception. +pooledConnection.dataSourceNullConnection=DataSource {0} returned a null connection +pooledConnection.discardedStateChange=Unable to change the state once the connection has been discarded +pooledConnection.disconnected=Connection has been disconnected. +pooledConnection.driverReturnedNull=Driver:{0} returned null for URL:{1} +pooledConnection.interceptorDisconnectedFailed=Interceptor threw an exception from the disconnected() event; ignoring it so that the physical connection can be closed. +pooledConnection.interceptorResetFailed=Interceptor [{0}] threw an exception from reset(); continuing with the rest of the chain. +pooledConnection.isValidFailed=isValid() failed. +pooledConnection.isValidReturnedFalse=isValid() returned false. +pooledConnection.rollbackFailed=Failed to rollback transaction +pooledConnection.sqlValidationError=SQL Validation error +pooledConnection.unableToClearWarnings=Unable to clear warnings on the connection. +pooledConnection.unknownDataSource=DataSource is of unknown class:{0} +pooledConnection.xaDataSourceNullConnection=XADataSource {0} returned a null connection for the XA connection handle + +proxyConnection.connectionClosed=Connection has already been closed. +proxyConnection.notAWrapper=Not a wrapper of {0} +proxyConnection.notXAConnection=The pooled connection is not an XA connection; method [{0}] cannot be dispatched. + +queryTimeoutInterceptor.invalidQueryTimeout=[QueryTimeoutInterceptor] The configured queryTimeout [{0}] is not an integer number of seconds and is not applied: statements created through this configuration keep the default {1}-second query timeout. Correct the value in the jdbcInterceptors configuration to set the timeout that was meant to be configured. +queryTimeoutInterceptor.queryTimeoutRefused=[QueryTimeoutInterceptor] Unable to set the query timeout of {0} seconds on a statement of this connection: {1}. The driver does not apply the timeout, so statements created on this physical connection run without a query timeout. Refusals are not logged again on this connection. + +resetAbandonedTimer.resultSetClosed=ResultSet closed. +resetAbandonedTimer.statementClosed=Statement closed. +resetAbandonedTimer.unableToCreateTimerResultSetProxy=Unable to create timer result set proxy for {0}. +resetAbandonedTimer.unableToCreateTimerStatementProxy=Unable to create timer statement proxy for {0}. + +slowQueryReport.connectionClosedOrAbandoned=Connection has already been closed or abandoned +slowQueryReport.failedQueryReport=Failed Query Report SQL={0}; time={1} ms; +slowQueryReport.poolNameInUse=Connection pool name [{0}] is already in use by another live pool; SlowQueryReport statistics are keyed by pool name, so both pools report into the same statistics map. +slowQueryReport.slowQueryReport=Slow Query Report SQL={0}; time={1} ms; + +slowQueryReportJmx.jmxDeregistrationFailed=Jmx deregistration failed. +slowQueryReportJmx.jmxRegistrationFailed=Jmx registration of [{0}] failed, no JMX data will be exposed for the query stats until a registration succeeds. The registration is retried by later borrows; repeated failures are logged at debug level. +slowQueryReportJmx.jmxRegistrationFailedNoData=Jmx registration failed, no JMX data will be exposed for the query stats. +slowQueryReportJmx.jmxRegistrationInUse=Jmx registration of [{0}] failed: the name is already in use by another MBean. The registration is retried by later borrows; repeated failures are logged at debug level. +slowQueryReportJmx.noJmxSupport={0}- No JMX support, composite type was not found. +slowQueryReportJmx.unableToInitCompositeType=Unable to initialize composite data type for JMX stats and notifications. + +statementCache.connectionClosedOrAbandoned=Connection has already been closed or abandoned +statementCache.nullKey=Null key +statementCache.unableToCloseDiscardedStatement=Unable to close statement [{0}] that the statement cache is discarding. + +statementDecoratorInterceptor.statementClosed=Statement closed. + +statementFacade.resultSetClosed=ResultSet closed. +statementFacade.resultSetClosedConnectionReturned=ResultSet closed. The pooled connection this result set was read from has been returned to the pool. +statementFacade.statementClosed=Statement closed. +statementFacade.statementClosedConnectionReturned=Statement closed. The pooled connection this statement was created from has been returned to the pool. + +statementFinalizer.statementNotClosed=Statement created, but was not closed at: +statementFinalizer.unableToCreateTrackingProxy=Unable to create statement tracking proxy. + +trapException.uncaughtUnderlyingException=Uncaught underlying exception. + +xaDataSource.dataSourceNotXA=The connection pool [{0}] cannot provide XA connections: the data source configured through the ''dataSource'' or ''dataSourceJNDI'' attribute ({1}) does not implement javax.sql.XADataSource. +xaDataSource.jndiNotResolved=The connection pool [{0}] cannot provide XA connections: the name "{1}" set through the ''dataSourceJNDI'' attribute has not been resolved into a data source; the name is only looked up when the pool is created through the DataSourceFactory. Set the ''dataSource'' attribute to a javax.sql.XADataSource provided by the JDBC driver. +xaDataSource.noDataSource=The connection pool [{0}] cannot provide XA connections: neither the ''dataSource'' nor the ''dataSourceJNDI'' attribute is set, so only plain JDBC connections from a JDBC driver and URL can be pooled. Set the ''dataSource'' or ''dataSourceJNDI'' attribute to a javax.sql.XADataSource provided by the JDBC driver. diff --git a/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/util/MessageFactory.java b/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/util/MessageFactory.java new file mode 100644 index 0000000000..90520db49d --- /dev/null +++ b/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/util/MessageFactory.java @@ -0,0 +1,116 @@ +/* + * 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.jdbc.pool.util; + +import java.text.Format; +import java.text.MessageFormat; +import java.text.NumberFormat; +import java.util.MissingResourceException; +import java.util.ResourceBundle; + +/** + * Factory for creating localized JDBC pool messages. + */ +public final class MessageFactory { + + private static final ResourceBundle DEFAULT_BUNDLE = + ResourceBundle.getBundle("org.apache.tomcat.jdbc.pool.util.LocalStrings"); + + private static final MessageFactory DEFAULT_MESSAGE_FACTORY = new MessageFactory(DEFAULT_BUNDLE); + + /** + * Get a localized message. + * + * @param key the message key + * + * @return the message + */ + public static String get(final String key) { + return DEFAULT_MESSAGE_FACTORY.getInternal(key); + } + + /** + * Get a localized message with arguments. + * + * @param key the message key + * @param args the arguments + * + * @return the message + */ + public static String get(final String key, final Object... args) { + return DEFAULT_MESSAGE_FACTORY.getInternal(key, args); + } + + private final ResourceBundle bundle; + + /** + * Constructor. + * + * @param bundle the resource bundle + */ + public MessageFactory(ResourceBundle bundle) { + this.bundle = bundle; + } + + /** + * Get a message from the bundle. + * + * @param key the message key + * + * @return the message + */ + protected String getInternal(final String key) { + try { + return bundle.getString(key); + } catch (MissingResourceException e) { + return key; + } + } + + /** + * Get a message from the bundle with arguments. + * + * @param key the message key + * @param args the arguments + * + * @return the message + */ + protected String getInternal(final String key, final Object... args) { + String value = getInternal(key); + + MessageFormat mf = new MessageFormat(value); + Format[] formats = null; + + // Unless an argument has been explicitly configured to use a number + // format, convert all Number arguments to String else MessageFormat may + // try to format them in unexpected ways. + if (args != null) { + for (int i = 0; i < args.length; i++) { + if (args[i] instanceof Number) { + if (formats == null) { + formats = mf.getFormatsByArgumentIndex(); + } + if (i < formats.length && !(formats[i] instanceof NumberFormat)) { + args[i] = args[i].toString(); + } + } + } + } + + return mf.format(args, new StringBuffer(), null).toString(); + } +} diff --git a/modules/jdbc-pool/src/test/java/org/apache/tomcat/jdbc/pool/interceptor/TestSlowQueryReportLogging.java b/modules/jdbc-pool/src/test/java/org/apache/tomcat/jdbc/pool/interceptor/TestSlowQueryReportLogging.java index 8b0b6c4595..d81d055d5b 100644 --- a/modules/jdbc-pool/src/test/java/org/apache/tomcat/jdbc/pool/interceptor/TestSlowQueryReportLogging.java +++ b/modules/jdbc-pool/src/test/java/org/apache/tomcat/jdbc/pool/interceptor/TestSlowQueryReportLogging.java @@ -232,7 +232,6 @@ class TestSlowQueryReportLogging extends JdbcPoolBaseTest { } /** - * Captures what {@link SlowQueryReport} logs, following the handler * idiom of the pool's other diagnostic tests. The canary record - * written through the very JULI logger the interceptor logs through, --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
