This will typically be the native driver Connection
* or a wrapper from a connection pool.
*
* @return the underlying Connection (never {@code null})
*/
Connection getTargetConnection();
}
PK CtiJV[T + src/play/db/LoggingConnectionDecorator.javapackage play.db;
import javax.sql.DataSource;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.sql.Connection;
import java.sql.PreparedStatement;
import static java.lang.reflect.Proxy.newProxyInstance;
import static play.db.Reflection.invokeUnwrappingExceptions;
public class LoggingConnectionDecorator implements InvocationHandler {
private final Connection connection;
LoggingConnectionDecorator(Connection connection) {
this.connection = connection;
}
@Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object result = invokeUnwrappingExceptions(method, connection, args);
if ("prepareStatement".equals(method.getName())) {
return newProxyInstance(PreparedStatement.class.getClassLoader(),
new Class>[] {PreparedStatement.class}, new LoggingStatementDecorator((PreparedStatement) result, (String) args[0]));
}
return result;
}
public static DataSource loggingConnectionDataSourceProxy(DataSource datasource) {
return (DataSource) Proxy.newProxyInstance(datasource.getClass().getClassLoader(), new Class>[]{DataSource.class}, (proxy, method, args) -> {
Object result = invokeUnwrappingExceptions(method, datasource, args);
if ("getConnection".equals(method.getName())) {
return Proxy.newProxyInstance(Connection.class.getClassLoader(), new Class>[]{Connection.class}, new LoggingConnectionDecorator((Connection) result));
}
return result;
});
}
}
PK CtiJKl5 5 src/play/db/LogEntry.javapackage play.db;
import java.util.concurrent.atomic.AtomicLong;
import java.util.regex.Pattern;
public class LogEntry {
private static final int SLOW_AVERAGE_SQL_THRESHOLD_IN_MS = 100;
private static final int SLOW_TOTAL_SQL_THRESHOLD_IN_MS = 200;
public final String sql;
public final String request;
public final String sessionId;
private final AtomicLong totalDuration = new AtomicLong();
private final AtomicLong count = new AtomicLong();
private static final Pattern shortenSelect = Pattern.compile("\\bselect\\s.+?\\sfrom\\s", Pattern.DOTALL);
private static final Pattern shortenUpdate = Pattern.compile("(\\bupdate\\s.+?\\sset)\\s.+?\\swhere\\s", Pattern.DOTALL);
LogEntry(String sql, String requestId, String sessionId) {
this.sql = sql;
this.request = requestId;
this.sessionId = sessionId;
}
public boolean isSlow() {
return totalDuration.get() > SLOW_TOTAL_SQL_THRESHOLD_IN_MS ||
totalDuration.get()/count.get() > SLOW_AVERAGE_SQL_THRESHOLD_IN_MS;
}
public String getShortenedSQL() {
String result = shortenSelect.matcher(sql).replaceAll("select ... from ");
return shortenUpdate.matcher(result).replaceAll("$1 ... where ").trim();
}
public void addExecution(long duration) {
totalDuration.addAndGet(duration);
count.incrementAndGet();
}
}
PK CtiJ3 src/play/db/Reflection.javapackage play.db;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
class Reflection {
public static This class is meant to be subclassed, with subclasses overriding only
* those methods (such as {@link #getConnection()}) that should not simply
* delegate to the target DataSource.
*
* @author Juergen Hoeller
* @see #getConnection
* @since 1.1
*/
class DelegatingDataSource implements DataSource {
private DataSource targetDataSource;
/**
* Create a new DelegatingDataSource.
*
* @see #setTargetDataSource
*/
public DelegatingDataSource() {
}
/**
* Create a new DelegatingDataSource.
*
* @param targetDataSource the target DataSource
*/
public DelegatingDataSource(DataSource targetDataSource) {
setTargetDataSource(targetDataSource);
}
/**
* Set the target DataSource that this DataSource should delegate to.
*/
public void setTargetDataSource(DataSource targetDataSource) {
this.targetDataSource = targetDataSource;
}
/**
* Return the target DataSource that this DataSource should delegate to.
*/
public DataSource getTargetDataSource() {
return this.targetDataSource;
}
@Override
public Connection getConnection() throws SQLException {
return getTargetDataSource().getConnection();
}
@Override
public Connection getConnection(String username, String password) throws SQLException {
return getTargetDataSource().getConnection(username, password);
}
@Override
public PrintWriter getLogWriter() throws SQLException {
return getTargetDataSource().getLogWriter();
}
@Override
public void setLogWriter(PrintWriter out) throws SQLException {
getTargetDataSource().setLogWriter(out);
}
@Override
public int getLoginTimeout() throws SQLException {
return getTargetDataSource().getLoginTimeout();
}
@Override
public void setLoginTimeout(int seconds) throws SQLException {
getTargetDataSource().setLoginTimeout(seconds);
}
//---------------------------------------------------------------------
// Implementation of JDBC 4.0's Wrapper interface
//---------------------------------------------------------------------
@Override
@SuppressWarnings("unchecked")
public