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/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/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/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,log4jid,", 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/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.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]