mwomack 2003/06/10 21:58:18 Added: src/java/org/apache/log4j/jdbc UrlConnectionSource.java PreparedStatementSource.java PreparedStatementParameter.java PreparedStatementAppender.java JNDIConnectionSource.java ConnectionSource.java Log: Added PreparedStatementAppender and related classes from Ray DeCampo. Revision Changes Path 1.1 jakarta-log4j-sandbox/src/java/org/apache/log4j/jdbc/UrlConnectionSource.java Index: UrlConnectionSource.java =================================================================== /* * ============================================================================ * The Apache Software License, Version 1.1 * ============================================================================ * * Copyright (C) 1999 The Apache Software Foundation. All rights reserved. * * Redistribution and use in source and binary forms, with or without modifica- * tion, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * 3. The end-user documentation included with the redistribution, if any, must * include the following acknowledgment: "This product includes software * developed by the Apache Software Foundation (http://www.apache.org/)." * Alternately, this acknowledgment may appear in the software itself, if * and wherever such third-party acknowledgments normally appear. * * 4. The names "log4j" and "Apache Software Foundation" must not be used to * endorse or promote products derived from this software without prior * written permission. For written permission, please contact * [EMAIL PROTECTED] * * 5. Products derived from this software may not be called "Apache", nor may * "Apache" appear in their name, without prior written permission of the * Apache Software Foundation. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU- * DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * This software consists of voluntary contributions made by many individuals * on behalf of the Apache Software Foundation. For more information on the * Apache Software Foundation, please see <http://www.apache.org/>. * */ package org.apache.log4j.jdbc; import org.apache.log4j.spi.ErrorCode; import org.apache.log4j.spi.ErrorHandler; import java.sql.Connection; import java.sql.DriverManager; import java.sql.SQLException; /** * The UrlConnectionSource is an implementation of [EMAIL PROTECTED] ConnectionSource} * that obtains the Connection in the traditional JDBC manner based on the * connection URL. * <p> * Note that this class will estanblish a new Connection for each call to * [EMAIL PROTECTED] #getConnection()}. It is recommended that you either use a JDBC * driver that natively supported Connection pooling or that you create * your own implementation of [EMAIL PROTECTED] ConnectionSource} that taps into whatever * pooling mechanism you are already using. (If you have access to a JNDI * implementation that supports [EMAIL PROTECTED] javax.sql.DataSource}s, e.g. within * a J2EE application server, see [EMAIL PROTECTED] JNDIConnectionSource}). * <p> * Sample configuration:<br> * <pre> * <connectionSource class="org.apache.log4j.jdbc.UrlConnectionSource"> * <param name="driver" value="com.mysql.jdbc.Driver" /> * <param name="url" value="jdbc:mysql://localhost:3306/mydb" /> * <param name="username" value="myUser" /> * <param name="password" value="myPassword" /> * </connectionSource> * </pre> * * @author <a href="mailto:[EMAIL PROTECTED]">Ray DeCampo</a> */ public class UrlConnectionSource implements ConnectionSource { private String driver = null; private String url = null; private String username = null; private String password = null; private ErrorHandler errorHandler = null; public void activateOptions() { try { Class.forName(driver); } catch (final ClassNotFoundException cnfe) { if (errorHandler != null) { errorHandler.error( "Could not load JDBC driver class: " + driver, cnfe, ErrorCode.GENERIC_FAILURE); } else { cnfe.printStackTrace(); } } } /** * @see org.apache.log4j.jdbc.ConnectionSource#getConnection() */ public Connection getConnection() throws SQLException { if (username == null) { return DriverManager.getConnection(url); } else { return DriverManager.getConnection(url, username, password); } } /** * Returns the password. * @return String */ public String getPassword() { return password; } /** * Returns the url. * @return String */ public String getUrl() { return url; } /** * Returns the username. * @return String */ public String getUsername() { return username; } /** * Sets the password. * @param password The password to set */ public void setPassword(String password) { this.password = password; } /** * Sets the url. * @param url The url to set */ public void setUrl(String url) { this.url = url; } /** * Sets the username. * @param username The username to set */ public void setUsername(String username) { this.username = username; } /** * Returns the driver. * @return String */ public String getDriver() { return driver; } /** * Sets the driver. * @param driver The driver to set */ public void setDriver(String driver) { this.driver = driver; } /** * Sets the error handler. * @param errorHandler the error handler to set */ public void setErrorHandler(ErrorHandler errorHandler) { this.errorHandler = errorHandler; } } 1.1 jakarta-log4j-sandbox/src/java/org/apache/log4j/jdbc/PreparedStatementSource.java Index: PreparedStatementSource.java =================================================================== /* * ============================================================================ * The Apache Software License, Version 1.1 * ============================================================================ * * Copyright (C) 1999 The Apache Software Foundation. All rights reserved. * * Redistribution and use in source and binary forms, with or without modifica- * tion, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * 3. The end-user documentation included with the redistribution, if any, must * include the following acknowledgment: "This product includes software * developed by the Apache Software Foundation (http://www.apache.org/)." * Alternately, this acknowledgment may appear in the software itself, if * and wherever such third-party acknowledgments normally appear. * * 4. The names "log4j" and "Apache Software Foundation" must not be used to * endorse or promote products derived from this software without prior * written permission. For written permission, please contact * [EMAIL PROTECTED] * * 5. Products derived from this software may not be called "Apache", nor may * "Apache" appear in their name, without prior written permission of the * Apache Software Foundation. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU- * DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * This software consists of voluntary contributions made by many individuals * on behalf of the Apache Software Foundation. For more information on the * Apache Software Foundation, please see <http://www.apache.org/>. * */ package org.apache.log4j.jdbc; import org.apache.log4j.spi.ErrorHandler; import org.apache.log4j.spi.OptionHandler; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.SQLException; /** * The <code>PreparedStatementSource</code> interface provides a pluggable * means of creating [EMAIL PROTECTED] java.sql.PreparedStatement}s for use with the * [EMAIL PROTECTED] PreparedStatementAppender}. Create an implementation of this * interface if the default [EMAIL PROTECTED] java.sql.PreparedStatement} created * by the appender is not sufficient. * <p> * Note that since a [EMAIL PROTECTED] java.sql.CallableStatement} is a * [EMAIL PROTECTED] java.sql.PreparedStatement} you can use this * interface to set up calls to stored procedures if desired. * * @author <a href="mailto:[EMAIL PROTECTED]">Ray DeCampo</a> */ public interface PreparedStatementSource extends OptionHandler { /** * Generate a [EMAIL PROTECTED] java.sql.PreparedStatement} for use by the client. * The client is responsible for closing the statement. */ public PreparedStatement generate( PreparedStatementAppender psa, Connection conn) throws SQLException; /** * Set the error handler. * * @param errorHanlder the new error handler */ void setErrorHandler(ErrorHandler errorHandler); } 1.1 jakarta-log4j-sandbox/src/java/org/apache/log4j/jdbc/PreparedStatementParameter.java Index: PreparedStatementParameter.java =================================================================== /* * ============================================================================ * The Apache Software License, Version 1.1 * ============================================================================ * * Copyright (C) 1999 The Apache Software Foundation. All rights reserved. * * Redistribution and use in source and binary forms, with or without modifica- * tion, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * 3. The end-user documentation included with the redistribution, if any, must * include the following acknowledgment: "This product includes software * developed by the Apache Software Foundation (http://www.apache.org/)." * Alternately, this acknowledgment may appear in the software itself, if * and wherever such third-party acknowledgments normally appear. * * 4. The names "log4j" and "Apache Software Foundation" must not be used to * endorse or promote products derived from this software without prior * written permission. For written permission, please contact * [EMAIL PROTECTED] * * 5. Products derived from this software may not be called "Apache", nor may * "Apache" appear in their name, without prior written permission of the * Apache Software Foundation. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU- * DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * This software consists of voluntary contributions made by many individuals * on behalf of the Apache Software Foundation. For more information on the * Apache Software Foundation, please see <http://www.apache.org/>. * */ package org.apache.log4j.jdbc; import org.apache.log4j.Level; import org.apache.log4j.spi.ErrorHandler; import org.apache.log4j.spi.ThrowableInformation; import java.io.PrintWriter; import java.io.StringReader; import java.io.StringWriter; import java.math.BigDecimal; import java.sql.Date; import java.sql.PreparedStatement; import java.sql.SQLException; import java.sql.Time; import java.sql.Timestamp; /** * The <code>PreparedStatementParameter</code> class encapsulates the * information needed to set a parameter on a * [EMAIL PROTECTED] java.sql.PreparedStatement}. * * @author <a href="mailto:[EMAIL PROTECTED]">Ray DeCampo</a> */ public class PreparedStatementParameter implements Comparable { private String columnName; private int order; private String jdbcSetter; private ErrorHandler errorHandler; /** * Default constructor. */ public PreparedStatementParameter() { } /** * Returns the columnName. * @return String */ public String getColumnName() { return columnName; } /** * Returns the jdbcSetter. * @return String */ public String getJdbcSetter() { return jdbcSetter; } /** * Returns the order. * @return int */ public int getOrder() { return order; } /** * Sets the columnName. * @param columnName The columnName to set */ public void setColumnName(String columnName) { this.columnName = columnName; } /** * Sets the jdbcSetter. * @param jdbcSetter The jdbcSetter to set */ public void setJdbcSetter(String jdbcSetter) { this.jdbcSetter = jdbcSetter; } /** * Sets the order. * @param order The order to set */ public void setOrder(int order) { this.order = order; } /** * Compares based on the order. */ public int compareTo(Object obj) { PreparedStatementParameter that = (PreparedStatementParameter) obj; if (this.order < that.order) { return -1; } else if (this.order == that.order) { return 0; } else { return 1; } } /** * Set this parameter on the given statement with the given value. * * @param stmt the statement * @param value the value to set * * @throws SQLException if the parameter could not be set */ public void setParameter(PreparedStatement stmt, String value) throws SQLException { if ("setString".equals(jdbcSetter)) { stmt.setString(order, value); } else if ("setCharacterStream".equals(jdbcSetter)) { if (value == null) { value = ""; } stmt.setCharacterStream(order, new StringReader(value), value.length()); } else if ("setObject".equals(jdbcSetter)) { stmt.setObject(order, value); } else { errorHandler.error("Unsupported setter for String: " + jdbcSetter); } } /** * Set this parameter on the given statement with the given value. * * @param stmt the statement * @param value the value to set * * @throws SQLException if the parameter could not be set */ public void setParameter(PreparedStatement stmt, ThrowableInformation value) throws SQLException { final StringWriter buf = new StringWriter(); if ((value != null) && (value.getThrowable() != null)) { value.getThrowable().printStackTrace(new PrintWriter(buf)); } final String str = buf.getBuffer().toString(); if ("setString".equals(jdbcSetter)) { stmt.setString(order, str); } else if ("setCharacterStream".equals(jdbcSetter)) { stmt.setCharacterStream(order, new StringReader(str), str.length()); } else if ("setObject".equals(jdbcSetter)) { stmt.setObject(order, str); } else { errorHandler.error("Unsupported setter for Throwable: " + jdbcSetter); } } /** * Set this parameter on the given statement with the given value. * * @param stmt the statement * @param value the value to set * * @throws SQLException if the parameter could not be set */ public void setParameter(PreparedStatement stmt, Level value) throws SQLException { if ("setString".equals(jdbcSetter)) { stmt.setString(order, String.valueOf(value)); } else if ("setInt".equals(jdbcSetter)) { stmt.setInt(order, value.toInt()); } else if ("setObject".equals(jdbcSetter)) { stmt.setObject(order, String.valueOf(value)); } else if ("setLong".equals(jdbcSetter)) { stmt.setLong(order, value.toInt()); } else if ("setDouble".equals(jdbcSetter)) { stmt.setDouble(order, value.toInt()); } else if ("setBigDecimal".equals(jdbcSetter)) { stmt.setBigDecimal(order, new BigDecimal(value.toInt())); } else if ("setFloat".equals(jdbcSetter)) { stmt.setFloat(order, value.toInt()); } else { errorHandler.error("Unsupported setter for Level: " + jdbcSetter); } } /** * Set this parameter on the given statement with the given value. * * @param stmt the statement * @param value the value to set * * @throws SQLException if the parameter could not be set */ public void setParameter(PreparedStatement stmt, long value) throws SQLException { if ("setTimestamp".equals(jdbcSetter)) { stmt.setTimestamp(order, new Timestamp(value)); } else if ("setDate".equals(jdbcSetter)) { stmt.setDate(order, new Date(value)); } else if ("setTime".equals(jdbcSetter)) { stmt.setTime(order, new Time(value)); } else if ("setString".equals(jdbcSetter)) { stmt.setString(order, String.valueOf(value)); } else if ("setObject".equals(jdbcSetter)) { stmt.setObject(order, new Long(value)); } else if ("setLong".equals(jdbcSetter)) { stmt.setLong(order, value); } else if ("setDouble".equals(jdbcSetter)) { stmt.setDouble(order, value); } else if ("setBigDecimal".equals(jdbcSetter)) { stmt.setBigDecimal(order, new BigDecimal(value)); } else if ("setInt".equals(jdbcSetter)) { stmt.setInt(order, (int) value); } else if ("setFloat".equals(jdbcSetter)) { stmt.setFloat(order, (float) value); } else { errorHandler.error("Unsupported setter for long: " + jdbcSetter); } } /** * Sets the errorHandler. * @param errorHandler The errorHandler to set */ public void setErrorHandler(ErrorHandler errorHandler) { this.errorHandler = errorHandler; } } 1.1 jakarta-log4j-sandbox/src/java/org/apache/log4j/jdbc/PreparedStatementAppender.java Index: PreparedStatementAppender.java =================================================================== /* * ============================================================================ * The Apache Software License, Version 1.1 * ============================================================================ * * Copyright (C) 1999 The Apache Software Foundation. All rights reserved. * * Redistribution and use in source and binary forms, with or without modifica- * tion, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * 3. The end-user documentation included with the redistribution, if any, must * include the following acknowledgment: "This product includes software * developed by the Apache Software Foundation (http://www.apache.org/)." * Alternately, this acknowledgment may appear in the software itself, if * and wherever such third-party acknowledgments normally appear. * * 4. The names "log4j" and "Apache Software Foundation" must not be used to * endorse or promote products derived from this software without prior * written permission. For written permission, please contact * [EMAIL PROTECTED] * * 5. Products derived from this software may not be called "Apache", nor may * "Apache" appear in their name, without prior written permission of the * Apache Software Foundation. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU- * DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * This software consists of voluntary contributions made by many individuals * on behalf of the Apache Software Foundation. For more information on the * Apache Software Foundation, please see <http://www.apache.org/>. * */ package org.apache.log4j.jdbc; import org.apache.log4j.AppenderSkeleton; import org.apache.log4j.helpers.LogLog; import org.apache.log4j.spi.ErrorCode; import org.apache.log4j.spi.LoggingEvent; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.SQLException; import java.util.ArrayList; /** * The <code>PreparedStatementAppender</code> class provides a JDBC-based * appender that uses [EMAIL PROTECTED] java.sql.PreparedStatement}s for efficiency. * Note that this appender takes advantage of the advanced capabilities of the * [EMAIL PROTECTED] org.apache.log4j.xml.DOMConfigurator} and therefore must be * configured with an XML configuration file. * <p> * This appender has a number of configurable options. First and foremost is * the <code>connectionSource</code>, an implementation of * [EMAIL PROTECTED] ConnectionSource}. For example, [EMAIL PROTECTED] UrlConnectionSource} and * [EMAIL PROTECTED] JNDIConnectionSource} are provider by log4j. It is recommended that * you use [EMAIL PROTECTED] JNDIConnectionSource} whenever possible and create your own * implementation of [EMAIL PROTECTED] ConnectionSource} otherwise. Use * [EMAIL PROTECTED] UrlConnectionSource} if you just want to get something working fast. * <p> * Second is the optional <code>preparedStatementSource</code>, an * implementation of [EMAIL PROTECTED] PreparedStatementSource}. Only specify this if * the default statement * provider by <code>PreparedStatementAppender</code> is not sufficient. * By default a statement similar to "<code>INSERT INTO LOG4J (message, * logger, level) VALUES (?, ?, ?)</code>" will be generated based on the * other parameters (see the example below). * <p> * Next, there is a parameter for each part of the logging event you might * want to include in database:<br> * <table border="1" rules="all" cellpadding="3"> * <tr> * <th>Parameter</th> * <th>Description</th> * <th>Default JDBC Setter</th> * </tr> * <tr> * <td>messageParameter</td> * <td>The raw log message</td> * <td>setString</td> * </tr> * <tr> * <td>formattedMessageParameter</td> * <td>The formatted log message</td> * <td>setString</td> * </tr> * <tr> * <td>loggerParameter</td> * <td>The logger</td> * <td>setString</td> * </tr> * <tr> * <td>levelParameter</td> * <td>The log message level</td> * <td>setString</td> * </tr> * <tr> * <td>ndcParameter</td> * <td>The NDC (nested diagnostic context) of the log message</td> * <td>setString</td> * </tr> * <tr> * <td>exceptionParameter</td> * <td>The message of the exception, i.e. the value of * <code>Exception.getMessage()</code>, for the exception passed to the * logger</td> * <td>setString</td> * </tr> * <tr> * <td>stackParameter</td> * <td>The stack trace of the exception passed to the logger. Beware that * no effort is made to ensure that the stack trace will fit inside the * database column provided.</td> * <td>setCharacterStream</td> * </tr> * <tr> * <td>timeStampParameter</td> * <td>The time stamp of the log message</td> * <td>setTimerStamp</td> * </tr> * </table><br> * Define whichever subset of these you wish to include in your database table. * If the JDBC setter referenced above is sufficient for the column in * question, you may omit the setter value in the configuration. * <p> * Finally, the table parameter is used to indicate the table into which to * insert the rows for the default prepared statement. * * <h3>Example Configurations</h3> * All of the example configurations assume that the database vendor is MySQL, * the instance is test, the user is myUser and the password is myPassword. * The database table is LOG4J and looks like:<br> * <pre> * mysql> desc LOG4J; * +-----------+--------------+------+-----+---------+-------+ * | Field | Type | Null | Key | Default | Extra | * +-----------+--------------+------+-----+---------+-------+ * | msg | blob | YES | | NULL | | * | logger | varchar(255) | YES | | NULL | | * | level | varchar(5) | YES | | NULL | | * | ndc | varchar(255) | YES | | NULL | | * | exception | blob | YES | | NULL | | * | stack | blob | YES | | NULL | | * | formatted | blob | YES | | NULL | | * | stamp | datetime | YES | | NULL | | * +-----------+--------------+------+-----+---------+-------+ * </pre> * * <h4>Quick and dirty</h4> * Include the following in your log4j.xml file:<br> * <pre> * <appender name="X" class="org.apache.log4j.jdbc.PreparedStatementAppender"> * <layout class="org.apache.log4j.PatternLayout"> * <param name="ConversionPattern" value="%d %-5p %c - %m%n"/> * </layout> * <connectionSource class="org.apache.log4j.jdbc.UrlConnectionSource"> * <param name="driver" value="com.mysql.jdbc.Driver" /> * <param name="url" value="jdbc:mysql://localhost:3306/test" /> * <param name="username" value="myUser" /> * <param name="password" value="myPassword" /> * </connectionSource> * <param name="table" value="LOG4J"/> * <messageParameter class="org.apache.log4j.jdbc.PreparedStatementParameter"> * <param name="columnName" value="msg" /> * </messageParameter> * <loggerParameter class="org.apache.log4j.jdbc.PreparedStatementParameter"> * <param name="columnName" value="logger" /> * </loggerParameter> * <levelParameter class="org.apache.log4j.jdbc.PreparedStatementParameter"> * <param name="columnName" value="level" /> * </levelParameter> * <ndcParameter class="org.apache.log4j.jdbc.PreparedStatementParameter"> * <param name="columnName" value="ndc" /> * </ndcParameter> * <exceptionParameter class="org.apache.log4j.jdbc.PreparedStatementParameter"> * <param name="columnName" value="exception" /> * </exceptionParameter> * <stackParameter class="org.apache.log4j.jdbc.PreparedStatementParameter"> * <param name="columnName" value="stack" /> * </stackParameter> * <formattedMessageParameter class="org.apache.log4j.jdbc.PreparedStatementParameter"> * <param name="columnName" value="formatted" /> * </formattedMessageParameter> * <timeStampParameter class="org.apache.log4j.jdbc.PreparedStatementParameter"> * <param name="columnName" value="stamp" /> * </timeStampParameter> * </appender> * </pre> * <p> * This configuration will generate a prepared statement of the form * <code>INSERT INTO LOG4J (msg, logger, level, ndc, exception, stack, * formatted, stamp) VALUES (?, ?, ?, ?, ?, ?, ?, ?)</code>. If you do not * need one of the columns, for example <code>msg</code>, simply do not include * it in the configuration. * * <h4>JNDI-based Configuration</h4> * This example demonstrates the JNDIConnectionSource:<br> * <pre> * <appender name="X" class="org.apache.log4j.jdbc.PreparedStatementAppender"> * <layout class="org.apache.log4j.PatternLayout"> * <param name="ConversionPattern" value="%d %-5p %c - %m%n"/> * </layout> * <b> * <connectionSource class="org.apache.log4j.jdbc.JNDIConnectionSource"> * <param name="jndiLocation" value="jdbc/MySQLDS" /> * </connectionSource> * </b> * <param name="table" value="LOG4J"/> * <loggerParameter class="org.apache.log4j.jdbc.PreparedStatementParameter"> * <param name="columnName" value="logger" /> * </loggerParameter> * <levelParameter class="org.apache.log4j.jdbc.PreparedStatementParameter"> * <param name="columnName" value="level" /> * </levelParameter> * <exceptionParameter class="org.apache.log4j.jdbc.PreparedStatementParameter"> * <param name="columnName" value="exception" /> * </exceptionParameter> * <stackParameter class="org.apache.log4j.jdbc.PreparedStatementParameter"> * <param name="columnName" value="stack" /> * </stackParameter> * <formattedMessageParameter class="org.apache.log4j.jdbc.PreparedStatementParameter"> * <param name="columnName" value="formatted" /> * </formattedMessageParameter> * <timeStampParameter class="org.apache.log4j.jdbc.PreparedStatementParameter"> * <param name="columnName" value="stamp" /> * </timeStampParameter> * </appender> * </pre> * Note that this configuration will produce a slightly different prepared * statement: <code>INSERT INTO LOG4J (logger, level, exception, stack, * formatted, stamp) VALUES (?, ?, ?, ?, ?)</code>. This was done purely for * demonstration purposes, there is no reason <code>messageParameter</code> and * <code>ndcParameter</code> could not be included. * * <h4>Custom PreparedStatementSopurce Configuration</h4> * This example demonstrates a custom [EMAIL PROTECTED] PreparedStatementSource}:<br> * <pre> * <appender name="X" class="org.apache.log4j.jdbc.PreparedStatementAppender"> * <layout class="org.apache.log4j.PatternLayout"> * <param name="ConversionPattern" value="%d %-5p %c - %m%n"/> * </layout> * <connectionSource class="org.apache.log4j.jdbc.JNDIConnectionSource"> * <param name="jndiLocation" value="jdbc/MySQLDS" /> * </connectionSource> * <b> * <preparedStatementSource class="my.wonderful.implmentation.of.PreparedStatementSource"> * <param name="myParam1" value="myValue1" /> * <param name="myParam2" value="myValue2" /> * </preparedStatementSource> * </b> * <loggerParameter class="org.apache.log4j.jdbc.PreparedStatementParameter"> * <param name="columnName" value="logger" /> * </loggerParameter> * <levelParameter class="org.apache.log4j.jdbc.PreparedStatementParameter"> * <param name="columnName" value="level" /> * </levelParameter> * <exceptionParameter class="org.apache.log4j.jdbc.PreparedStatementParameter"> * <param name="columnName" value="exception" /> * </exceptionParameter> * <stackParameter class="org.apache.log4j.jdbc.PreparedStatementParameter"> * <param name="columnName" value="stack" /> * </stackParameter> * <formattedMessageParameter class="org.apache.log4j.jdbc.PreparedStatementParameter"> * <param name="columnName" value="formatted" /> * </formattedMessageParameter> * <timeStampParameter class="org.apache.log4j.jdbc.PreparedStatementParameter"> * <param name="columnName" value="stamp" /> * </timeStampParameter> * </appender> * </pre> * Use this configuration when you want to provide your own * [EMAIL PROTECTED] PreparedStatementSource} becuase the default statements are * insufficient. For example, you want to call a stored procedure or the like. * Note that you still must provide the <code>xxxParameter</code> * configurations. * * @author <a href="mailto:[EMAIL PROTECTED]">Ray DeCampo</a> */ public class PreparedStatementAppender extends AppenderSkeleton { private String table = "LOG4J"; private PreparedStatementParameter messageParameter = null; private PreparedStatementParameter loggerParameter = null; private PreparedStatementParameter levelParameter = null; private PreparedStatementParameter ndcParameter = null; private PreparedStatementParameter exceptionParameter = null; private PreparedStatementParameter stackParameter = null; private PreparedStatementParameter timeStampParameter = null; private PreparedStatementParameter formattedMessageParameter = null; private ConnectionSource connectionSource = null; private PreparedStatementSource preparedStatementSource = null; private StringBuffer sql = new StringBuffer(); private final ArrayList params = new ArrayList(); /** * Default constructor. */ public PreparedStatementAppender() { } public String getTable() { return table; } public void setTable(String newTable) { table = newTable; } public void activateOptions() { super.activateOptions(); // Set up default setters and create the params list if (messageParameter != null) { params.add(messageParameter); messageParameter.setErrorHandler(errorHandler); if (messageParameter.getJdbcSetter() == null) { messageParameter.setJdbcSetter("setString"); } } if (loggerParameter != null) { params.add(loggerParameter); loggerParameter.setErrorHandler(errorHandler); if (loggerParameter.getJdbcSetter() == null) { loggerParameter.setJdbcSetter("setString"); } } if (levelParameter != null) { params.add(levelParameter); levelParameter.setErrorHandler(errorHandler); if (levelParameter.getJdbcSetter() == null) { levelParameter.setJdbcSetter("setString"); } } if (ndcParameter != null) { params.add(ndcParameter); ndcParameter.setErrorHandler(errorHandler); if (ndcParameter.getJdbcSetter() == null) { ndcParameter.setJdbcSetter("setString"); } } if (exceptionParameter != null) { params.add(exceptionParameter); exceptionParameter.setErrorHandler(errorHandler); if (exceptionParameter.getJdbcSetter() == null) { exceptionParameter.setJdbcSetter("setString"); } } if (stackParameter != null) { params.add(stackParameter); stackParameter.setErrorHandler(errorHandler); if (stackParameter.getJdbcSetter() == null) { stackParameter.setJdbcSetter("setCharacterStream"); } } if (timeStampParameter != null) { params.add(timeStampParameter); timeStampParameter.setErrorHandler(errorHandler); if (timeStampParameter.getJdbcSetter() == null) { timeStampParameter.setJdbcSetter("setTimestamp"); } } if (formattedMessageParameter != null) { params.add(formattedMessageParameter); formattedMessageParameter.setErrorHandler(errorHandler); if (formattedMessageParameter.getJdbcSetter() == null) { formattedMessageParameter.setJdbcSetter("setString"); } } params.trimToSize(); connectionSource.setErrorHandler(errorHandler); connectionSource.activateOptions(); if (preparedStatementSource == null) { generateSql(); } else { preparedStatementSource.activateOptions(); } } public void append(LoggingEvent event) { Throwable throwable = null; if (event.getThrowableInformation() != null) { throwable = event.getThrowableInformation().getThrowable(); } Connection conn = null; PreparedStatement stmt = null; try { conn = connectionSource.getConnection(); if (preparedStatementSource != null) { stmt = preparedStatementSource.generate(this, conn); } else { stmt = conn.prepareStatement(sql.toString()); } // Set stmt parameters if (messageParameter != null) { messageParameter.setParameter( stmt, String.valueOf(event.getMessage())); } if (loggerParameter != null) { loggerParameter.setParameter(stmt, event.getLoggerName()); } if (levelParameter != null) { levelParameter.setParameter(stmt, event.getLevel()); } if (ndcParameter != null) { ndcParameter.setParameter(stmt, event.getNDC()); } if (exceptionParameter != null) { if (throwable != null) { exceptionParameter.setParameter(stmt, throwable.getMessage()); } else { exceptionParameter.setParameter(stmt, ""); } } if (stackParameter != null) { stackParameter.setParameter(stmt, event.getThrowableInformation()); } if (timeStampParameter != null) { timeStampParameter.setParameter(stmt, event.timeStamp); } if (formattedMessageParameter != null) { formattedMessageParameter.setParameter( stmt, getLayout().format(event)); } // OK, do the dirty deed stmt.executeUpdate(); } catch (final SQLException sqle) { errorHandler.error( "Error executing SQL: " + sql, sqle, ErrorCode.GENERIC_FAILURE, event); } finally { closeJdbc(stmt, conn); } } public boolean requiresLayout() { return true; } public void close() { } private void generateSql() { int colCount = 0; sql.setLength(0); sql.append("INSERT INTO ").append(table).append(" ("); for (int i = 0; i < params.size(); i++) { colCount = appendColumn(getParameter(i), colCount); } sql.append(") VALUES ("); for (int i = 0; i < colCount; i++) { sql.append((i == 0) ? "?" : ", ?"); } sql.append(")"); System.out.println(sql); } private int appendColumn(PreparedStatementParameter psp, int colCount) { if ((psp != null) && (psp.getColumnName() != null)) { sql.append((colCount == 0) ? "" : ", ").append(psp.getColumnName()); psp.setOrder(++colCount); System.out.println( "JDBC setter for " + psp.getColumnName() + " is " + psp.getJdbcSetter()); } return colCount; } private void closeJdbc(PreparedStatement stmt, Connection conn) { try { if (stmt != null) { stmt.close(); } } catch (final SQLException sqle) { errorHandler.error( "Error closing prepared statement", sqle, ErrorCode.GENERIC_FAILURE); } try { if (conn != null) { conn.close(); } } catch (final SQLException sqle) { errorHandler.error( "Error closing connection", sqle, ErrorCode.GENERIC_FAILURE); } } private PreparedStatementParameter getParameter(int i) { return (PreparedStatementParameter) params.get(i); } /** * Returns the timeStampParameter. * @return PreparedStatementParameter */ public PreparedStatementParameter getTimeStampParameter() { return timeStampParameter; } /** * Returns the exceptionParameter. * @return PreparedStatementParameter */ public PreparedStatementParameter getExceptionParameter() { return exceptionParameter; } /** * Returns the formattedMessageParameter. * @return PreparedStatementParameter */ public PreparedStatementParameter getFormattedMessageParameter() { return formattedMessageParameter; } /** * Returns the levelParameter. * @return PreparedStatementParameter */ public PreparedStatementParameter getLevelParameter() { return levelParameter; } /** * Returns the loggerParameter. * @return PreparedStatementParameter */ public PreparedStatementParameter getLoggerParameter() { return loggerParameter; } /** * Returns the messageParameter. * @return PreparedStatementParameter */ public PreparedStatementParameter getMessageParameter() { return messageParameter; } /** * Returns the ndcParameter. * @return PreparedStatementParameter */ public PreparedStatementParameter getNdcParameter() { return ndcParameter; } /** * Returns the stackParameter. * @return PreparedStatementParameter */ public PreparedStatementParameter getStackParameter() { return stackParameter; } /** * Sets the timeStampParameter. * @param timeStampParameter The timeStampParameter to set */ public void setTimeStampParameter(PreparedStatementParameter date) { this.timeStampParameter = date; } /** * Sets the exceptionParameter. * @param exceptionParameter The exceptionParameter to set */ public void setExceptionParameter(PreparedStatementParameter exception) { this.exceptionParameter = exception; } /** * Sets the formattedMessageParameter. * @param formattedMessageParameter The formattedMessageParameter to set */ public void setFormattedMessageParameter( PreparedStatementParameter formattedMsg) { this.formattedMessageParameter = formattedMsg; } /** * Sets the levelParameter. * @param levelParameter The levelParameter to set */ public void setLevelParameter(PreparedStatementParameter level) { this.levelParameter = level; } /** * Sets the loggerParameter. * @param loggerParameter The loggerParameter to set */ public void setLoggerParameter(PreparedStatementParameter logger) { this.loggerParameter = logger; } /** * Sets the messageParameter. * @param messageParameter The messageParameter to set */ public void setMessageParameter(PreparedStatementParameter msg) { this.messageParameter = msg; } /** * Sets the ndcParameter. * @param ndcParameter The ndcParameter to set */ public void setNdcParameter(PreparedStatementParameter ndc) { this.ndcParameter = ndc; } /** * Sets the stackParameter. * @param stackParameter The stackParameter to set */ public void setStackParameter(PreparedStatementParameter stack) { this.stackParameter = stack; } /** * Returns the connectionSource. * @return ConnectionSource */ public ConnectionSource getConnectionSource() { return connectionSource; } /** * Sets the connectionSource. * @param connectionSource The connectionSource to set */ public void setConnectionSource(ConnectionSource connectionSource) { this.connectionSource = connectionSource; } /** * Returns the preparedStatementSource. * @return PreparedStatementSource */ public PreparedStatementSource getPreparedStatementSource() { return preparedStatementSource; } /** * Sets the preparedStatementSource. * @param preparedStatementSource The preparedStatementSource to set */ public void setPreparedStatementSource( PreparedStatementSource preparedStatementSource) { this.preparedStatementSource = preparedStatementSource; } } 1.1 jakarta-log4j-sandbox/src/java/org/apache/log4j/jdbc/JNDIConnectionSource.java Index: JNDIConnectionSource.java =================================================================== /* * ============================================================================ * The Apache Software License, Version 1.1 * ============================================================================ * * Copyright (C) 1999 The Apache Software Foundation. All rights reserved. * * Redistribution and use in source and binary forms, with or without modifica- * tion, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * 3. The end-user documentation included with the redistribution, if any, must * include the following acknowledgment: "This product includes software * developed by the Apache Software Foundation (http://www.apache.org/)." * Alternately, this acknowledgment may appear in the software itself, if * and wherever such third-party acknowledgments normally appear. * * 4. The names "log4j" and "Apache Software Foundation" must not be used to * endorse or promote products derived from this software without prior * written permission. For written permission, please contact * [EMAIL PROTECTED] * * 5. Products derived from this software may not be called "Apache", nor may * "Apache" appear in their name, without prior written permission of the * Apache Software Foundation. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU- * DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * This software consists of voluntary contributions made by many individuals * on behalf of the Apache Software Foundation. For more information on the * Apache Software Foundation, please see <http://www.apache.org/>. * */ package org.apache.log4j.jdbc; import org.apache.log4j.spi.ErrorHandler; import java.sql.Connection; import java.sql.SQLException; import javax.naming.Context; import javax.naming.InitialContext; import javax.naming.NamingException; import javax.rmi.PortableRemoteObject; import javax.sql.DataSource; /** * The <code>JNDIConnectionSource</code> is an implementation of * [EMAIL PROTECTED] ConnectionSource} that obtains a [EMAIL PROTECTED] javax.sql.DataSource} from a * JNDI provider and uses it to obtain a [EMAIL PROTECTED] java.sql.Connection}. It is * primarily designed to be used inside of J2EE application servers or * application server clients, assuming the application server supports remote * access of [EMAIL PROTECTED] javax.sql.DataSource}s. In this way one can take * advantage of connection pooling and whatever other goodies the application * server provides. * <p> * Sample configuration:<br> * <pre> * <connectionSource class="org.apache.log4j.jdbc.JNDIConnectionSource"> * <param name="jndiLocation" value="jdbc/MySQLDS" /> * </connectionSource> * </pre> * <p> * Sample configuration (with username and password):<br> * <pre> * <connectionSource class="org.apache.log4j.jdbc.JNDIConnectionSource"> * <param name="jndiLocation" value="jdbc/MySQLDS" /> * <param name="username" value="myUser" /> * <param name="password" value="myPassword" /> * </connectionSource> * </pre> * <p> * Note that this class will obtain an [EMAIL PROTECTED] javax.naming.InitialContext} * using the no-argument constructor. This will usually work when executing * within a J2EE environment. When outside the J2EE environment, make sure * that you provide a jndi.properties file as described by your JNDI * provider's documentation. * * @author <a href="mailto:[EMAIL PROTECTED]">Ray DeCampo</a> */ public class JNDIConnectionSource implements ConnectionSource { private String jndiLocation = null; private DataSource dataSource = null; private ErrorHandler errorHandler = null; private String username = null; private String password = null; /** * @see org.apache.log4j.jdbc.ConnectionSource#getConnection() */ public Connection getConnection() throws SQLException { Connection conn = null; try { ensureDataSource(); if (username == null) { conn = dataSource.getConnection(); } else { conn = dataSource.getConnection(username, password); } } catch (final NamingException ne) { if (errorHandler != null) { errorHandler.error(ne.getMessage(), ne, 0); } throw new SQLException( "NamingException while looking up " + "DataSource: " + ne.getMessage()); } catch (final ClassCastException cce) { if (errorHandler != null) { errorHandler.error(cce.getMessage(), cce, 0); } throw new SQLException( "ClassCastException while looking up " + "DataSource: " + cce.getMessage()); } return conn; } /** * @see org.apache.log4j.spi.OptionHandler#activateOptions() */ public void activateOptions() { } /** * Returns the jndiLocation. * @return String */ public String getJndiLocation() { return jndiLocation; } /** * Sets the jndiLocation. * @param jndiLocation The jndiLocation to set */ public void setJndiLocation(String jndiLocation) { this.jndiLocation = jndiLocation; } /** * Sets the error handler. * @param errorHandler the error handler to set */ public void setErrorHandler(ErrorHandler errorHandler) { this.errorHandler = errorHandler; } /** * Returns the password. * @return String */ public String getPassword() { return password; } /** * Returns the username. * @return String */ public String getUsername() { return username; } /** * Sets the password. * @param password The password to set */ public void setPassword(String password) { this.password = password; } /** * Sets the username. * @param username The username to set */ public void setUsername(String username) { this.username = username; } private void ensureDataSource() throws NamingException, SQLException { if (dataSource == null) { Context ctx = new InitialContext(); Object obj = ctx.lookup(jndiLocation); dataSource = (DataSource) PortableRemoteObject.narrow(obj, DataSource.class); } if (dataSource == null) { throw new SQLException( "Failed to obtain data source from JNDI " + "location " + jndiLocation); } } } 1.1 jakarta-log4j-sandbox/src/java/org/apache/log4j/jdbc/ConnectionSource.java Index: ConnectionSource.java =================================================================== /* * ============================================================================ * The Apache Software License, Version 1.1 * ============================================================================ * * Copyright (C) 1999 The Apache Software Foundation. All rights reserved. * * Redistribution and use in source and binary forms, with or without modifica- * tion, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * 3. The end-user documentation included with the redistribution, if any, must * include the following acknowledgment: "This product includes software * developed by the Apache Software Foundation (http://www.apache.org/)." * Alternately, this acknowledgment may appear in the software itself, if * and wherever such third-party acknowledgments normally appear. * * 4. The names "log4j" and "Apache Software Foundation" must not be used to * endorse or promote products derived from this software without prior * written permission. For written permission, please contact * [EMAIL PROTECTED] * * 5. Products derived from this software may not be called "Apache", nor may * "Apache" appear in their name, without prior written permission of the * Apache Software Foundation. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU- * DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * This software consists of voluntary contributions made by many individuals * on behalf of the Apache Software Foundation. For more information on the * Apache Software Foundation, please see <http://www.apache.org/>. * */ package org.apache.log4j.jdbc; import org.apache.log4j.spi.ErrorHandler; import org.apache.log4j.spi.OptionHandler; import java.sql.Connection; import java.sql.SQLException; /** * The <code>ConnectionSource</code> interface provides a pluggable means of * transparently obtaining JDBC [EMAIL PROTECTED] java.sql.Connection}s for log4j classes * that require the use of a [EMAIL PROTECTED] java.sql.Connection}. * * @author <a href="mailto:[EMAIL PROTECTED]">Ray DeCampo</a> */ public interface ConnectionSource extends OptionHandler { /** * Obtain a [EMAIL PROTECTED] java.sql.Connection} for use. The client is * responsible for closing the [EMAIL PROTECTED] java.sql.Connection} when it is no * longer required. * * @throws SQLException if a [EMAIL PROTECTED] java.sql.Connection} could not be * obtained */ Connection getConnection() throws SQLException; /** * Set the error handler. * * @param errorHanlder the new error handler */ void setErrorHandler(ErrorHandler errorHandler); }
--------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]