mwomack     2003/06/10 21:58:18

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

---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to