12 Commits

Author SHA1 Message Date
arthur.blake 7355247886 finalize release date for next beta release in CHANGES file
update copyright date in license file
2010-06-10 00:16:40 +00:00
arthur.blake 00369eba9f fix possible null pointer issue with setBlob and setClob (Issue 21) 2010-06-07 14:04:34 +00:00
arthur.blake a02f682e7c fix; Timestamp check has to be done first because Timestamp extends Date 2010-05-28 01:03:49 +00:00
arthur.blake a5290edf4b Issue 14; add support for the newer oracle.jdbc.OracleDriver driver (the older oracle.jdbc.driver.OracleDriver driver is still supported as well.) 2010-05-28 00:37:22 +00:00
arthur.blake 9769dbc6dd add new option, log4jdbc.suppress.generated.keys.exception for ColdFusion 2010-05-27 23:49:12 +00:00
arthur.blake b0b69fdc64 add new option, log4jdbc.trim.sql to trim the SQL before logging it (previously the sql was always trimmed) 2010-05-24 11:07:46 +00:00
arthur.blake 1dd40a2f76 Issue 18; Fix non-threadsafe usage of SimpleDateFormat 2010-05-15 18:24:24 +00:00
arthur.blake bbf255e0b4 look first for log4jdbc property settings in optional log4jdbc.properties in the classpath 2010-05-12 13:17:28 +00:00
arthur.blake 4ee6d5f745 upgrade from slf4j 1.5.0 to 1.6.0 2010-05-11 15:54:39 +00:00
arthur.blake c83e89c194 bump version numbers for upcoming 1.2 beta 2 release 2010-05-10 20:31:46 +00:00
arthur.blake 5ac146eb77 add system property log4jdbc.auto.load.popular.drivers for disabling auto-loading of drivers 2010-05-10 20:30:48 +00:00
arthur.blake cab8caa20a don't build tar.gz file in release target, and use consistent jdk in javadoc.cmd 2010-03-21 02:26:36 +00:00
23 changed files with 382 additions and 171 deletions
+26
View File
@@ -1,3 +1,29 @@
2010-06-09 1.2 beta 2 Release
o add new option, log4jdbc.auto.load.popular.drivers for
disabling auto-loading of drivers
o look first for log4jdbc property settings in optional
log4jdbc.properties file in the classpath.
o Fix non-threadsafe usage of SimpleDateFormat (Issue 18)
o add new option, log4jdbc.trim.sql to trim the SQL before logging
it.
o add new option, log4jdbc.suppress.generated.keys.exception that
will ignore any exception produced by the method,
Statement.getGeneratedKeys(). This flag is useful in Coldfusion
environments which typically call this method after every update,
even if unwarranted, and ignoring the exception, thus clogging up
the logs with these exception reports.
o add support for the newer oracle.jdbc.OracleDriver driver (the
older oracle.jdbc.driver.OracleDriver driver is still supported
as well) and add corrected date formatting for Oracle.
o fix possible null pointer issue with setBlob and setClob (Issue 21)
2010-03-20 1.2 beta 1 Release
o Check for exception that should not, but in some cases could
+1 -1
View File
@@ -1,6 +1,6 @@
log4jdbc is open source software, released under the Apache License, Version 2.0:
Copyright 2007-2008 Arthur Blake
Copyright 2007-2010 Arthur Blake
Licensed under the Apache License, Version 2.0 (the "License");
you may not use log4jdbc except in compliance with the License.
+2
View File
@@ -18,3 +18,5 @@ o review dumpedSql method - make auto line breaking option (& num chars used) b
o need log4jdbc.debug.stack.regex so that the stack matching can take place via regex
o maven2 repository support
o this may be a better solution to SimpleDateFormat contention issue: http://www.javaspecialists.eu/archive/Issue172.html
Binary file not shown.
Binary file not shown.
+4 -4
View File
@@ -1,5 +1,5 @@
To build log4jdbc, you must have Ant 1.6.5 or later installed,
and JDK 1.4 and JDK 1.6 installed.
log4jdbc is built with Ant 1.8.x, JDK 1.4.x and JDK 1.6.x
The build.cmd file is useful for building both the jdbc 3 version (JDK 1.4) and the jdbc 4 version (under JDK 1.6) under windows.
The javadoc.cmd file is useful for building javadoc (requires the 3rd party ydoc tool)
The build.cmd file is useful for building both the jdbc 3 version (JDK 1.4) and
the jdbc 4 version (under JDK 1.6) under windows. The javadoc.cmd file is
useful for building javadoc (requires the 3rd party ydoc tool)
+3 -3
View File
@@ -9,15 +9,15 @@ REM if you don't happen to have it laying around,
REM as the ant script properly sets the source
REM and target java versions anyway.
set ANT_HOME=c:\apache-ant-1.7.1
set ANT_HOME=c:\apache-ant-1.8.1
set JAVA_HOME=C:\jdk\1.4.2_18
set JAVA_HOME=C:\jdk\1.4.2_19
set PATH=%JAVA_HOME%\bin;%ANT_HOME%\bin
call java -version
call ant -Djdbc.level=3 -Djvm.ver=1.4 all
set JAVA_HOME=C:\jdk\1.6.0_16
set JAVA_HOME=C:\jdk\1.6.0_18
set PATH=%JAVA_HOME%\bin;%ANT_HOME%\bin
call java -version
+2 -9
View File
@@ -49,7 +49,7 @@
<!-- release version -->
<property name="version" value="1.2beta1"/>
<property name="version" value="1.2beta2"/>
<target name="all" depends="cleancompile,compile,cleanjar,jar"/>
@@ -70,7 +70,7 @@
<target name="compile" description="compile all the source code">
<javac source="${jvm.ver}" target="${jvm.ver}" srcdir="${src}" destdir="${classes}"
deprecation="true" debug="true">
deprecation="true" debug="true" includeAntRuntime="false">
<classpath>
<pathelement location="$src"/>
<fileset dir="lib">
@@ -102,8 +102,6 @@
<target name="cleanrelease" description="clean up any release files">
<delete file="../log4jdbc-${version}.zip"/>
<delete file="../log4jdbc-${version}.tar"/>
<delete file="../log4jdbc-${version}.tar.gz"/>
</target>
<target name="clean" depends="cleanrelease,cleanjavadoc,cleanjar,cleancompile" description="clean up all build artifacts"/>
@@ -112,11 +110,6 @@
<zip destfile="../log4jdbc-${version}.zip">
<zipfileset dir="." prefix="log4jdbc-${version}" excludes="*.zip,*.tar.gz,*,iml,*.ipr,*.iws,thirdparty-stuff/**,classes*/**"/>
</zip>
<tar destfile="../log4jdbc-${version}.tar">
<tarfileset dir="." prefix="log4jdbc-${version}" excludes="*.zip,*.tar.gz,*,iml,*.ipr,*.iws,thirdparty-stuff/**,classes*/**"/>
</tar>
<gzip destfile="../log4jdbc-${version}.tar.gz" src="../log4jdbc-${version}.tar"/>
<delete file="../log4jdbc-${version}.tar"/>
</target>
<!-- make the javadoc (or ydoc which includes UML diagrams) -->
+2 -2
View File
@@ -4,7 +4,7 @@ setlocal
REM invoke the 1.4 and the 1.6 jvm each in turn
REM for JDBC 3 and JDBC 4 versions respectively
set ANT_HOME=c:\apache-ant-1.7.1
set ANT_HOME=c:\apache-ant-1.8.1
set ANT_OPTS=-Xmx512m
set JAVA_HOME=C:\jdk\1.4.2_19
@@ -13,7 +13,7 @@ set PATH=%JAVA_HOME%\bin;%ANT_HOME%\bin
call java -version
call ant -Djdbc.level=3 -Djvm.ver=1.4 ydoc.3
set JAVA_HOME=c:\jdk\1.6.0_16
set JAVA_HOME=c:\jdk\1.6.0_18
set PATH=%JAVA_HOME%\bin;%ANT_HOME%\bin
call java -version
+1 -1
View File
@@ -25,4 +25,4 @@ rem * profiling output report.
rem * *
rem *************************************************************************************************
java -Xmx1024m -classpath ..\build\log4jdbc3-1.2beta1.jar net.sf.log4jdbc.PostLogProfilerProcessor %*
java -Xmx1024m -classpath ..\build\log4jdbc3-1.2beta2.jar net.sf.log4jdbc.PostLogProfilerProcessor %*
+1 -1
View File
@@ -25,4 +25,4 @@
# * *
# *************************************************************************************************
java -Xmx1024m -classpath ../build/log4jdbc3-1.2beta1.jar net.sf.log4jdbc.PostLogProfilerProcessor $@
java -Xmx1024m -classpath ../build/log4jdbc3-1.2beta2.jar net.sf.log4jdbc.PostLogProfilerProcessor $@
+144 -60
View File
@@ -15,6 +15,8 @@
*/
package net.sf.log4jdbc;
import java.io.IOException;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.Driver;
@@ -33,9 +35,11 @@ import java.util.TreeSet;
* A JDBC driver which is a facade that delegates to one or more real underlying
* JDBC drivers. The driver will spy on any other JDBC driver that is loaded,
* simply by prepending <code>jdbc:log4</code> to the normal jdbc driver URL
* used by any other JDBC driver. The driver also loads several well known
* drivers at class load time, so that this driver can be "dropped in" to any
* java program that uses these drivers without making any code changes.
* used by any other JDBC driver. The driver, by default, also loads several
* well known drivers at class load time, so that this driver can be
* "dropped in" to any Java program that uses these drivers without making any
* code changes.
* <p/>
* The well known driver classes that are loaded are:
* <p/>
* <p/>
@@ -58,10 +62,15 @@ import java.util.TreeSet;
* </code>
* <p/>
* <p/>
* Additional drivers can be set via a system property: <b>log4jdbc.drivers</b>
* Additional drivers can be set via a property: <b>log4jdbc.drivers</b>
* This can be either a single driver class name or a list of comma separated
* driver class names.
* <p/>
* The autoloading behavior can be disabled by setting a property:
* <b>log4jdbc.auto.load.popular.drivers</b> to false. If that is done, then
* the only drivers that log4jdbc will attempt to load are the ones specified
* in <b>log4jdbc.drivers</b>.
* <p/>
* If any of the above driver classes cannot be loaded, the driver continues on
* without failing.
* <p/>
@@ -188,19 +197,38 @@ public class DriverSpy implements Driver
* under some circumstances.
*/
static boolean DumpFullDebugStackTrace;
/**
* Attempt to Automatically load a set of popular JDBC drivers?
*/
static boolean AutoLoadPopularDrivers;
/**
* Get a Long option from a system property and
* Trim SQL before logging it?
*/
static boolean TrimSql;
/**
* Coldfusion typically calls PreparedStatement.getGeneratedKeys() after
* every SQL update call, even if it's not warranted. This typically produces
* an exception that is ignored by Coldfusion. If this flag is true, then
* any exception generated by this method is also ignored by log4jdbc.
*/
static boolean SuppressGetGeneratedKeysException;
/**
* Get a Long option from a property and
* log a debug message about this.
*
* @param propName System property key.
* @param props Properties to get option from.
* @param propName property key.
*
* @return the value of that System property key, converted
* @return the value of that property key, converted
* to a Long. Or null if not defined or is invalid.
*/
private static Long getLongOption(String propName)
private static Long getLongOption(Properties props, String propName)
{
String propValue = System.getProperty(propName);
String propValue = props.getProperty(propName);
Long longPropValue = null;
if (propValue == null)
{
@@ -223,21 +251,24 @@ public class DriverSpy implements Driver
}
/**
* Get a Long option from a system property and
* Get a Long option from a property and
* log a debug message about this.
*
* @param props Properties to get option from.
* @param propName property key.
*
* @param propName System property key.
*
* @return the value of that System property key, converted
* @return the value of that property key, converted
* to a Long. Or null if not defined or is invalid.
*/
private static Long getLongOption(String propName, long defaultValue)
private static Long getLongOption(Properties props, String propName,
long defaultValue)
{
String propValue = System.getProperty(propName);
String propValue = props.getProperty(propName);
Long longPropValue;
if (propValue == null)
{
log.debug("x " + propName + " is not defined (using default of " + defaultValue +")");
log.debug("x " + propName + " is not defined (using default of " +
defaultValue +")");
longPropValue = new Long(defaultValue);
}
else
@@ -258,15 +289,16 @@ public class DriverSpy implements Driver
}
/**
* Get a String option from a system property and
* Get a String option from a property and
* log a debug message about this.
*
* @param propName System property key.
* @return the value of that System property key.
* @param props Properties to get option from.
* @param propName property key.
* @return the value of that property key.
*/
private static String getStringOption(String propName)
private static String getStringOption(Properties props, String propName)
{
String propValue = System.getProperty(propName);
String propValue = props.getProperty(propName);
if (propValue == null || propValue.length()==0)
{
log.debug("x " + propName + " is not defined");
@@ -280,18 +312,20 @@ public class DriverSpy implements Driver
}
/**
* Get a boolean option from a system property and
* Get a boolean option from a property and
* log a debug message about this.
*
*
* @param props Properties to get option from.
* @param propName property name to get.
* @param defaultValue default value to use if undefined.
*
* @return boolean value found in property, or defaultValue if no property
* found.
*/
private static boolean getBooleanOption(String propName, boolean defaultValue)
private static boolean getBooleanOption(Properties props, String propName,
boolean defaultValue)
{
String propValue = System.getProperty(propName);
String propValue = props.getProperty(propName);
boolean val;
if (propValue == null)
{
@@ -320,18 +354,52 @@ public class DriverSpy implements Driver
{
log.debug("... log4jdbc initializing ...");
// look for additional driver specified in system properties
DebugStackPrefix = getStringOption("log4jdbc.debug.stack.prefix");
InputStream propStream =
DriverSpy.class.getResourceAsStream("/log4jdbc.properties");
Properties props = new Properties(System.getProperties());
if (propStream != null)
{
try
{
props.load(propStream);
}
catch (IOException e)
{
log.debug("ERROR! io exception loading " +
"log4jdbc.properties from classpath: " + e.getMessage());
}
finally
{
try
{
propStream.close();
}
catch (IOException e)
{
log.debug("ERROR! io exception closing property file stream: " +
e.getMessage());
}
}
log.debug(" log4jdbc.properties loaded from classpath");
}
else
{
log.debug(" log4jdbc.properties not found on classpath");
}
// look for additional driver specified in properties
DebugStackPrefix = getStringOption(props, "log4jdbc.debug.stack.prefix");
TraceFromApplication = DebugStackPrefix != null;
Long thresh = getLongOption("log4jdbc.sqltiming.warn.threshold");
Long thresh = getLongOption(props, "log4jdbc.sqltiming.warn.threshold");
SqlTimingWarnThresholdEnabled = (thresh != null);
if (SqlTimingWarnThresholdEnabled)
{
SqlTimingWarnThresholdMsec = thresh.longValue();
}
thresh = getLongOption("log4jdbc.sqltiming.error.threshold");
thresh = getLongOption(props, "log4jdbc.sqltiming.error.threshold");
SqlTimingErrorThresholdEnabled = (thresh != null);
if (SqlTimingErrorThresholdEnabled)
{
@@ -339,54 +407,69 @@ public class DriverSpy implements Driver
}
DumpBooleanAsTrueFalse =
getBooleanOption("log4jdbc.dump.booleanastruefalse",false);
getBooleanOption(props, "log4jdbc.dump.booleanastruefalse",false);
DumpSqlMaxLineLength = getLongOption("log4jdbc.dump.sql.maxlinelength", 90L).
intValue();
DumpSqlMaxLineLength = getLongOption(props,
"log4jdbc.dump.sql.maxlinelength", 90L).intValue();
DumpFullDebugStackTrace =
getBooleanOption("log4jdbc.dump.fulldebugstacktrace",false);
getBooleanOption(props, "log4jdbc.dump.fulldebugstacktrace",false);
StatementUsageWarn =
getBooleanOption("log4jdbc.statement.warn",false);
getBooleanOption(props, "log4jdbc.statement.warn",false);
DumpSqlSelect = getBooleanOption("log4jdbc.dump.sql.select",true);
DumpSqlInsert = getBooleanOption("log4jdbc.dump.sql.insert",true);
DumpSqlUpdate = getBooleanOption("log4jdbc.dump.sql.update",true);
DumpSqlDelete = getBooleanOption("log4jdbc.dump.sql.delete",true);
DumpSqlCreate = getBooleanOption("log4jdbc.dump.sql.create",true);
DumpSqlSelect = getBooleanOption(props, "log4jdbc.dump.sql.select",true);
DumpSqlInsert = getBooleanOption(props, "log4jdbc.dump.sql.insert",true);
DumpSqlUpdate = getBooleanOption(props, "log4jdbc.dump.sql.update",true);
DumpSqlDelete = getBooleanOption(props, "log4jdbc.dump.sql.delete",true);
DumpSqlCreate = getBooleanOption(props, "log4jdbc.dump.sql.create",true);
DumpSqlFilteringOn = !(DumpSqlSelect && DumpSqlInsert && DumpSqlUpdate &&
DumpSqlDelete && DumpSqlCreate);
DumpSqlAddSemicolon = getBooleanOption("log4jdbc.dump.sql.addsemicolon",false);
DumpSqlAddSemicolon = getBooleanOption(props,
"log4jdbc.dump.sql.addsemicolon", false);
AutoLoadPopularDrivers = getBooleanOption(props,
"log4jdbc.auto.load.popular.drivers", true);
TrimSql = getBooleanOption(props, "log4jdbc.trim.sql", true);
SuppressGetGeneratedKeysException =
getBooleanOption(props, "log4jdbc.suppress.generated.keys.exception",
false);
// The Set of drivers that the log4jdbc driver will preload at instantiation
// time. The driver can spy on any driver type, it's just a little bit
// easier to configure log4jdbc if it's one of these types!
Set subDrivers = new TreeSet();
subDrivers.add("oracle.jdbc.driver.OracleDriver");
subDrivers.add("com.sybase.jdbc2.jdbc.SybDriver");
subDrivers.add("net.sourceforge.jtds.jdbc.Driver");
// MS driver for Sql Server 2000
subDrivers.add("com.microsoft.jdbc.sqlserver.SQLServerDriver");
if (AutoLoadPopularDrivers)
{
subDrivers.add("oracle.jdbc.driver.OracleDriver");
subDrivers.add("oracle.jdbc.OracleDriver");
subDrivers.add("com.sybase.jdbc2.jdbc.SybDriver");
subDrivers.add("net.sourceforge.jtds.jdbc.Driver");
// MS driver for Sql Server 2005
subDrivers.add("com.microsoft.sqlserver.jdbc.SQLServerDriver");
// MS driver for Sql Server 2000
subDrivers.add("com.microsoft.jdbc.sqlserver.SQLServerDriver");
subDrivers.add("weblogic.jdbc.sqlserver.SQLServerDriver");
subDrivers.add("com.informix.jdbc.IfxDriver");
subDrivers.add("org.apache.derby.jdbc.ClientDriver");
subDrivers.add("org.apache.derby.jdbc.EmbeddedDriver");
subDrivers.add("com.mysql.jdbc.Driver");
subDrivers.add("org.postgresql.Driver");
subDrivers.add("org.hsqldb.jdbcDriver");
subDrivers.add("org.h2.Driver");
// MS driver for Sql Server 2005
subDrivers.add("com.microsoft.sqlserver.jdbc.SQLServerDriver");
// look for additional driver specified in system properties
String moreDrivers = getStringOption("log4jdbc.drivers");
subDrivers.add("weblogic.jdbc.sqlserver.SQLServerDriver");
subDrivers.add("com.informix.jdbc.IfxDriver");
subDrivers.add("org.apache.derby.jdbc.ClientDriver");
subDrivers.add("org.apache.derby.jdbc.EmbeddedDriver");
subDrivers.add("com.mysql.jdbc.Driver");
subDrivers.add("org.postgresql.Driver");
subDrivers.add("org.hsqldb.jdbcDriver");
subDrivers.add("org.h2.Driver");
}
// look for additional driver specified in properties
String moreDrivers = getStringOption(props, "log4jdbc.drivers");
if (moreDrivers != null)
{
@@ -395,7 +478,7 @@ public class DriverSpy implements Driver
for (int i = 0; i < moreDriversArr.length; i++)
{
subDrivers.add(moreDriversArr[i]);
log.debug (" will look for additional driver " + moreDriversArr[i]);
log.debug (" will look for specific driver " + moreDriversArr[i]);
}
}
@@ -435,11 +518,12 @@ public class DriverSpy implements Driver
}
SqlServerRdbmsSpecifics sqlServer = new SqlServerRdbmsSpecifics();
OracleRdbmsSpecifics oracle = new OracleRdbmsSpecifics();
/** create lookup Map for specific rdbms formatters */
rdbmsSpecifics = new HashMap();
rdbmsSpecifics.put("oracle.jdbc.driver.OracleDriver",
new OracleRdbmsSpecifics());
rdbmsSpecifics.put("oracle.jdbc.driver.OracleDriver", oracle);
rdbmsSpecifics.put("oracle.jdbc.OracleDriver", oracle);
rdbmsSpecifics.put("net.sourceforge.jtds.jdbc.Driver", sqlServer);
rdbmsSpecifics.put("com.microsoft.jdbc.sqlserver.SQLServerDriver",
sqlServer);
@@ -15,6 +15,8 @@
*/
package net.sf.log4jdbc;
import java.sql.Timestamp;
import java.text.SimpleDateFormat;
import java.util.Date;
/**
@@ -28,21 +30,22 @@ class OracleRdbmsSpecifics extends RdbmsSpecifics
{
super();
}
String formatParameterObject(Object object)
{
if (object != null && object instanceof Date)
if (object instanceof Timestamp)
{
// Use Oracle's to_date function to insure it comes across as a date
//
// for example:
// to_date('12/31/2011 23:59:59.150, 'mm/dd/yyyy hh24:mi:ss.ff3')
return "to_date('" + dateFormat.format(object) + "', " +
"'mm/dd/yyyy hh24:mi:ss.ff3')";
return "to_timestamp('" + new SimpleDateFormat("MM/dd/yyyy HH:mm:ss.SSS").
format(object) + "', 'mm/dd/yyyy hh24:mi:ss.ff3')";
}
else if (object instanceof Date)
{
return "to_date('" + new SimpleDateFormat("MM/dd/yyyy HH:mm:ss").
format(object) + "', 'mm/dd/yyyy hh24:mi:ss')";
}
else
{
return super.formatParameterObject(object);
}
}
}
}
@@ -304,7 +304,8 @@ public class PreparedStatementSpy extends StatementSpy implements PreparedStatem
public void setBlob(int i, Blob x) throws SQLException
{
String methodCall = "setBlob(" + i + ", " + x + ")";
argTraceSet(i, "(Blob)", "<Blob of size " + x.length() + ">");
argTraceSet(i, "(Blob)",
x==null?null:("<Blob of size " + x.length() + ">"));
try
{
realPreparedStatement.setBlob(i, x);
@@ -320,7 +321,8 @@ public class PreparedStatementSpy extends StatementSpy implements PreparedStatem
public void setClob(int i, Clob x) throws SQLException
{
String methodCall = "setClob(" + i + ", " + x + ")";
argTraceSet(i, "(Clob)", "<Clob of size " + x.length() + ">");
argTraceSet(i, "(Clob)",
x==null?null:("<Clob of size " + x.length() + ">"));
try
{
realPreparedStatement.setClob(i, x);
@@ -34,8 +34,7 @@ class RdbmsSpecifics
{
}
protected static final DateFormat dateFormat =
new SimpleDateFormat("MM/dd/yyyy HH:mm:ss.SSS");
protected static final String dateFormat = "MM/dd/yyyy HH:mm:ss.SSS";
/**
* Format an Object that is being bound to a PreparedStatement parameter, for display. The goal is to reformat the
@@ -61,7 +60,7 @@ class RdbmsSpecifics
}
else if (object instanceof Date)
{
return "'" + dateFormat.format(object) + "'";
return "'" + new SimpleDateFormat(dateFormat).format(object) + "'";
}
else if (object instanceof Boolean)
{
@@ -17,6 +17,8 @@ package net.sf.log4jdbc;
import java.util.StringTokenizer;
import net.sf.log4jdbc.DriverSpy;
import org.slf4j.LoggerFactory;
import org.slf4j.Logger;
@@ -239,7 +241,10 @@ public class Slf4jSpyLogDelegator implements SpyLogDelegator
return null;
}
sql = sql.trim();
if (DriverSpy.TrimSql)
{
sql = sql.trim();
}
StringBuffer output = new StringBuffer();
+4 -1
View File
@@ -587,7 +587,10 @@ public class StatementSpy implements Statement, Spy
}
catch (SQLException s)
{
reportException(methodCall, s);
if (!DriverSpy.SuppressGetGeneratedKeysException)
{
reportException(methodCall, s);
}
throw s;
}
}
+142 -58
View File
@@ -15,6 +15,8 @@
*/
package net.sf.log4jdbc;
import java.io.IOException;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.Driver;
@@ -33,9 +35,11 @@ import java.util.TreeSet;
* A JDBC driver which is a facade that delegates to one or more real underlying
* JDBC drivers. The driver will spy on any other JDBC driver that is loaded,
* simply by prepending <code>jdbc:log4</code> to the normal jdbc driver URL
* used by any other JDBC driver. The driver also loads several well known
* drivers at class load time, so that this driver can be "dropped in" to any
* java program that uses these drivers without making any code changes.
* used by any other JDBC driver. The driver, by default, also loads several
* well known drivers at class load time, so that this driver can be
* "dropped in" to any Java program that uses these drivers without making any
* code changes.
* <p/>
* The well known driver classes that are loaded are:
* <p/>
* <p/>
@@ -58,10 +62,15 @@ import java.util.TreeSet;
* </code>
* <p/>
* <p/>
* Additional drivers can be set via a system property: <b>log4jdbc.drivers</b>
* Additional drivers can be set via a property: <b>log4jdbc.drivers</b>
* This can be either a single driver class name or a list of comma separated
* driver class names.
* <p/>
* The autoloading behavior can be disabled by setting a property:
* <b>log4jdbc.auto.load.popular.drivers</b> to false. If that is done, then
* the only drivers that log4jdbc will attempt to load are the ones specified
* in <b>log4jdbc.drivers</b>.
* <p/>
* If any of the above driver classes cannot be loaded, the driver continues on
* without failing.
* <p/>
@@ -190,17 +199,36 @@ public class DriverSpy implements Driver
static boolean DumpFullDebugStackTrace;
/**
* Get a Long option from a system property and
* Attempt to Automatically load a set of popular JDBC drivers?
*/
static boolean AutoLoadPopularDrivers;
/**
* Trim SQL before logging it?
*/
static boolean TrimSql;
/**
* Coldfusion typically calls PreparedStatement.getGeneratedKeys() after
* every SQL update call, even if it's not warranted. This typically produces
* an exception that is ignored by Coldfusion. If this flag is true, then
* any exception generated by this method is also ignored by log4jdbc.
*/
static boolean SuppressGetGeneratedKeysException;
/**
* Get a Long option from a property and
* log a debug message about this.
*
* @param propName System property key.
* @param props Properties to get option from.
* @param propName property key.
*
* @return the value of that System property key, converted
* @return the value of that property key, converted
* to a Long. Or null if not defined or is invalid.
*/
private static Long getLongOption(String propName)
private static Long getLongOption(Properties props, String propName)
{
String propValue = System.getProperty(propName);
String propValue = props.getProperty(propName);
Long longPropValue = null;
if (propValue == null)
{
@@ -223,21 +251,24 @@ public class DriverSpy implements Driver
}
/**
* Get a Long option from a system property and
* Get a Long option from a property and
* log a debug message about this.
*
* @param propName System property key.
* @param props Properties to get option from.
* @param propName property key.
*
* @return the value of that System property key, converted
* @return the value of that property key, converted
* to a Long. Or null if not defined or is invalid.
*/
private static Long getLongOption(String propName, long defaultValue)
private static Long getLongOption(Properties props, String propName,
long defaultValue)
{
String propValue = System.getProperty(propName);
String propValue = props.getProperty(propName);
Long longPropValue;
if (propValue == null)
{
log.debug("x " + propName + " is not defined (using default of " + defaultValue +")");
log.debug("x " + propName + " is not defined (using default of " +
defaultValue +")");
longPropValue = new Long(defaultValue);
}
else
@@ -258,15 +289,16 @@ public class DriverSpy implements Driver
}
/**
* Get a String option from a system property and
* Get a String option from a property and
* log a debug message about this.
*
* @param propName System property key.
* @return the value of that System property key.
* @param props Properties to get option from.
* @param propName property key.
* @return the value of that property key.
*/
private static String getStringOption(String propName)
private static String getStringOption(Properties props, String propName)
{
String propValue = System.getProperty(propName);
String propValue = props.getProperty(propName);
if (propValue == null || propValue.length()==0)
{
log.debug("x " + propName + " is not defined");
@@ -280,18 +312,20 @@ public class DriverSpy implements Driver
}
/**
* Get a boolean option from a system property and
* Get a boolean option from a property and
* log a debug message about this.
*
* @param props Properties to get option from.
* @param propName property name to get.
* @param defaultValue default value to use if undefined.
*
* @return boolean value found in property, or defaultValue if no property
* found.
*/
private static boolean getBooleanOption(String propName, boolean defaultValue)
private static boolean getBooleanOption(Properties props, String propName,
boolean defaultValue)
{
String propValue = System.getProperty(propName);
String propValue = props.getProperty(propName);
boolean val;
if (propValue == null)
{
@@ -320,18 +354,52 @@ public class DriverSpy implements Driver
{
log.debug("... log4jdbc initializing ...");
// look for additional driver specified in system properties
DebugStackPrefix = getStringOption("log4jdbc.debug.stack.prefix");
InputStream propStream =
DriverSpy.class.getResourceAsStream("/log4jdbc.properties");
Properties props = new Properties(System.getProperties());
if (propStream != null)
{
try
{
props.load(propStream);
}
catch (IOException e)
{
log.debug("ERROR! io exception loading " +
"log4jdbc.properties from classpath: " + e.getMessage());
}
finally
{
try
{
propStream.close();
}
catch (IOException e)
{
log.debug("ERROR! io exception closing property file stream: " +
e.getMessage());
}
}
log.debug(" log4jdbc.properties loaded from classpath");
}
else
{
log.debug(" log4jdbc.properties not found on classpath");
}
// look for additional driver specified in properties
DebugStackPrefix = getStringOption(props, "log4jdbc.debug.stack.prefix");
TraceFromApplication = DebugStackPrefix != null;
Long thresh = getLongOption("log4jdbc.sqltiming.warn.threshold");
Long thresh = getLongOption(props, "log4jdbc.sqltiming.warn.threshold");
SqlTimingWarnThresholdEnabled = (thresh != null);
if (SqlTimingWarnThresholdEnabled)
{
SqlTimingWarnThresholdMsec = thresh.longValue();
}
thresh = getLongOption("log4jdbc.sqltiming.error.threshold");
thresh = getLongOption(props, "log4jdbc.sqltiming.error.threshold");
SqlTimingErrorThresholdEnabled = (thresh != null);
if (SqlTimingErrorThresholdEnabled)
{
@@ -339,54 +407,69 @@ public class DriverSpy implements Driver
}
DumpBooleanAsTrueFalse =
getBooleanOption("log4jdbc.dump.booleanastruefalse",false);
getBooleanOption(props, "log4jdbc.dump.booleanastruefalse",false);
DumpSqlMaxLineLength = getLongOption("log4jdbc.dump.sql.maxlinelength", 90L).
intValue();
DumpSqlMaxLineLength = getLongOption(props,
"log4jdbc.dump.sql.maxlinelength", 90L).intValue();
DumpFullDebugStackTrace =
getBooleanOption("log4jdbc.dump.fulldebugstacktrace",false);
getBooleanOption(props, "log4jdbc.dump.fulldebugstacktrace",false);
StatementUsageWarn =
getBooleanOption("log4jdbc.statement.warn",false);
getBooleanOption(props, "log4jdbc.statement.warn",false);
DumpSqlSelect = getBooleanOption("log4jdbc.dump.sql.select",true);
DumpSqlInsert = getBooleanOption("log4jdbc.dump.sql.insert",true);
DumpSqlUpdate = getBooleanOption("log4jdbc.dump.sql.update",true);
DumpSqlDelete = getBooleanOption("log4jdbc.dump.sql.delete",true);
DumpSqlCreate = getBooleanOption("log4jdbc.dump.sql.create",true);
DumpSqlSelect = getBooleanOption(props, "log4jdbc.dump.sql.select",true);
DumpSqlInsert = getBooleanOption(props, "log4jdbc.dump.sql.insert",true);
DumpSqlUpdate = getBooleanOption(props, "log4jdbc.dump.sql.update",true);
DumpSqlDelete = getBooleanOption(props, "log4jdbc.dump.sql.delete",true);
DumpSqlCreate = getBooleanOption(props, "log4jdbc.dump.sql.create",true);
DumpSqlFilteringOn = !(DumpSqlSelect && DumpSqlInsert && DumpSqlUpdate &&
DumpSqlDelete && DumpSqlCreate);
DumpSqlAddSemicolon = getBooleanOption("log4jdbc.dump.sql.addsemicolon",false);
DumpSqlAddSemicolon = getBooleanOption(props,
"log4jdbc.dump.sql.addsemicolon", false);
AutoLoadPopularDrivers = getBooleanOption(props,
"log4jdbc.auto.load.popular.drivers", true);
TrimSql = getBooleanOption(props, "log4jdbc.trim.sql", true);
SuppressGetGeneratedKeysException =
getBooleanOption(props, "log4jdbc.suppress.generated.keys.exception",
false);
// The Set of drivers that the log4jdbc driver will preload at instantiation
// time. The driver can spy on any driver type, it's just a little bit
// easier to configure log4jdbc if it's one of these types!
Set subDrivers = new TreeSet();
subDrivers.add("oracle.jdbc.driver.OracleDriver");
subDrivers.add("com.sybase.jdbc2.jdbc.SybDriver");
subDrivers.add("net.sourceforge.jtds.jdbc.Driver");
// MS driver for Sql Server 2000
subDrivers.add("com.microsoft.jdbc.sqlserver.SQLServerDriver");
if (AutoLoadPopularDrivers)
{
subDrivers.add("oracle.jdbc.driver.OracleDriver");
subDrivers.add("oracle.jdbc.OracleDriver");
subDrivers.add("com.sybase.jdbc2.jdbc.SybDriver");
subDrivers.add("net.sourceforge.jtds.jdbc.Driver");
// MS driver for Sql Server 2005
subDrivers.add("com.microsoft.sqlserver.jdbc.SQLServerDriver");
// MS driver for Sql Server 2000
subDrivers.add("com.microsoft.jdbc.sqlserver.SQLServerDriver");
subDrivers.add("weblogic.jdbc.sqlserver.SQLServerDriver");
subDrivers.add("com.informix.jdbc.IfxDriver");
subDrivers.add("org.apache.derby.jdbc.ClientDriver");
subDrivers.add("org.apache.derby.jdbc.EmbeddedDriver");
subDrivers.add("com.mysql.jdbc.Driver");
subDrivers.add("org.postgresql.Driver");
subDrivers.add("org.hsqldb.jdbcDriver");
subDrivers.add("org.h2.Driver");
// MS driver for Sql Server 2005
subDrivers.add("com.microsoft.sqlserver.jdbc.SQLServerDriver");
// look for additional driver specified in system properties
String moreDrivers = getStringOption("log4jdbc.drivers");
subDrivers.add("weblogic.jdbc.sqlserver.SQLServerDriver");
subDrivers.add("com.informix.jdbc.IfxDriver");
subDrivers.add("org.apache.derby.jdbc.ClientDriver");
subDrivers.add("org.apache.derby.jdbc.EmbeddedDriver");
subDrivers.add("com.mysql.jdbc.Driver");
subDrivers.add("org.postgresql.Driver");
subDrivers.add("org.hsqldb.jdbcDriver");
subDrivers.add("org.h2.Driver");
}
// look for additional driver specified in properties
String moreDrivers = getStringOption(props, "log4jdbc.drivers");
if (moreDrivers != null)
{
@@ -395,7 +478,7 @@ public class DriverSpy implements Driver
for (int i = 0; i < moreDriversArr.length; i++)
{
subDrivers.add(moreDriversArr[i]);
log.debug (" will look for additional driver " + moreDriversArr[i]);
log.debug (" will look for specific driver " + moreDriversArr[i]);
}
}
@@ -435,11 +518,12 @@ public class DriverSpy implements Driver
}
SqlServerRdbmsSpecifics sqlServer = new SqlServerRdbmsSpecifics();
OracleRdbmsSpecifics oracle = new OracleRdbmsSpecifics();
/** create lookup Map for specific rdbms formatters */
rdbmsSpecifics = new HashMap();
rdbmsSpecifics.put("oracle.jdbc.driver.OracleDriver",
new OracleRdbmsSpecifics());
rdbmsSpecifics.put("oracle.jdbc.driver.OracleDriver", oracle);
rdbmsSpecifics.put("oracle.jdbc.OracleDriver", oracle);
rdbmsSpecifics.put("net.sourceforge.jtds.jdbc.Driver", sqlServer);
rdbmsSpecifics.put("com.microsoft.jdbc.sqlserver.SQLServerDriver",
sqlServer);
@@ -15,6 +15,8 @@
*/
package net.sf.log4jdbc;
import java.sql.Timestamp;
import java.text.SimpleDateFormat;
import java.util.Date;
/**
@@ -28,21 +30,22 @@ class OracleRdbmsSpecifics extends RdbmsSpecifics
{
super();
}
String formatParameterObject(Object object)
{
if (object != null && object instanceof Date)
if (object instanceof Timestamp)
{
// Use Oracle's to_date function to insure it comes across as a date
//
// for example:
// to_date('12/31/2011 23:59:59.150, 'mm/dd/yyyy hh24:mi:ss.ff3')
return "to_date('" + dateFormat.format(object) + "', " +
"'mm/dd/yyyy hh24:mi:ss.ff3')";
return "to_timestamp('" + new SimpleDateFormat("MM/dd/yyyy HH:mm:ss.SSS").
format(object) + "', 'mm/dd/yyyy hh24:mi:ss.ff3')";
}
else if (object instanceof Date)
{
return "to_date('" + new SimpleDateFormat("MM/dd/yyyy HH:mm:ss").
format(object) + "', 'mm/dd/yyyy hh24:mi:ss')";
}
else
{
return super.formatParameterObject(object);
}
}
}
}
@@ -308,7 +308,8 @@ public class PreparedStatementSpy extends StatementSpy implements PreparedStatem
public void setBlob(int i, Blob x) throws SQLException
{
String methodCall = "setBlob(" + i + ", " + x + ")";
argTraceSet(i, "(Blob)", "<Blob of size " + x.length() + ">");
argTraceSet(i, "(Blob)",
x==null?null:("<Blob of size " + x.length() + ">"));
try
{
realPreparedStatement.setBlob(i, x);
@@ -324,7 +325,8 @@ public class PreparedStatementSpy extends StatementSpy implements PreparedStatem
public void setClob(int i, Clob x) throws SQLException
{
String methodCall = "setClob(" + i + ", " + x + ")";
argTraceSet(i, "(Clob)", "<Clob of size " + x.length() + ">");
argTraceSet(i, "(Clob)",
x==null?null:("<Clob of size " + x.length() + ">"));
try
{
realPreparedStatement.setClob(i, x);

Some files were not shown because too many files have changed in this diff Show More