do not log passwords
This commit is contained in:
parent
7378b91c28
commit
6127f11914
7 changed files with 72 additions and 23 deletions
|
@ -379,7 +379,7 @@ public class Pool implements BagStateListener {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Recycle PoolEntry (add back to the pool)
|
* Recycle PoolEntry, add back to the pool.
|
||||||
*
|
*
|
||||||
* @param poolEntry the PoolEntry to recycle
|
* @param poolEntry the PoolEntry to recycle
|
||||||
*/
|
*/
|
||||||
|
@ -957,7 +957,7 @@ public class Pool implements BagStateListener {
|
||||||
writeMethod.invoke(target, Class.forName(propValue.toString()).getDeclaredConstructor().newInstance());
|
writeMethod.invoke(target, Class.forName(propValue.toString()).getDeclaredConstructor().newInstance());
|
||||||
} catch (InstantiationException | ClassNotFoundException e) {
|
} catch (InstantiationException | ClassNotFoundException e) {
|
||||||
logger.log(Level.FINE, () ->
|
logger.log(Level.FINE, () ->
|
||||||
MessageFormat.format("class not found or could not instantiate it (Default constructor): {0}",
|
MessageFormat.format("class not found or could not instantiate it (default constructor): {0}",
|
||||||
propValue));
|
propValue));
|
||||||
writeMethod.invoke(target, propValue);
|
writeMethod.invoke(target, propValue);
|
||||||
}
|
}
|
||||||
|
|
|
@ -567,11 +567,11 @@ public class PoolConfig {
|
||||||
this.threadFactory = threadFactory;
|
this.threadFactory = threadFactory;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Class<?> attemptFromContextLoader(final String driverClassName) {
|
private Class<?> attemptFromContextLoader(String driverClassName) {
|
||||||
final ClassLoader threadContextClassLoader = Thread.currentThread().getContextClassLoader();
|
ClassLoader threadContextClassLoader = Thread.currentThread().getContextClassLoader();
|
||||||
if (threadContextClassLoader != null) {
|
if (threadContextClassLoader != null) {
|
||||||
try {
|
try {
|
||||||
final Class<?> driverClass = threadContextClassLoader.loadClass(driverClassName);
|
Class<?> driverClass = threadContextClassLoader.loadClass(driverClassName);
|
||||||
logger.log(Level.FINE, "Driver class found in Thread context class loader:" +
|
logger.log(Level.FINE, "Driver class found in Thread context class loader:" +
|
||||||
driverClassName + " " + threadContextClassLoader);
|
driverClassName + " " + threadContextClassLoader);
|
||||||
return driverClass;
|
return driverClass;
|
||||||
|
@ -580,7 +580,6 @@ public class PoolConfig {
|
||||||
driverClassName + " " + threadContextClassLoader + " " + this.getClass().getClassLoader());
|
driverClassName + " " + threadContextClassLoader + " " + this.getClass().getClassLoader());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -622,7 +621,7 @@ public class PoolConfig {
|
||||||
/**
|
/**
|
||||||
* @return null if string is null or empty
|
* @return null if string is null or empty
|
||||||
*/
|
*/
|
||||||
private static String getNullIfEmpty(final String text) {
|
private static String getNullIfEmpty(String text) {
|
||||||
return text == null ? null : text.trim().isEmpty() ? null : text.trim();
|
return text == null ? null : text.trim().isEmpty() ? null : text.trim();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -40,7 +40,7 @@ public class PoolEntry implements BagEntry {
|
||||||
|
|
||||||
private final boolean isAutoCommit;
|
private final boolean isAutoCommit;
|
||||||
|
|
||||||
public PoolEntry(Connection connection, Pool pool, final boolean isReadOnly, final boolean isAutoCommit) {
|
public PoolEntry(Connection connection, Pool pool, boolean isReadOnly, boolean isAutoCommit) {
|
||||||
this.connection = connection;
|
this.connection = connection;
|
||||||
this.pool = pool;
|
this.pool = pool;
|
||||||
this.isReadOnly = isReadOnly;
|
this.isReadOnly = isReadOnly;
|
||||||
|
@ -70,7 +70,7 @@ public class PoolEntry implements BagEntry {
|
||||||
*
|
*
|
||||||
* @param lastAccessed last access time-stamp
|
* @param lastAccessed last access time-stamp
|
||||||
*/
|
*/
|
||||||
public void recycle(final long lastAccessed) {
|
public void recycle(long lastAccessed) {
|
||||||
if (connection != null) {
|
if (connection != null) {
|
||||||
this.lastAccessed = lastAccessed;
|
this.lastAccessed = lastAccessed;
|
||||||
pool.recycle(this);
|
pool.recycle(this);
|
||||||
|
@ -82,11 +82,11 @@ public class PoolEntry implements BagEntry {
|
||||||
*
|
*
|
||||||
* @param endOfLife this PoolEntry/Connection's end of life {@link ScheduledFuture}
|
* @param endOfLife this PoolEntry/Connection's end of life {@link ScheduledFuture}
|
||||||
*/
|
*/
|
||||||
public void setFutureEol(final ScheduledFuture<?> endOfLife) {
|
public void setFutureEol(ScheduledFuture<?> endOfLife) {
|
||||||
this.endOfLife = endOfLife;
|
this.endOfLife = endOfLife;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Connection createProxyConnection(final ProxyLeakTask leakTask, final long now) {
|
public Connection createProxyConnection(ProxyLeakTask leakTask, long now) {
|
||||||
return ProxyFactory.getProxyConnection(this, connection, openStatements, leakTask, now, isReadOnly, isAutoCommit);
|
return ProxyFactory.getProxyConnection(this, connection, openStatements, leakTask, now, isReadOnly, isAutoCommit);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -102,7 +102,7 @@ public class PoolEntry implements BagEntry {
|
||||||
this.evict = true;
|
this.evict = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void evict(final String closureReason) {
|
public void evict(String closureReason) {
|
||||||
pool.closeConnection(this, closureReason);
|
pool.closeConnection(this, closureReason);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -17,15 +17,15 @@ import java.util.stream.Collectors;
|
||||||
* This is a specialized concurrent bag that achieves superior performance
|
* This is a specialized concurrent bag that achieves superior performance
|
||||||
* to {@link java.util.concurrent.LinkedBlockingQueue} and
|
* to {@link java.util.concurrent.LinkedBlockingQueue} and
|
||||||
* {@link java.util.concurrent.LinkedTransferQueue} for the purposes of a
|
* {@link java.util.concurrent.LinkedTransferQueue} for the purposes of a
|
||||||
* connection pool. It uses {@link ThreadLocal} storage when possible to avoid
|
* connection pool. It uses {@link ThreadLocal} storage when possible to avoid
|
||||||
* locks, but resorts to scanning a common collection if there are no
|
* locks, but resorts to scanning a common collection if there are no
|
||||||
* available items in the {@link ThreadLocal} list. Not-in-use items in the
|
* available items in the {@link ThreadLocal} list. Not-in-use items in the
|
||||||
* {@link ThreadLocal} lists can be "stolen" when the borrowing thread has none
|
* {@link ThreadLocal} lists can be "stolen" when the borrowing thread has none
|
||||||
* of its own. It is a "lock-less" implementation using a specialized
|
* of its own. It is a "lock-less" implementation using a specialized
|
||||||
* {@link AbstractQueuedLongSynchronizer} to manage cross-thread signaling.
|
* {@link AbstractQueuedLongSynchronizer} to manage cross-thread signaling.
|
||||||
* Note that items that are "borrowed" from the bag are not actually
|
* Note that items that are "borrowed" from the bag are not actually
|
||||||
* removed from any collection, so garbage collection will not occur
|
* removed from any collection, so garbage collection will not occur
|
||||||
* even if the reference is abandoned. Thus care must be taken to
|
* even if the reference is abandoned. Thus care must be taken to
|
||||||
* {@link Bag#requite(T)} borrowed objects otherwise a memory leak will result.
|
* {@link Bag#requite(T)} borrowed objects otherwise a memory leak will result.
|
||||||
* Only the {@link Bag#remove(T)} method can completely remove an object.
|
* Only the {@link Bag#remove(T)} method can completely remove an object.
|
||||||
*
|
*
|
||||||
|
|
|
@ -143,9 +143,15 @@ public interface ClockSource {
|
||||||
return sb.toString();
|
return sb.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
TimeUnit[] TIMEUNITS_DESCENDING = {TimeUnit.DAYS, TimeUnit.HOURS, TimeUnit.MINUTES,
|
TimeUnit[] TIMEUNITS_DESCENDING = {
|
||||||
TimeUnit.SECONDS, TimeUnit.MILLISECONDS, TimeUnit.MICROSECONDS,
|
TimeUnit.DAYS,
|
||||||
TimeUnit.NANOSECONDS};
|
TimeUnit.HOURS,
|
||||||
|
TimeUnit.MINUTES,
|
||||||
|
TimeUnit.SECONDS,
|
||||||
|
TimeUnit.MILLISECONDS,
|
||||||
|
TimeUnit.MICROSECONDS,
|
||||||
|
TimeUnit.NANOSECONDS
|
||||||
|
};
|
||||||
|
|
||||||
String[] TIMEUNIT_DISPLAY_VALUES = {"ns", "µs", "ms", "s", "m", "h", "d"};
|
String[] TIMEUNIT_DISPLAY_VALUES = {"ns", "µs", "ms", "s", "m", "h", "d"};
|
||||||
|
|
||||||
|
|
|
@ -78,16 +78,16 @@ public class DriverDataSource implements DataSource {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
final String sanitizedUrl = jdbcUrl.replaceAll("([?&;]password=)[^&#;]*(.*)", "$1<masked>$2");
|
final String sanitizedUrl = jdbcUrl.replaceAll("([?&;][^&#;=]*[pP]assword=)[^&#;]*", "$1<masked>");
|
||||||
try {
|
try {
|
||||||
if (driver == null) {
|
if (driver == null) {
|
||||||
driver = DriverManager.getDriver(jdbcUrl);
|
driver = DriverManager.getDriver(jdbcUrl);
|
||||||
logger.fine("Loaded driver with class name for jdbcUrl: " + driver.getClass().getName() + " " + sanitizedUrl);
|
logger.fine("Loaded driver with class name for jdbcUrl " + driver.getClass().getName() + " " + sanitizedUrl);
|
||||||
} else if (!driver.acceptsURL(jdbcUrl)) {
|
} else if (!driver.acceptsURL(jdbcUrl)) {
|
||||||
throw new RuntimeException("Driver " + driverClassName + " claims to not accept jdbcUrl, " + sanitizedUrl);
|
throw new RuntimeException("Driver " + driverClassName + " claims to not accept jdbcUrl " + sanitizedUrl);
|
||||||
}
|
}
|
||||||
} catch (SQLException e) {
|
} catch (SQLException e) {
|
||||||
throw new RuntimeException("Failed to get driver instance for jdbcUrl=" + sanitizedUrl, e);
|
throw new RuntimeException("Failed to get driver instance for jdbcUrl " + sanitizedUrl, e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,44 @@
|
||||||
|
package org.xbib.io.pool.jdbc;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.xbib.jdbc.connection.pool.util.DriverDataSource;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Properties;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||||
|
import static org.junit.jupiter.api.Assertions.fail;
|
||||||
|
|
||||||
|
public class DriverDataSourceTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testJdbcUrlLogging() {
|
||||||
|
List<String> urls = Arrays.asList(
|
||||||
|
"jdbc:invalid://host/d_dlq?user=USER&password=SECRET",
|
||||||
|
"jdbc:invalid://host/d_dlq?user=USER&truststorePassword=SECRET",
|
||||||
|
"jdbc:invalid://host/d_dlq?a=b&password=SECRET&user=USER",
|
||||||
|
"jdbc:invalid://host/d_dlq?a=b&sslpassword=SECRET&user=USER",
|
||||||
|
"jdbc:invalid://host/d_dlq?a=b&sslpassword=SECRET&password=SECRET&user=USER",
|
||||||
|
"jdbc:invalid://host/d_dlq?truststorePassword=SECRET;user=USER&password=SECRET#extra",
|
||||||
|
"jdbc:invalid://host/d_dlq?sslpassword=SECRET&password=SECRET&trustPassword=SECRET&user=USER",
|
||||||
|
"jdbc:invalid://host/d_dlq?password=SECRET#user=USER;extra"
|
||||||
|
);
|
||||||
|
for (String url : urls) {
|
||||||
|
testExceptionMessage(url);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void testExceptionMessage(String jdbcUrl) {
|
||||||
|
try {
|
||||||
|
new DriverDataSource(jdbcUrl, null, new Properties(), null, null);
|
||||||
|
fail();
|
||||||
|
} catch (RuntimeException e) {
|
||||||
|
String msg = e.getMessage();
|
||||||
|
assertTrue(msg.contains("jdbc:invalid://host/d_dlq"));
|
||||||
|
assertTrue(msg.contains("user=USER"));
|
||||||
|
assertFalse(msg.contains("SECRET"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue