The JDBC package is a special case because it is still being developed by Ray DeCampo who does not have access to log4j CVS (nor to the sandbox by the way).
At 10:17 AM 6/24/2003 -0700, you wrote:
I guess part of my point is that these classes are not related to the Chainsaw changes, and are still under development in the sandbox.
-Mark
> -----Original Message----- > From: Mark Womack > Sent: Tuesday, June 24, 2003 9:49 AM > To: 'Log4J Developers List' > Subject: RE: cvs commit: jakarta-log4j/src/java/org/apache/log4j/jdbc > Prep aredStatementSource.java PreparedStatementParameter.java > ConnectionSource .java JDBCReceiver.java UrlConnectionSource.java > PreparedStatementAppende r.java JNDIConnectionSource.java > > > I don't think we made the decision to move these specific > classes into the > core cvs yet. Did we? > > -Mark > > > -----Original Message----- > > From: [EMAIL PROTECTED] [mailto:[EMAIL PROTECTED] > > Sent: Tuesday, June 24, 2003 1:19 AM > > To: [EMAIL PROTECTED] > > Subject: cvs commit: jakarta-log4j/src/java/org/apache/log4j/jdbc > > PreparedStatementSource.java PreparedStatementParameter.java > > ConnectionSource.java JDBCReceiver.java UrlConnectionSource.java > > PreparedStatementAppender.java JNDIConnectionSource.java > > > > > > psmith 2003/06/24 01:19:11 > > > > Added: src/java/org/apache/log4j/jdbc > > PreparedStatementSource.java > > PreparedStatementParameter.java > > ConnectionSource.java JDBCReceiver.java > > UrlConnectionSource.java > > PreparedStatementAppender.java > > JNDIConnectionSource.java > > Log: > > moving to jakarta-log4j from jakarta-log4j-sandbox. > > > > Revision Changes Path > > 1.1 > > jakarta-log4j/src/java/org/apache/log4j/jdbc/PreparedStatement > > Source.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/src/java/org/apache/log4j/jdbc/PreparedStatement > > Parameter.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/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); > > } > > > > > > > > 1.1 > > jakarta-log4j/src/java/org/apache/log4j/jdbc/JDBCReceiver.java > > > > Index: JDBCReceiver.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.Logger; > > import org.apache.log4j.plugins.Receiver; > > import org.apache.log4j.spi.LocationInfo; > > import org.apache.log4j.spi.LoggingEvent; > > > > import java.sql.Connection; > > import java.sql.DriverManager; > > import java.sql.ResultSet; > > import java.sql.SQLException; > > import java.sql.Statement; > > > > import java.util.Hashtable; > > import java.util.StringTokenizer; > > > > > > /** > > * Convert Log data stored in a database into LoggingEvents. > > * > > * This receiver executes the SQL statement defined in the > > plugin configuration once, > > * converting the rows it finds into LoggingEvents, and then ends. > > * > > * The configuration of this plugin is very similar to the > > JDBCAppender, however a > > * SELECT statement must be provided instead of an INSERT > statement. > > * > > * The select statement must provide all fields which > > define a LoggingEvent, with > > * the column names matching this list: LOGGER, TIMESTAMP, > > LEVEL, THREAD, MESSAGE, > > * NDC, MDC, CLASS, METHOD, FILE, LINE, PROPERTIES, EXCEPTION > > * > > * If the source table doesn't provide a column for any of > > the fields, the field must > > * still be provided in the SELECT statement. For example, > > if a JDBCAppender was used > > * to write only a timestamp, level and patternlayout > > combination of message and other > > * fields, here is a sample SQL statement you would provide > > as the plugin 'sql' param: > > * > > * EXAMPLE MYSQL SELECT STATEMENT WHICH CAN BE USED TO > > PROVIDE EVENTS TO CHAINSAW - > > * (counter is an autoincrement int column and timestamp is > > a datetime column): > > * > > * param name="sql" value='select logger as LOGGER, > > timestamp as TIMESTAMP, > > * level as LEVEL, thread as THREAD, message as MESSAGE, > > ndc as NDC, mdc as MDC, > > * class as CLASS, method as METHOD, file as FILE, line as LINE, > > * > > concat("{{log4japp,databaselogs,log4jmachinename,mymachine,log > > 4jid,", COUNTER, "}}") > > * as PROPERTIES, "" as EXCEPTION from logtable' > > * > > * In other words, if a number of LoggingEvent properties > > were combined into one field > > * in the database, the combined field should be set as the > > MESSAGE column in the > > * SELECT statement. Missing columns should be set to "". > > * > > * Make sure to alias the column names if needed to match > > the list provided above. > > * > > * NOTE: Patternlayout doesn't support Properties and > > JDBCAppender doesn't support > > * exceptions, but the fields can be defined in the SQL > > statement and included in > > * the event. > > * > > * This means that log4japp and/or log4jmachinename > > properties can be provided and > > * the properties may be used to create a unique tab for > the events. > > * > > * Both {{name, value, name2, value2}} formats and formats > > without the double braces > > * are supported for MDC and properties fields. > > * > > * NOTE: If refreshMillis is not set, the receiver will run > > the SQL ONCE. If it is set, > > * the SQL will be ran every refreshMillis milliseconds. > > * > > * WARNING: Using refreshMillis with an event processing > > tool that doesn't know how > > * to ignore duplicate events will result in duplicate > > events being processed. > > * > > * CREATING EVENTS USABLE BY CHAINSAW: > > * Chainsaw's event reception ignores duplicate event > > delivery, so refreshMillis can be > > * set and JDBCReceiver can be used as a primary receiver > > with Chainsaw - allowing > > * a timed re-retrieve of events from a database into the > > UI for analysis of events. > > * > > * Include the properties as provided in the example SQL > > above to successfully get > > * events to be delivered into Chainsaw. The log4jid > > property must be provided by the > > * database and the timestamp field must be a datetime. > > The log4jmachinename and log4japp > > * properties are specific to your application and define > > which unique tab the events are > > * delivered to. > > * > > * @author Scott Deboy <[EMAIL PROTECTED]> > > * > > */ > > public class JDBCReceiver extends Receiver { > > private boolean isActive = false; > > > > /** > > * URL of the DB for default connection handling > > */ > > protected String databaseURL = "jdbc:odbc:myDB"; > > > > /** > > * User to connect as for default connection handling > > */ > > protected String databaseUser = "me"; > > > > /** > > * User to use for default connection handling > > */ > > protected String databasePassword = "mypassword"; > > protected Connection connection = null; > > protected String sqlStatement = ""; > > protected String refreshMillis = null; > > > > public JDBCReceiver() { > > } > > > > /** > > * Start a thread which will handle the retrieval. > > */ > > public void activateOptions() { > > new JDBCReceiverThread().start(); > > } > > > > protected Connection getConnection() throws SQLException { > > if (!DriverManager.getDrivers().hasMoreElements()) { > > setDriver("sun.jdbc.odbc.JdbcOdbcDriver"); > > } > > > > if (connection == null) { > > connection = > > DriverManager.getConnection( > > databaseURL, databaseUser, databasePassword); > > } > > > > return connection; > > } > > > > public void close() { > > try { > > if ((connection != null) && !connection.isClosed()) { > > connection.close(); > > } > > } catch (SQLException e) { > > e.printStackTrace(); > > } > > } > > > > public void finalize() { > > close(); > > } > > > > public synchronized void shutdown() { > > } > > > > public void setRefreshMillis(String s) { > > refreshMillis = s; > > } > > > > public String getRefreshMillis() { > > return refreshMillis; > > } > > > > public void setSql(String s) { > > sqlStatement = s; > > } > > > > public String getSql() { > > return sqlStatement; > > } > > > > public void setUser(String user) { > > databaseUser = user; > > } > > > > public String getUser() { > > return databaseUser; > > } > > > > public void setURL(String url) { > > databaseURL = url; > > } > > > > public String getURL() { > > return databaseURL; > > } > > > > public void setPassword(String password) { > > databasePassword = password; > > } > > > > public String getPassword() { > > return databasePassword; > > } > > > > /** > > * Ensures that the given driver class has been loaded > > for sql connection > > * creation. > > */ > > public void setDriver(String driverClass) { > > try { > > Class.forName(driverClass); > > } catch (Exception e) { > > e.printStackTrace(); > > } > > } > > > > class JDBCReceiverThread extends Thread { > > public JDBCReceiverThread() { > > setDaemon(true); > > } > > > > public void run() { > > active = true; > > > > do { > > try { > > Logger logger = null; > > long timeStamp = 0L; > > String level = null; > > String threadName = null; > > Object message = null; > > String ndc = null; > > Hashtable mdc = null; > > String[] exception = null; > > String className = null; > > String methodName = null; > > String fileName = null; > > String lineNumber = null; > > Hashtable properties = null; > > > > Statement statement = getConnection().createStatement(); > > ResultSet rs = statement.executeQuery(sqlStatement); > > > > while (rs.next()) { > > logger = Logger.getLogger(rs.getString("LOGGER")); > > timeStamp = rs.getTimestamp("TIMESTAMP").getTime(); > > > > level = rs.getString("LEVEL"); > > threadName = rs.getString("THREAD"); > > message = rs.getString("MESSAGE"); > > ndc = rs.getString("NDC"); > > > > String mdcString = rs.getString("MDC"); > > mdc = new Hashtable(); > > > > if (mdcString != null) { > > //support MDC being wrapped in {{name, > > value}} or just name, value > > if ( > > (mdcString.indexOf("{{") > -1) > > && (mdcString.indexOf("}}") > -1)) { > > mdcString = > > mdcString.substring( > > mdcString.indexOf("{{") + 2, > > mdcString.indexOf("}}")); > > } > > > > StringTokenizer tok = new > > StringTokenizer(mdcString, ","); > > > > while (tok.countTokens() > 1) { > > mdc.put(tok.nextToken(), tok.nextToken()); > > } > > } > > > > //although exception is not supported by > > jdbcappender, it needs to be provided in the SQL string > > exception = new String[] { > rs.getString("EXCEPTION") }; > > className = rs.getString("CLASS"); > > methodName = rs.getString("METHOD"); > > fileName = rs.getString("FILE"); > > lineNumber = rs.getString("LINE"); > > > > //although properties are not supported by > > JDBCAppender, if they are provided in the > > //SQL they can be used here (for example, to > > route events to a unique tab if > > //the machinename and/or appname property are set) > > String propertiesString = rs.getString("PROPERTIES"); > > properties = new Hashtable(); > > > > if (propertiesString != null) { > > //support properties being wrapped in {{name, > > value}} or just name, value > > if ( > > (propertiesString.indexOf("{{") > -1) > > && (propertiesString.indexOf("}}") > -1)) { > > propertiesString = > > propertiesString.substring( > > propertiesString.indexOf("{{") + 2, > > propertiesString.indexOf("}}")); > > } > > > > StringTokenizer tok2 = > > new StringTokenizer(propertiesString, ","); > > > > while (tok2.countTokens() > 1) { > > properties.put(tok2.nextToken(), > tok2.nextToken()); > > } > > } > > > > Level levelImpl = Level.toLevel(level); > > > > LoggingEvent event = > > new LoggingEvent( > > logger.getName(), logger, timeStamp, > > levelImpl, threadName, > > message, ndc, mdc, exception, > > new LocationInfo(fileName, className, > > methodName, lineNumber), > > properties); > > > > doPost(event); > > } > > } catch (SQLException se) { > > se.printStackTrace(); > > } > > > > if (refreshMillis != null) { > > try { > > Thread.sleep(Integer.parseInt(refreshMillis)); > > } catch (InterruptedException ie) { > > } > > } > > } while (refreshMillis != null); > > } > > } > > } > > > > > > > > 1.1 > > > jakarta-log4j/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/src/java/org/apache/log4j/jdbc/PreparedStatement > > Appender.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.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/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); > > } > > } > > } > > > > > > > > > > > --------------------------------------------------------------------- > > To unsubscribe, e-mail: [EMAIL PROTECTED] > > For additional commands, e-mail: [EMAIL PROTECTED] > > > > --------------------------------------------------------------------- > To unsubscribe, e-mail: [EMAIL PROTECTED] > For additional commands, e-mail: [EMAIL PROTECTED] >
--------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]
--
Ceki For log4j documentation consider "The complete log4j manual"
ISBN: 2970036908 http://www.qos.ch/shop/products/clm_t.jsp
--------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]