logging-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From sde...@apache.org
Subject svn commit: r1178304 [1/6] - in /logging/chainsaw/trunk: ./ src/main/java/org/apache/log4j/ src/main/java/org/apache/log4j/db/ src/main/java/org/apache/log4j/db/dialect/ src/main/java/org/apache/log4j/helpers/ src/main/java/org/apache/log4j/net/ src/ma...
Date Mon, 03 Oct 2011 06:15:43 GMT
Author: sdeboy
Date: Mon Oct  3 06:15:40 2011
New Revision: 1178304

URL: http://svn.apache.org/viewvc?rev=1178304&view=rev
Log:
Moved component and receivers companion sources to the Chainsaw source tree - those companions won't be released.

Added:
    logging/chainsaw/trunk/src/main/java/org/apache/log4j/LoggerRepositoryExImpl.java
      - copied unchanged from r1177631, logging/log4j/companions/component/trunk/src/main/java/org/apache/log4j/LoggerRepositoryExImpl.java
    logging/chainsaw/trunk/src/main/java/org/apache/log4j/ULogger.java
      - copied unchanged from r1177631, logging/log4j/companions/component/trunk/src/main/java/org/apache/log4j/ULogger.java
    logging/chainsaw/trunk/src/main/java/org/apache/log4j/db/
    logging/chainsaw/trunk/src/main/java/org/apache/log4j/db/ConnectionSource.java
    logging/chainsaw/trunk/src/main/java/org/apache/log4j/db/ConnectionSourceSkeleton.java
    logging/chainsaw/trunk/src/main/java/org/apache/log4j/db/CustomSQLDBReceiver.java
    logging/chainsaw/trunk/src/main/java/org/apache/log4j/db/DBAppender.java
    logging/chainsaw/trunk/src/main/java/org/apache/log4j/db/DBHelper.java
    logging/chainsaw/trunk/src/main/java/org/apache/log4j/db/DBReceiver.java
    logging/chainsaw/trunk/src/main/java/org/apache/log4j/db/DBReceiverJob.java
    logging/chainsaw/trunk/src/main/java/org/apache/log4j/db/DataSourceConnectionSource.java
    logging/chainsaw/trunk/src/main/java/org/apache/log4j/db/DriverManagerConnectionSource.java
    logging/chainsaw/trunk/src/main/java/org/apache/log4j/db/JNDIConnectionSource.java
    logging/chainsaw/trunk/src/main/java/org/apache/log4j/db/dialect/
    logging/chainsaw/trunk/src/main/java/org/apache/log4j/db/dialect/HSQLDBDialect.java
    logging/chainsaw/trunk/src/main/java/org/apache/log4j/db/dialect/MsSQLDialect.java
    logging/chainsaw/trunk/src/main/java/org/apache/log4j/db/dialect/MySQLDialect.java
    logging/chainsaw/trunk/src/main/java/org/apache/log4j/db/dialect/OracleDialect.java
    logging/chainsaw/trunk/src/main/java/org/apache/log4j/db/dialect/PostgreSQLDialect.java
    logging/chainsaw/trunk/src/main/java/org/apache/log4j/db/dialect/SQLDialect.java
    logging/chainsaw/trunk/src/main/java/org/apache/log4j/db/dialect/SybaseDialect.java
    logging/chainsaw/trunk/src/main/java/org/apache/log4j/db/dialect/Util.java
    logging/chainsaw/trunk/src/main/java/org/apache/log4j/db/dialect/db2.sql
    logging/chainsaw/trunk/src/main/java/org/apache/log4j/db/dialect/db2l.sql
    logging/chainsaw/trunk/src/main/java/org/apache/log4j/db/dialect/hsqldb.sql
    logging/chainsaw/trunk/src/main/java/org/apache/log4j/db/dialect/mssql.sql
    logging/chainsaw/trunk/src/main/java/org/apache/log4j/db/dialect/mysql.sql
    logging/chainsaw/trunk/src/main/java/org/apache/log4j/db/dialect/oracle.sql
    logging/chainsaw/trunk/src/main/java/org/apache/log4j/db/dialect/postgresql.sql
    logging/chainsaw/trunk/src/main/java/org/apache/log4j/db/package.html
    logging/chainsaw/trunk/src/main/java/org/apache/log4j/helpers/
    logging/chainsaw/trunk/src/main/java/org/apache/log4j/helpers/Constants.java
    logging/chainsaw/trunk/src/main/java/org/apache/log4j/helpers/MessageFormatter.java
    logging/chainsaw/trunk/src/main/java/org/apache/log4j/helpers/UtilLoggingLevel.java
      - copied unchanged from r1177642, logging/log4j/companions/receivers/trunk/src/main/java/org/apache/log4j/helpers/UtilLoggingLevel.java
    logging/chainsaw/trunk/src/main/java/org/apache/log4j/net/
    logging/chainsaw/trunk/src/main/java/org/apache/log4j/net/AddressBased.java
    logging/chainsaw/trunk/src/main/java/org/apache/log4j/net/JMSReceiver.java
    logging/chainsaw/trunk/src/main/java/org/apache/log4j/net/JMSReceiverBeanInfo.java
    logging/chainsaw/trunk/src/main/java/org/apache/log4j/net/MulticastAppender.java
    logging/chainsaw/trunk/src/main/java/org/apache/log4j/net/MulticastReceiver.java
    logging/chainsaw/trunk/src/main/java/org/apache/log4j/net/MulticastReceiverBeanInfo.java
    logging/chainsaw/trunk/src/main/java/org/apache/log4j/net/NetworkBased.java
    logging/chainsaw/trunk/src/main/java/org/apache/log4j/net/PortBased.java
    logging/chainsaw/trunk/src/main/java/org/apache/log4j/net/SocketHubReceiver.java
    logging/chainsaw/trunk/src/main/java/org/apache/log4j/net/SocketNode13.java
    logging/chainsaw/trunk/src/main/java/org/apache/log4j/net/SocketNodeEventListener.java
    logging/chainsaw/trunk/src/main/java/org/apache/log4j/net/SocketReceiver.java
    logging/chainsaw/trunk/src/main/java/org/apache/log4j/net/UDPAppender.java
    logging/chainsaw/trunk/src/main/java/org/apache/log4j/net/UDPReceiver.java
    logging/chainsaw/trunk/src/main/java/org/apache/log4j/net/XMLSocketNode.java
    logging/chainsaw/trunk/src/main/java/org/apache/log4j/net/XMLSocketReceiver.java
    logging/chainsaw/trunk/src/main/java/org/apache/log4j/plugins/
    logging/chainsaw/trunk/src/main/java/org/apache/log4j/plugins/Pauseable.java
    logging/chainsaw/trunk/src/main/java/org/apache/log4j/plugins/Plugin.java
    logging/chainsaw/trunk/src/main/java/org/apache/log4j/plugins/PluginEvent.java
    logging/chainsaw/trunk/src/main/java/org/apache/log4j/plugins/PluginListener.java
    logging/chainsaw/trunk/src/main/java/org/apache/log4j/plugins/PluginRegistry.java
    logging/chainsaw/trunk/src/main/java/org/apache/log4j/plugins/PluginSkeleton.java
    logging/chainsaw/trunk/src/main/java/org/apache/log4j/plugins/Receiver.java
    logging/chainsaw/trunk/src/main/java/org/apache/log4j/rewrite/
    logging/chainsaw/trunk/src/main/java/org/apache/log4j/rewrite/MapRewritePolicy.java
    logging/chainsaw/trunk/src/main/java/org/apache/log4j/rewrite/PropertyRewritePolicy.java
    logging/chainsaw/trunk/src/main/java/org/apache/log4j/rewrite/ReflectionRewritePolicy.java
    logging/chainsaw/trunk/src/main/java/org/apache/log4j/rewrite/RewriteAppender.java
    logging/chainsaw/trunk/src/main/java/org/apache/log4j/rewrite/RewritePolicy.java
    logging/chainsaw/trunk/src/main/java/org/apache/log4j/scheduler/
    logging/chainsaw/trunk/src/main/java/org/apache/log4j/scheduler/Job.java
    logging/chainsaw/trunk/src/main/java/org/apache/log4j/scheduler/Scheduler.java
    logging/chainsaw/trunk/src/main/java/org/apache/log4j/spi/
    logging/chainsaw/trunk/src/main/java/org/apache/log4j/spi/Component.java
    logging/chainsaw/trunk/src/main/java/org/apache/log4j/spi/ComponentBase.java
    logging/chainsaw/trunk/src/main/java/org/apache/log4j/spi/Decoder.java
      - copied unchanged from r1177642, logging/log4j/companions/receivers/trunk/src/main/java/org/apache/log4j/spi/Decoder.java
    logging/chainsaw/trunk/src/main/java/org/apache/log4j/spi/ErrorItem.java
    logging/chainsaw/trunk/src/main/java/org/apache/log4j/spi/Log4JULogger.java
    logging/chainsaw/trunk/src/main/java/org/apache/log4j/spi/LoggerEventListener.java
    logging/chainsaw/trunk/src/main/java/org/apache/log4j/spi/LoggerRepositoryEventListener.java
    logging/chainsaw/trunk/src/main/java/org/apache/log4j/spi/LoggerRepositoryEx.java
    logging/chainsaw/trunk/src/main/java/org/apache/log4j/spi/NOPULogger.java
    logging/chainsaw/trunk/src/main/java/org/apache/log4j/spi/SimpleULogger.java
    logging/chainsaw/trunk/src/main/java/org/apache/log4j/spi/Thresholdable.java
    logging/chainsaw/trunk/src/main/java/org/apache/log4j/varia/
    logging/chainsaw/trunk/src/main/java/org/apache/log4j/varia/ListModelAppender.java
    logging/chainsaw/trunk/src/main/java/org/apache/log4j/varia/LogFilePatternReceiver.java
    logging/chainsaw/trunk/src/main/java/org/apache/log4j/varia/LogFilePatternReceiverBeanInfo.java
    logging/chainsaw/trunk/src/main/java/org/apache/log4j/xml/
    logging/chainsaw/trunk/src/main/java/org/apache/log4j/xml/LogFileXMLReceiver.java
      - copied unchanged from r1177642, logging/log4j/companions/receivers/trunk/src/main/java/org/apache/log4j/xml/LogFileXMLReceiver.java
    logging/chainsaw/trunk/src/main/java/org/apache/log4j/xml/UtilLoggingEntityResolver.java
      - copied unchanged from r1177642, logging/log4j/companions/receivers/trunk/src/main/java/org/apache/log4j/xml/UtilLoggingEntityResolver.java
    logging/chainsaw/trunk/src/main/java/org/apache/log4j/xml/UtilLoggingXMLDecoder.java
      - copied unchanged from r1177642, logging/log4j/companions/receivers/trunk/src/main/java/org/apache/log4j/xml/UtilLoggingXMLDecoder.java
    logging/chainsaw/trunk/src/main/java/org/apache/log4j/xml/XMLDecoder.java
      - copied unchanged from r1177642, logging/log4j/companions/receivers/trunk/src/main/java/org/apache/log4j/xml/XMLDecoder.java
    logging/chainsaw/trunk/src/test/java/org/apache/log4j/VectorAppender.java
      - copied unchanged from r1177642, logging/log4j/companions/receivers/trunk/src/test/java/org/apache/log4j/VectorAppender.java
    logging/chainsaw/trunk/src/test/java/org/apache/log4j/db/
    logging/chainsaw/trunk/src/test/java/org/apache/log4j/db/FullCycleDBTest.java
    logging/chainsaw/trunk/src/test/java/org/apache/log4j/helpers/
    logging/chainsaw/trunk/src/test/java/org/apache/log4j/helpers/UtilLoggingLevelTest.java
    logging/chainsaw/trunk/src/test/java/org/apache/log4j/rewrite/
    logging/chainsaw/trunk/src/test/java/org/apache/log4j/rewrite/RewriteAppenderTest.java
    logging/chainsaw/trunk/src/test/java/org/apache/log4j/util/
    logging/chainsaw/trunk/src/test/java/org/apache/log4j/util/Compare.java
    logging/chainsaw/trunk/src/test/java/org/apache/log4j/xml/
    logging/chainsaw/trunk/src/test/java/org/apache/log4j/xml/XMLDecoderTest.java
    logging/chainsaw/trunk/src/test/resources/org/
    logging/chainsaw/trunk/src/test/resources/org/apache/
    logging/chainsaw/trunk/src/test/resources/org/apache/log4j/
    logging/chainsaw/trunk/src/test/resources/org/apache/log4j/db/
    logging/chainsaw/trunk/src/test/resources/org/apache/log4j/db/append-with-drivermanager1.xml
    logging/chainsaw/trunk/src/test/resources/org/apache/log4j/db/read-with-drivermanager1.xml
    logging/chainsaw/trunk/src/test/resources/org/apache/log4j/rewrite/
    logging/chainsaw/trunk/src/test/resources/org/apache/log4j/rewrite/map.log
    logging/chainsaw/trunk/src/test/resources/org/apache/log4j/rewrite/map.xml
    logging/chainsaw/trunk/src/test/resources/org/apache/log4j/rewrite/property.log
    logging/chainsaw/trunk/src/test/resources/org/apache/log4j/rewrite/property.xml
    logging/chainsaw/trunk/src/test/resources/org/apache/log4j/rewrite/reflection.log
    logging/chainsaw/trunk/src/test/resources/org/apache/log4j/rewrite/reflection.xml
    logging/chainsaw/trunk/src/test/resources/org/apache/log4j/xml/
    logging/chainsaw/trunk/src/test/resources/org/apache/log4j/xml/xmlLayout.1.xml
    logging/chainsaw/trunk/src/test/resources/org/apache/log4j/xml/xsltLayout.1.xml
Modified:
    logging/chainsaw/trunk/HOWTOBUILD.txt
    logging/chainsaw/trunk/pom.xml
    logging/chainsaw/trunk/src/main/resources/org/apache/log4j/chainsaw/help/release-notes.html

Modified: logging/chainsaw/trunk/HOWTOBUILD.txt
URL: http://svn.apache.org/viewvc/logging/chainsaw/trunk/HOWTOBUILD.txt?rev=1178304&r1=1178303&r2=1178304&view=diff
==============================================================================
--- logging/chainsaw/trunk/HOWTOBUILD.txt (original)
+++ logging/chainsaw/trunk/HOWTOBUILD.txt Mon Oct  3 06:15:40 2011
@@ -23,19 +23,6 @@ Firstly, you'll need maven 2.0.9+ to bui
 http://maven.apache.org
 
 
-Next, an interim step is required until the 'companions' are voted on and released:
-
-* SVN check out the following projects:
-	log4j-component - http://svn.apache.org/repos/asf/logging/log4j/companions/component/trunk/
-	log4j-extras - http://svn.apache.org/repos/asf/logging/log4j/companions/extras/trunk/
-	log4j-receivers - http://svn.apache.org/repos/asf/logging/log4j/companions/receivers/trunk/
-
-  In each of these checkout directories:
-  	mvn install
-
-  This will install into your local maven repository the correct releases of the required dependencies. 
-  These dependencies are not yet available in the standard maven repositories, and so failure to complete this step will prevent you from building Chainsaw.
-
 * cd to Chainsaw project checkout directory
 
 	mvn install

Modified: logging/chainsaw/trunk/pom.xml
URL: http://svn.apache.org/viewvc/logging/chainsaw/trunk/pom.xml?rev=1178304&r1=1178303&r2=1178304&view=diff
==============================================================================
--- logging/chainsaw/trunk/pom.xml (original)
+++ logging/chainsaw/trunk/pom.xml Mon Oct  3 06:15:40 2011
@@ -118,8 +118,7 @@
       <plugin>
         <artifactId>maven-compiler-plugin</artifactId>
         <configuration>
-          <source>1.2</source>
-          <target>1.1</target>
+          <source>1.4</source>
         </configuration>
       </plugin>
       <plugin>
@@ -220,7 +219,7 @@
             <artifactId>ant-contrib</artifactId>
             <version>1.0b2</version>
           </dependency>
-        </dependencies>
+	</dependencies>
       </plugin>
         <plugin>
           <groupId>org.codehaus.mojo</groupId>
@@ -324,6 +323,14 @@
           <iconFile>${basedir}/src/main/resources/logo.icns</iconFile>
           <bundleName>Chainsaw</bundleName>
         </configuration>
+        <executions>
+            <execution>
+                <phase>package</phase>
+                <goals>
+                    <goal>bundle</goal>
+                </goals>
+            </execution>
+       </executions>
       </plugin>
       <plugin>
         <groupId>org.codehaus.mojo</groupId>
@@ -386,17 +393,6 @@
     </dependency>
     <dependency>
       <groupId>log4j</groupId>
-      <artifactId>apache-log4j-receivers</artifactId>
-      <version>1.0-SNAPSHOT</version>
-    </dependency>
-    <dependency>
-      <groupId>log4j</groupId>
-      <artifactId>apache-log4j-receivers</artifactId>
-      <version>1.0-SNAPSHOT</version>
-      <classifier>javadoc</classifier>
-    </dependency>
-    <dependency>
-      <groupId>log4j</groupId>
       <artifactId>log4j</artifactId>
       <version>1.2.16</version>
     </dependency>
@@ -437,6 +433,18 @@
       <artifactId>jsch</artifactId>
       <version>0.1.42</version>
     </dependency>
+    <dependency>
+		<groupId>hsqldb</groupId>
+		<artifactId>hsqldb</artifactId>
+		<version>1.8.0.7</version>
+		<scope>test</scope>
+	</dependency>
+    <dependency>
+        <groupId>org.apache.geronimo.specs</groupId>
+        <artifactId>geronimo-jms_1.1_spec</artifactId>
+        <version>1.0</version>
+        <optional>true</optional>
+    </dependency>
   </dependencies>
   <reporting>
     <excludeDefaults>true</excludeDefaults>
@@ -480,7 +488,7 @@
       </plugin>
     </plugins>
   </reporting>
-  <distributionManagement>
+    <distributionManagement>
     <repository>
       <id>logging.repo</id>
       <url>scp://people.apache.org/www/people.apache.org/builds/logging/repo/</url>

Added: logging/chainsaw/trunk/src/main/java/org/apache/log4j/db/ConnectionSource.java
URL: http://svn.apache.org/viewvc/logging/chainsaw/trunk/src/main/java/org/apache/log4j/db/ConnectionSource.java?rev=1178304&view=auto
==============================================================================
--- logging/chainsaw/trunk/src/main/java/org/apache/log4j/db/ConnectionSource.java (added)
+++ logging/chainsaw/trunk/src/main/java/org/apache/log4j/db/ConnectionSource.java Mon Oct  3 06:15:40 2011
@@ -0,0 +1,69 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.log4j.db;
+
+import org.apache.log4j.spi.Component;
+import org.apache.log4j.spi.OptionHandler;
+
+import java.sql.Connection;
+import java.sql.SQLException;
+
+
+/**
+ *  The <id>ConnectionSource</id> interface provides a pluggable means of
+ *  transparently obtaining JDBC {@link java.sql.Connection}s for log4j classes
+ *  that require the use of a {@link java.sql.Connection}.
+ *
+ *  @author <a href="mailto:rdecampo@twcny.rr.com">Ray DeCampo</a>
+ */
+public interface ConnectionSource extends Component, OptionHandler {
+
+  final int UNKNOWN_DIALECT = 0;
+  final int POSTGRES_DIALECT = 1;
+  final int MYSQL_DIALECT = 2;
+  final int ORACLE_DIALECT = 3;
+  final int MSSQL_DIALECT = 4;
+  final int HSQL_DIALECT = 5;  
+  /**
+   *  Obtain a {@link java.sql.Connection} for use.  The client is
+   *  responsible for closing the {@link java.sql.Connection} when it is no
+   *  longer required.
+   *
+   *  @throws SQLException  if a {@link java.sql.Connection} could not be
+   *                        obtained
+   */
+  Connection getConnection() throws SQLException;
+
+  /**
+   * Get the SQL dialect that should be used for this connection. Note that the
+   * dialect is not needed if the JDBC driver supports the getGeneratedKeys 
+   * method.
+   */
+  int getSQLDialectCode();
+  
+  /**
+   * If the connection supports the JDBC 3.0 getGeneratedKeys method, then
+   * we do not need any specific dialect support.
+   */
+  boolean supportsGetGeneratedKeys();
+  
+  /**
+   * If the connection does not support batch updates, we will avoid using them.
+   */  
+  public boolean supportsBatchUpdates();
+}

Added: logging/chainsaw/trunk/src/main/java/org/apache/log4j/db/ConnectionSourceSkeleton.java
URL: http://svn.apache.org/viewvc/logging/chainsaw/trunk/src/main/java/org/apache/log4j/db/ConnectionSourceSkeleton.java?rev=1178304&view=auto
==============================================================================
--- logging/chainsaw/trunk/src/main/java/org/apache/log4j/db/ConnectionSourceSkeleton.java (added)
+++ logging/chainsaw/trunk/src/main/java/org/apache/log4j/db/ConnectionSourceSkeleton.java Mon Oct  3 06:15:40 2011
@@ -0,0 +1,150 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.log4j.db;
+
+import java.sql.Connection;
+import java.sql.DatabaseMetaData;
+import java.sql.SQLException;
+
+import org.apache.log4j.db.dialect.Util;
+import org.apache.log4j.spi.ComponentBase;
+
+
+/**
+ * @author Ceki G&uuml;lc&uuml;
+ */
+public abstract class ConnectionSourceSkeleton extends ComponentBase implements ConnectionSource {
+  
+  private Boolean overriddenSupportsGetGeneratedKeys = null;
+  
+  private String user = null;
+  private String password = null;
+
+  // initially we have an unkonw dialect
+  private int dialectCode = UNKNOWN_DIALECT;
+  private boolean supportsGetGeneratedKeys = false;
+  private boolean supportsBatchUpdates = false;
+
+
+  /**
+   * Learn relevant information about this connection source.
+   *
+   */
+  public void discoverConnnectionProperties() {
+    Connection connection = null;
+    try {
+      connection = getConnection();
+      if (connection == null) {
+        getLogger().warn("Could not get a conneciton");
+        return;
+      }
+      DatabaseMetaData meta = connection.getMetaData();
+      Util util = new Util();
+      util.setLoggerRepository(repository);
+      if (overriddenSupportsGetGeneratedKeys != null) {
+        supportsGetGeneratedKeys = overriddenSupportsGetGeneratedKeys
+            .booleanValue();
+      } else {
+        supportsGetGeneratedKeys = util.supportsGetGeneratedKeys(meta);
+      }
+      supportsBatchUpdates = util.supportsBatchUpdates(meta);
+      dialectCode = Util.discoverSQLDialect(meta);
+    } catch (SQLException se) {
+      getLogger().warn("Could not discover the dialect to use.", se);
+    } finally {
+      DBHelper.closeConnection(connection);
+    }
+  }
+
+  /**
+   * Does this connection support the JDBC Connection.getGeneratedKeys method?
+   */
+  public final boolean supportsGetGeneratedKeys() {
+    return supportsGetGeneratedKeys;
+  }
+
+  public final int getSQLDialectCode() {
+    return dialectCode;
+  }
+
+  /**
+   * Get the password for this connection source.
+   */
+  public final String getPassword() {
+    return password;
+  }
+
+  /**
+   * Sets the password.
+   * @param password The password to set
+   */
+  public final void setPassword(final String password) {
+    this.password = password;
+  }
+
+  /**
+   * Get the user for this connection source.
+   */
+  public final String getUser() {
+    return user;
+  }
+
+  /**
+   * Sets the username.
+   * @param username The username to set
+   */
+  public final void setUser(final String username) {
+    this.user = username;
+  }
+
+  /**
+   * Returns the "overridden" value of "supportsGetGeneratedKeys" property of
+   * the JDBC driver. In certain cases, getting (e.g. Oracle 10g) generated keys
+   * does not work because it returns the ROWID, not the value of the sequence.
+   * 
+   * @return A non null string, with "true" or "false" value, if overridden,
+   *         <code>null</code> if not overridden.
+   */
+  public String getOverriddenSupportsGetGeneratedKeys() {
+    return overriddenSupportsGetGeneratedKeys != null ? overriddenSupportsGetGeneratedKeys
+        .toString()
+        : null;
+  }
+
+  /**
+   * Sets the "overridden" value of "supportsGetGeneratedKeys" property of the
+   * JDBC driver. In certain cases, getting (e.g. Oracle 10g) generated keys
+   * does not work because it returns the ROWID, not the value of the sequence.
+   * 
+   * @param overriddenSupportsGetGeneratedKeys
+   *          A non null string, with "true" or "false" value, if overridden,
+   *          <code>null</code> if not overridden.
+   */
+  public void setOverriddenSupportsGetGeneratedKeys(
+      String overriddenSupportsGetGeneratedKeys) {
+    this.overriddenSupportsGetGeneratedKeys = Boolean
+        .valueOf(overriddenSupportsGetGeneratedKeys);
+  }
+  
+  /**
+   * Does this connection support batch updates?
+   */
+  public final boolean supportsBatchUpdates() {
+    return supportsBatchUpdates;
+  }
+}

Added: logging/chainsaw/trunk/src/main/java/org/apache/log4j/db/CustomSQLDBReceiver.java
URL: http://svn.apache.org/viewvc/logging/chainsaw/trunk/src/main/java/org/apache/log4j/db/CustomSQLDBReceiver.java?rev=1178304&view=auto
==============================================================================
--- logging/chainsaw/trunk/src/main/java/org/apache/log4j/db/CustomSQLDBReceiver.java (added)
+++ logging/chainsaw/trunk/src/main/java/org/apache/log4j/db/CustomSQLDBReceiver.java Mon Oct  3 06:15:40 2011
@@ -0,0 +1,468 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.log4j.db;
+
+import java.sql.Connection;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Statement;
+import java.util.Hashtable;
+import java.util.Properties;
+import java.util.StringTokenizer;
+
+import org.apache.log4j.Level;
+import org.apache.log4j.Logger;
+import org.apache.log4j.plugins.Pauseable;
+import org.apache.log4j.plugins.Receiver;
+import org.apache.log4j.scheduler.Job;
+import org.apache.log4j.scheduler.Scheduler;
+import org.apache.log4j.spi.LocationInfo;
+import org.apache.log4j.spi.LoggerRepositoryEx;
+import org.apache.log4j.spi.LoggingEvent;
+import org.apache.log4j.spi.ThrowableInformation;
+import org.apache.log4j.xml.DOMConfigurator;
+import org.apache.log4j.xml.UnrecognizedElementHandler;
+import org.w3c.dom.Element;
+
+/**
+ * Converts log data stored in a database into LoggingEvents.
+ * <p>
+ * <b>NOTE:</b> This receiver cannot yet be created through Chainsaw's receiver panel.  
+ * It must be created through an XML configuration file.
+ * <p>
+ * This receiver supports database configuration via ConnectionSource, in the
+ * org.apache.log4j.db package: DriverManagerConnectionSource,
+ * DataSourceConnectionSource, JNDIConnectionSource
+ * <p>
+ * This database receiver differs from DBReceiver in that this receiver relies
+ * on custom SQL to retrieve logging event data, where DBReceiver requires the
+ * use of a log4j-defined schema.
+ * <p>
+ * A 'refreshMillis' int parameter controls SQL execution. If 'refreshMillis' is
+ * zero (the default), the receiver will run only one time. If it is set to any
+ * other numeric value, the SQL will be executed on a recurring basis every
+ * 'refreshMillis' milliseconds.
+ * <p>
+ * The receiver closes the connection and acquires a new connection on each 
+ * execution of the SQL (use pooled connections if possible).
+ * <p>
+ * If the SQL will be executing on a recurring basis, specify the IDField param -
+ * the column name holding the unique identifier (int) representing the logging
+ * event.
+ * <p>
+ * As events are retrieved, the column represented by IDField is examined and
+ * the largest value is held and used by the next execution of the SQL statement
+ * to avoid retrieving previously processed events.
+ * <p>
+ * As an example, the IDField references a 'COUNTER' (int, auto-increment,
+ * unique) column. The first execution of the SQL statement returns 500 rows,
+ * with a final value in the COUNTER field of 500.
+ * <p>
+ * The SQL statement is manipulated prior to the next execution, adding ' WHERE
+ * COUNTER > 500' to the statement to avoid retrieval of previously processed
+ * events.
+ * <p>
+ * The select statement must provide ALL fields which define a LoggingEvent.
+ * <p>
+ * The SQL statement MUST include the columns: LOGGER, TIMESTAMP, LEVEL, THREAD,
+ * MESSAGE, NDC, MDC, CLASS, METHOD, FILE, LINE, PROPERTIES, THROWABLE
+ * <p>
+ * Use ' AS ' in the SQL statement to alias the SQL's column names to match your
+ * database schema. (see example below).
+ * <p>
+ * Include all fields in the SQL statement, even if you don't have data for the
+ * field (specify an empty string as the value for columns which you don't have
+ * data).
+ * <p>
+ * The TIMESTAMP column must be a datetime.
+ * <p>
+ * Both a PROPERTIES column and an MDC column are supported. These fields
+ * represent Maps on the logging event, but require the use of string
+ * concatenation database functions to hold the (possibly multiple) name/value
+ * pairs in the column.
+ * <p>
+ * For example, to include both 'userid' and 'lastname' properties in the
+ * logging event (from either the PROPERTIES or MDC columns), the name/value
+ * pairs must be concatenated together by your database.
+ * <p>
+ * The resulting PROPERTIES or MDC column must have data in this format: {{name,
+ * value, name2, value2}}
+ * <p>
+ * The resulting PROPERTIES column would contain this text: {{userid, someone,
+ * lastname, mylastname}}
+ * <p>
+ * Here is an example of concatenating a PROPERTIES or MDC column using MySQL's
+ * concat function, where the 'application' and 'hostname' parameters were fixed
+ * text, but the 'log4jid' key's value is the value of the COUNTER column:
+ * <p>
+ * concat("{{application,databaselogs,hostname,mymachine,log4jid,", COUNTER,
+ * "}}") as PROPERTIES
+ * <p>
+ * log4jid is a special property that is used by Chainsaw to represent an 'ID'
+ * field. Specify this property to ensure you can map events in Chainsaw to
+ * events in the database if you need to go back and view events at a later time
+ * or save the events to XML for later analysis.
+ * <p>
+ * Here is a complete MySQL SQL statement which can be used to provide events to
+ * Chainsaw (note how in the example below, there is no column in logtable representing the throwable, so an
+ * empty string is passed in and an ALIAS is still defined):
+ * <p>
+ * select myloggercolumn as LOGGER, mytimestampcolumn as TIMESTAMP, mylevelcolumn as LEVEL, mythreadcolumn as
+ * THREAD, mymessagecolumn as MESSAGE, myndccolumn as NDC, mymdccolumn as MDC, myclasscolumn as CLASS, mymethodcolumn as
+ * METHOD, myfilecolumn as FILE, mylinecolumn as LINE,
+ * concat("{{application,databaselogs,hostname,mymachine, log4jid,",
+ * COUNTER,"}}") as PROPERTIES, "" as THROWABLE from logtable
+ * <p>
+ * @author Scott Deboy <sdeboy@apache.org>
+ * <p>
+ */
+public class CustomSQLDBReceiver extends Receiver implements Pauseable, UnrecognizedElementHandler {
+
+    protected volatile Connection connection = null;
+
+    protected String sqlStatement = "";
+
+    /**
+     * By default we refresh data every 1000 milliseconds.
+     * 
+     * @see #setRefreshMillis
+     */
+    static int DEFAULT_REFRESH_MILLIS = 1000;
+
+    int refreshMillis = DEFAULT_REFRESH_MILLIS;
+
+    protected String idField = null;
+
+    int lastID = -1;
+
+    private static final String WHERE_CLAUSE = " WHERE ";
+
+    private static final String AND_CLAUSE = " AND ";
+
+    private boolean whereExists = false;
+
+    private boolean paused = false;
+
+    private ConnectionSource connectionSource;
+
+    public static final String LOG4J_ID_KEY = "log4jid";
+
+    private Job customReceiverJob;
+
+    public void activateOptions() {
+      
+      if(connectionSource == null)  {
+        throw new IllegalStateException(
+          "CustomSQLDBReceiver cannot function without a connection source");
+      }
+      whereExists = (sqlStatement.toUpperCase().indexOf(WHERE_CLAUSE) > -1);
+    
+      customReceiverJob = new CustomReceiverJob();
+        
+      if(this.repository == null) {
+        throw new IllegalStateException(
+        "CustomSQLDBReceiver cannot function without a reference to its owning repository");
+      }
+     
+    
+
+      if (repository instanceof LoggerRepositoryEx) {
+        Scheduler scheduler = ((LoggerRepositoryEx) repository).getScheduler();
+      
+        scheduler.schedule(
+          customReceiverJob, System.currentTimeMillis() + 500, refreshMillis);
+      }
+
+    }
+
+    void closeConnection() {
+        if (connection != null) {
+            try {
+                // LogLog.warn("closing the connection. ", new Exception("x"));
+                connection.close();
+            } catch (SQLException sqle) {
+                // nothing we can do here
+            }
+        }
+    }
+
+    public void setRefreshMillis(int refreshMillis) {
+        this.refreshMillis = refreshMillis;
+    }
+
+    public int getRefreshMillis() {
+        return refreshMillis;
+    }
+
+    /**
+     * @return Returns the connectionSource.
+     */
+    public ConnectionSource getConnectionSource() {
+        return connectionSource;
+    }
+
+    /**
+     * @param connectionSource
+     *            The connectionSource to set.
+     */
+    public void setConnectionSource(ConnectionSource connectionSource) {
+        this.connectionSource = connectionSource;
+    }
+
+    public void close() {
+        try {
+            if ((connection != null) && !connection.isClosed()) {
+                connection.close();
+            }
+        } catch (SQLException e) {
+            e.printStackTrace();
+        } finally {
+            connection = null;
+        }
+    }
+
+    public void finalize() throws Throwable {
+        super.finalize();
+        close();
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.log4j.plugins.Plugin#shutdown()
+     */
+    public void shutdown() {
+        getLogger().info("removing receiverJob from the Scheduler.");
+
+        if(this.repository instanceof LoggerRepositoryEx) {
+          Scheduler scheduler = ((LoggerRepositoryEx) repository).getScheduler();
+          scheduler.delete(customReceiverJob);
+        }
+
+        lastID = -1;
+    }
+
+    public void setSql(String s) {
+        sqlStatement = s;
+    }
+
+    public String getSql() {
+        return sqlStatement;
+    }
+
+    public void setIDField(String id) {
+        idField = id;
+    }
+
+    public String getIDField() {
+        return idField;
+    }
+
+    public synchronized void setPaused(boolean p) {
+        paused = p;
+    }
+
+    public synchronized boolean isPaused() {
+        return paused;
+    }
+
+    class CustomReceiverJob implements Job {
+        public void execute() {
+            int oldLastID = lastID;
+            try {
+                connection = connectionSource.getConnection();
+                Statement statement = connection.createStatement();
+
+                Logger eventLogger = null;
+                long timeStamp = 0L;
+                String level = null;
+                String threadName = null;
+                Object message = null;
+                String ndc = null;
+                Hashtable mdc = null;
+                String[] throwable = null;
+                String className = null;
+                String methodName = null;
+                String fileName = null;
+                String lineNumber = null;
+                Hashtable properties = null;
+
+                String currentSQLStatement = sqlStatement;
+                if (whereExists) {
+                    currentSQLStatement = sqlStatement + AND_CLAUSE + idField
+                            + " > " + lastID;
+                } else {
+                    currentSQLStatement = sqlStatement + WHERE_CLAUSE + idField
+                            + " > " + lastID;
+                }
+
+                ResultSet rs = statement.executeQuery(currentSQLStatement);
+
+                int i = 0;
+                while (rs.next()) {
+                    // add a small break every 1000 received events
+                    if (++i == 1000) {
+                        synchronized (this) {
+                            try {
+                                // add a delay
+                                wait(300);
+                            } catch (InterruptedException ie) {
+                            }
+                            i = 0;
+                        }
+                    }
+                    eventLogger = 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());
+                        }
+                    }
+
+                    throwable = new String[] { rs.getString("THROWABLE") };
+                    className = rs.getString("CLASS");
+                    methodName = rs.getString("METHOD");
+                    fileName = rs.getString("FILE");
+                    lineNumber = rs.getString("LINE");
+
+                    // if properties are provided in the
+                    // SQL they can be used here (for example, to route
+                    // events to a unique tab in
+                    // Chainsaw 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) {
+                            String tokenName = tok2.nextToken();
+                            String value = tok2.nextToken();
+                            if (tokenName.equals(LOG4J_ID_KEY)) {
+                                try {
+                                    int thisInt = Integer.parseInt(value);
+                                    value = String.valueOf(thisInt);
+                                    if (thisInt > lastID) {
+                                        lastID = thisInt;
+                                    }
+                                } catch (Exception e) {
+                                }
+                            }
+                            properties.put(tokenName, value);
+                        }
+                    }
+
+                    Level levelImpl = Level.toLevel(level);
+
+
+					LocationInfo locationInfo = new LocationInfo(fileName,
+	                            className, methodName, lineNumber);
+	
+					ThrowableInformation throwableInfo =  new ThrowableInformation(
+		                            throwable);
+	
+					properties.putAll(mdc);
+		
+				    LoggingEvent event = new LoggingEvent(eventLogger.getName(),
+				            eventLogger, timeStamp, levelImpl, message,
+				            threadName,
+				            throwableInfo,
+				            ndc,
+				            locationInfo,
+				            properties);
+
+                    doPost(event);
+                }
+                //log when rows are retrieved
+                if (lastID != oldLastID) {
+                    getLogger().debug("lastID: " + lastID);
+                    oldLastID = lastID;
+                }
+
+                statement.close();
+                statement = null;
+            } catch (SQLException sqle) {
+                getLogger()
+                        .error("*************Problem receiving events", sqle);
+            } finally {
+                closeConnection();
+            }
+
+            // if paused, loop prior to executing sql query
+            synchronized (this) {
+                while (isPaused()) {
+                    try {
+                        wait(1000);
+                    } catch (InterruptedException ie) {
+                    }
+                }
+            }
+        }
+    }
+
+    /**
+     * @{inheritDoc}
+     */
+  public boolean parseUnrecognizedElement(Element element, Properties props) throws Exception {
+        if ("connectionSource".equals(element.getNodeName())) {
+            Object instance =
+                    DOMConfigurator.parseElement(element, props, ConnectionSource.class);
+            if (instance instanceof ConnectionSource) {
+               ConnectionSource source = (ConnectionSource) instance;
+               source.activateOptions();
+               setConnectionSource(source);
+            }
+            return true;
+        }
+        return false;
+  }
+    
+}

Added: logging/chainsaw/trunk/src/main/java/org/apache/log4j/db/DBAppender.java
URL: http://svn.apache.org/viewvc/logging/chainsaw/trunk/src/main/java/org/apache/log4j/db/DBAppender.java?rev=1178304&view=auto
==============================================================================
--- logging/chainsaw/trunk/src/main/java/org/apache/log4j/db/DBAppender.java (added)
+++ logging/chainsaw/trunk/src/main/java/org/apache/log4j/db/DBAppender.java Mon Oct  3 06:15:40 2011
@@ -0,0 +1,403 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.log4j.db;
+
+import org.apache.log4j.AppenderSkeleton;
+import org.apache.log4j.db.dialect.SQLDialect;
+import org.apache.log4j.db.dialect.Util;
+import org.apache.log4j.helpers.LogLog;
+import org.apache.log4j.spi.LocationInfo;
+import org.apache.log4j.spi.LoggingEvent;
+import org.apache.log4j.xml.DOMConfigurator;
+import org.apache.log4j.xml.UnrecognizedElementHandler;
+import org.w3c.dom.Element;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.sql.Connection;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Statement;
+import java.util.Iterator;
+import java.util.Properties;
+import java.util.Set;
+
+
+/**
+ * The DBAppender inserts loggin events into three database tables in a format
+ * independent of the Java programming language. The three tables that
+ * DBAppender inserts to must exists before DBAppender can be used. These tables
+ * may be created with the help of SQL scripts found in the
+ * <em>src/java/org/apache/log4j/db/dialect</em> directory. There is a
+ * specific script for each of the most popular database systems. If the script
+ * for your particular type of database system is missing, it should be quite
+ * easy to write one, taking example on the already existing scripts. If you
+ * send them to us, we will gladly include missing scripts in future releases.
+ *
+ * <p>
+ * If the JDBC driver you are using supports the
+ * {@link java.sql.Statement#getGeneratedKeys}method introduced in JDBC 3.0
+ * specification, then you are all set. Otherwise, there must be an
+ * {@link SQLDialect}appropriate for your database system. Currently, we have
+ * dialects for PostgreSQL, MySQL, Oracle and MsSQL. As mentioed previously, an
+ * SQLDialect is required only if the JDBC driver for your database system does
+ * not support the {@link java.sql.Statement#getGeneratedKeys getGeneratedKeys}
+ * method.
+ * </p>
+ *
+ * <table border="1" cellpadding="4">
+ * <tr>
+ * <th>RDBMS</th>
+ * <th>supports <br/><code>getGeneratedKeys()</code> method</th>
+ * <th>specific <br/>SQLDialect support</th>
+ * <tr>
+ * <tr>
+ * <td>PostgreSQL</td>
+ * <td align="center">NO</td>
+ * <td>present and used</td>
+ * <tr>
+ * <tr>
+ * <td>MySQL</td>
+ * <td align="center">YES</td>
+ * <td>present, but not actually needed or used</td>
+ * <tr>
+ * <tr>
+ * <td>Oracle</td>
+ * <td align="center">YES</td>
+ * <td>present, but not actually needed or used</td>
+ * <tr>
+ * <tr>
+ * <td>DB2</td>
+ * <td align="center">YES</td>
+ * <td>not present, and not needed or used</td>
+ * <tr>
+ * <tr>
+ * <td>MsSQL</td>
+ * <td align="center">YES</td>
+ * <td>not present, and not needed or used</td>
+ * <tr>
+ * <tr>
+ *   <td>HSQL</td>
+ *    <td align="center">NO</td>
+ *    <td>present and used</td>
+ * <tr>
+ *
+ * </table>
+ * <p>
+ * <b>Performance: </b> Experiments show that writing a single event into the
+ * database takes approximately 50 milliseconds, on a "standard" PC. If pooled
+ * connections are used, this figure drops to under 10 milliseconds. Note that
+ * most JDBC drivers already ship with connection pooling support.
+ * </p>
+ *
+ *
+ *
+ * <p>
+ * <b>Configuration </b> DBAppender can be configured programmatically, or using
+ * {@link org.apache.log4j.xml.DOMConfigurator JoranConfigurator}. Example
+ * scripts can be found in the <em>tests/input/db</em> directory.
+ *
+ * @author Ceki G&uuml;lc&uuml;
+ * @author Ray DeCampo
+ */
+public class DBAppender extends AppenderSkeleton implements UnrecognizedElementHandler {
+  static final String insertPropertiesSQL =
+    "INSERT INTO  logging_event_property (event_id, mapped_key, mapped_value) VALUES (?, ?, ?)";
+  static final String insertExceptionSQL =
+    "INSERT INTO  logging_event_exception (event_id, i, trace_line) VALUES (?, ?, ?)";
+  static final String insertSQL;
+  private static final Method GET_GENERATED_KEYS_METHOD;
+
+
+  static {
+    StringBuffer sql = new StringBuffer();
+    sql.append("INSERT INTO logging_event (");
+    sql.append("sequence_number, ");
+    sql.append("timestamp, ");
+    sql.append("rendered_message, ");
+    sql.append("logger_name, ");
+    sql.append("level_string, ");
+    sql.append("ndc, ");
+    sql.append("thread_name, ");
+    sql.append("reference_flag, ");
+    sql.append("caller_filename, ");
+    sql.append("caller_class, ");
+    sql.append("caller_method, ");
+    sql.append("caller_line) ");
+    sql.append(" VALUES (?, ?, ? ,?, ?, ?, ?, ?, ?, ?, ?, ?)");
+    insertSQL = sql.toString();
+    //
+    //   PreparedStatement.getGeneratedKeys added in JDK 1.4
+    //
+    Method getGeneratedKeysMethod;
+    try {
+        getGeneratedKeysMethod = PreparedStatement.class.getMethod("getGeneratedKeys", null);
+    } catch(Exception ex) {
+        getGeneratedKeysMethod = null;
+    }
+    GET_GENERATED_KEYS_METHOD = getGeneratedKeysMethod;
+  }
+
+  ConnectionSource connectionSource;
+  boolean cnxSupportsGetGeneratedKeys = false;
+  boolean cnxSupportsBatchUpdates = false;
+  SQLDialect sqlDialect;
+  boolean locationInfo = false;
+  
+
+  public DBAppender() {
+      super(false);
+  }
+
+  public void activateOptions() {
+    LogLog.debug("DBAppender.activateOptions called");
+
+    if (connectionSource == null) {
+      throw new IllegalStateException(
+        "DBAppender cannot function without a connection source");
+    }
+
+    sqlDialect = Util.getDialectFromCode(connectionSource.getSQLDialectCode());
+    if (GET_GENERATED_KEYS_METHOD != null) {
+        cnxSupportsGetGeneratedKeys = connectionSource.supportsGetGeneratedKeys();
+    } else {
+        cnxSupportsGetGeneratedKeys = false;
+    }
+    cnxSupportsBatchUpdates = connectionSource.supportsBatchUpdates();
+    if (!cnxSupportsGetGeneratedKeys && (sqlDialect == null)) {
+      throw new IllegalStateException(
+        "DBAppender cannot function if the JDBC driver does not support getGeneratedKeys method *and* without a specific SQL dialect");
+    }
+    
+    // all nice and dandy on the eastern front
+    super.activateOptions();
+  }
+
+  /**
+   * @return Returns the connectionSource.
+   */
+  public ConnectionSource getConnectionSource() {
+    return connectionSource;
+  }
+
+  /**
+   * @param connectionSource
+   *          The connectionSource to set.
+   */
+  public void setConnectionSource(ConnectionSource connectionSource) {
+    LogLog.debug("setConnectionSource called for DBAppender");
+    this.connectionSource = connectionSource;
+  }
+
+  protected void append(LoggingEvent event) {
+      Connection connection = null;
+      try {
+          connection = connectionSource.getConnection();
+          connection.setAutoCommit(false);
+          
+          PreparedStatement insertStatement;
+          if (cnxSupportsGetGeneratedKeys) {
+        	  insertStatement = connection.prepareStatement(insertSQL, Statement.RETURN_GENERATED_KEYS);
+          } else {
+              insertStatement = connection.prepareStatement(insertSQL);
+          }
+
+/*          insertStatement.setLong(1, event.getSequenceNumber());*/
+		  insertStatement.setLong(1, 0);
+		
+          insertStatement.setLong(2, event.getTimeStamp());
+          insertStatement.setString(3, event.getRenderedMessage());
+          insertStatement.setString(4, event.getLoggerName());
+          insertStatement.setString(5, event.getLevel().toString());
+          insertStatement.setString(6, event.getNDC());
+          insertStatement.setString(7, event.getThreadName());
+          insertStatement.setShort(8, DBHelper.computeReferenceMask(event));
+          
+          LocationInfo li;
+          
+          if (event.locationInformationExists() || locationInfo) {
+              li = event.getLocationInformation();
+          } else {
+              li = LocationInfo.NA_LOCATION_INFO;
+          }
+          
+          insertStatement.setString(9, li.getFileName());
+          insertStatement.setString(10, li.getClassName());
+          insertStatement.setString(11, li.getMethodName());
+          insertStatement.setString(12, li.getLineNumber());
+          
+          int updateCount = insertStatement.executeUpdate();
+          if (updateCount != 1) {
+              LogLog.warn("Failed to insert loggingEvent");
+          }
+          
+          ResultSet rs = null;
+          Statement idStatement = null;
+          boolean gotGeneratedKeys = false;
+          if (cnxSupportsGetGeneratedKeys) {
+              try {
+                  rs = (ResultSet) GET_GENERATED_KEYS_METHOD.invoke(insertStatement, null);
+                  gotGeneratedKeys = true;
+              } catch(InvocationTargetException ex) {
+                  Throwable target = ex.getTargetException();
+                  if (target instanceof SQLException) {
+                      throw (SQLException) target;
+                  }
+                  throw ex; 
+              } catch(IllegalAccessException ex) {
+                  LogLog.warn("IllegalAccessException invoking PreparedStatement.getGeneratedKeys", ex);
+              }
+          }
+          
+          if (!gotGeneratedKeys) {
+              insertStatement.close();
+              insertStatement = null;
+              
+              idStatement = connection.createStatement();
+              idStatement.setMaxRows(1);
+              rs = idStatement.executeQuery(sqlDialect.getSelectInsertId());
+          }
+          
+          // A ResultSet cursor is initially positioned before the first row; the 
+          // first call to the method next makes the first row the current row
+          rs.next();
+          int eventId = rs.getInt(1);
+          
+          rs.close();
+
+          // we no longer need the insertStatement
+          if(insertStatement != null) {
+              insertStatement.close();
+              insertStatement = null;
+          }
+
+          if(idStatement != null) {
+              idStatement.close();
+              idStatement = null;
+          }
+
+          Set propertiesKeys = event.getPropertyKeySet();
+          
+          if (propertiesKeys.size() > 0) {
+              PreparedStatement insertPropertiesStatement =
+                  connection.prepareStatement(insertPropertiesSQL);
+              
+              for (Iterator i = propertiesKeys.iterator(); i.hasNext();) {
+                  String key = (String) i.next();
+                  String value = (String) event.getProperty(key);
+                  
+                  //LogLog.info("id " + eventId + ", key " + key + ", value " + value);
+                  insertPropertiesStatement.setInt(1, eventId);
+                  insertPropertiesStatement.setString(2, key);
+                  insertPropertiesStatement.setString(3, value);
+                  
+                  if (cnxSupportsBatchUpdates) {
+                      insertPropertiesStatement.addBatch();
+                  } else {
+                      insertPropertiesStatement.execute();
+                  }
+              }
+              
+              if (cnxSupportsBatchUpdates) {
+                  insertPropertiesStatement.executeBatch();
+              }
+              
+              insertPropertiesStatement.close();
+              insertPropertiesStatement = null;
+          }
+          
+          String[] strRep = event.getThrowableStrRep();
+          
+          if (strRep != null) {
+              LogLog.debug("Logging an exception");
+              
+              PreparedStatement insertExceptionStatement =
+                  connection.prepareStatement(insertExceptionSQL);
+              
+              for (short i = 0; i < strRep.length; i++) {
+                  insertExceptionStatement.setInt(1, eventId);
+                  insertExceptionStatement.setShort(2, i);
+                  insertExceptionStatement.setString(3, strRep[i]);
+                  if (cnxSupportsBatchUpdates) {
+                      insertExceptionStatement.addBatch();
+                  } else {
+                      insertExceptionStatement.execute();
+                  }
+              }
+              if (cnxSupportsBatchUpdates) {
+                  insertExceptionStatement.executeBatch();
+              }
+              insertExceptionStatement.close();
+              insertExceptionStatement = null;
+          }
+          
+          connection.commit();
+      } catch (Throwable sqle) {
+          LogLog.error("problem appending event", sqle);
+      } finally {
+          DBHelper.closeConnection(connection);
+      }
+  }
+
+  public void close() {
+    closed = true;
+  }
+
+  /**
+   * Returns value of the <b>LocationInfo </b> property which determines whether
+   * caller's location info is written to the database.
+   */
+  public boolean getLocationInfo() {
+    return locationInfo;
+  }
+
+  /**
+   * If true, the information written to the database will include caller's
+   * location information. Due to performance concerns, by default no location
+   * information is written to the database.
+   */
+  public void setLocationInfo(boolean locationInfo) {
+    this.locationInfo = locationInfo;
+  }
+
+    /**
+     * Gets whether appender requires a layout.
+     * @return false
+     */
+  public boolean requiresLayout() {
+      return false;
+  }
+
+    /**
+     * @{inheritDoc}
+     */
+  public boolean parseUnrecognizedElement(Element element, Properties props) throws Exception {
+        if ("connectionSource".equals(element.getNodeName())) {
+            Object instance =
+                    DOMConfigurator.parseElement(element, props, ConnectionSource.class);
+            if (instance instanceof ConnectionSource) {
+               ConnectionSource source = (ConnectionSource) instance;
+               source.activateOptions();
+               setConnectionSource(source);
+            }
+            return true;
+        }
+        return false;
+  }
+}

Added: logging/chainsaw/trunk/src/main/java/org/apache/log4j/db/DBHelper.java
URL: http://svn.apache.org/viewvc/logging/chainsaw/trunk/src/main/java/org/apache/log4j/db/DBHelper.java?rev=1178304&view=auto
==============================================================================
--- logging/chainsaw/trunk/src/main/java/org/apache/log4j/db/DBHelper.java (added)
+++ logging/chainsaw/trunk/src/main/java/org/apache/log4j/db/DBHelper.java Mon Oct  3 06:15:40 2011
@@ -0,0 +1,68 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.log4j.db;
+
+import java.sql.Connection;
+import java.sql.SQLException;
+import java.sql.Statement;
+import java.util.Set;
+
+import org.apache.log4j.spi.LoggingEvent;
+
+/**
+ * @author Ceki G&uuml;lc&uuml;
+ *
+ */
+public class DBHelper {
+  
+  public final static short PROPERTIES_EXIST = 0x01;
+  public final static short EXCEPTION_EXISTS = 0x02;
+  
+  public  static short computeReferenceMask(LoggingEvent event) {
+    short mask = 0;
+    Set propertiesKeys = event.getPropertyKeySet();
+    if(propertiesKeys.size() > 0) {
+      mask = PROPERTIES_EXIST;
+    }
+    String[] strRep = event.getThrowableStrRep();
+    if(strRep != null) {
+      mask |= EXCEPTION_EXISTS;
+    }
+    return mask;
+  }
+  
+  static public void closeConnection(Connection connection) {
+    if(connection != null) {
+      try { 
+        connection.close();
+      } catch(SQLException sqle) {
+        // static utility classes should not log without an explicit repository
+        // reference
+      }
+    }
+  }
+  
+  public static void closeStatement(Statement statement) {
+    if(statement != null) {
+      try {
+        statement.close();
+      } catch(SQLException sqle) {
+      }
+    }
+  }
+}

Added: logging/chainsaw/trunk/src/main/java/org/apache/log4j/db/DBReceiver.java
URL: http://svn.apache.org/viewvc/logging/chainsaw/trunk/src/main/java/org/apache/log4j/db/DBReceiver.java?rev=1178304&view=auto
==============================================================================
--- logging/chainsaw/trunk/src/main/java/org/apache/log4j/db/DBReceiver.java (added)
+++ logging/chainsaw/trunk/src/main/java/org/apache/log4j/db/DBReceiver.java Mon Oct  3 06:15:40 2011
@@ -0,0 +1,140 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.log4j.db;
+
+import org.apache.log4j.plugins.Pauseable;
+import org.apache.log4j.plugins.Receiver;
+import org.apache.log4j.scheduler.Scheduler;
+import org.apache.log4j.spi.LoggerRepositoryEx;
+import org.apache.log4j.xml.DOMConfigurator;
+import org.apache.log4j.xml.UnrecognizedElementHandler;
+import org.w3c.dom.Element;
+
+import java.util.Properties;
+
+/**
+ *
+ * @author Scott Deboy <sdeboy@apache.org>
+ * @author Ceki G&uuml;lc&uuml;
+ *
+ */
+public class DBReceiver extends Receiver implements Pauseable, UnrecognizedElementHandler {
+  /**
+   * By default we refresh data every 1000 milliseconds.
+   * @see #setRefreshMillis
+   */
+  static int DEFAULT_REFRESH_MILLIS = 1000;
+  ConnectionSource connectionSource;
+  int refreshMillis = DEFAULT_REFRESH_MILLIS;
+  DBReceiverJob receiverJob;
+  boolean paused = false;
+
+  public void activateOptions() {
+    
+    if(connectionSource == null)  {
+      throw new IllegalStateException(
+        "DBAppender cannot function without a connection source");
+    }
+  
+    receiverJob = new DBReceiverJob(this);
+    receiverJob.setLoggerRepository(repository);
+      
+    if(this.repository == null) {
+      throw new IllegalStateException(
+      "DBAppender cannot function without a reference to its owning repository");
+    }
+
+    if (repository instanceof LoggerRepositoryEx) {
+        Scheduler scheduler = ((LoggerRepositoryEx) repository).getScheduler();
+    
+        scheduler.schedule(
+            receiverJob, System.currentTimeMillis() + 500, refreshMillis);
+    }
+   
+  }
+
+  public void setRefreshMillis(int refreshMillis) {
+    this.refreshMillis = refreshMillis;
+  }
+
+  public int getRefreshMillis() {
+    return refreshMillis;
+  }
+
+
+  /**
+   * @return Returns the connectionSource.
+   */
+  public ConnectionSource getConnectionSource() {
+    return connectionSource;
+  }
+
+
+  /**
+   * @param connectionSource The connectionSource to set.
+   */
+  public void setConnectionSource(ConnectionSource connectionSource) {
+    this.connectionSource = connectionSource;
+  }
+
+
+  /* (non-Javadoc)
+   * @see org.apache.log4j.plugins.Plugin#shutdown()
+   */
+  public void shutdown() {
+    getLogger().info("removing receiverJob from the Scheduler.");
+
+    if(this.repository instanceof LoggerRepositoryEx) {
+      Scheduler scheduler = ((LoggerRepositoryEx) repository).getScheduler();
+      scheduler.delete(receiverJob);
+    }
+  }
+
+
+  /* (non-Javadoc)
+   * @see org.apache.log4j.plugins.Pauseable#setPaused(boolean)
+   */
+  public void setPaused(boolean paused) {
+    this.paused = paused;
+  }
+
+  /* (non-Javadoc)
+   * @see org.apache.log4j.plugins.Pauseable#isPaused()
+   */
+  public boolean isPaused() {
+    return paused;
+  }
+
+    /**
+     * @{inheritDoc}
+     */
+  public boolean parseUnrecognizedElement(Element element, Properties props) throws Exception {
+        if ("connectionSource".equals(element.getNodeName())) {
+            Object instance =
+                    DOMConfigurator.parseElement(element, props, ConnectionSource.class);
+            if (instance instanceof ConnectionSource) {
+                ConnectionSource source = (ConnectionSource) instance;
+                source.activateOptions();
+                setConnectionSource(source);
+            }
+            return true;
+        }
+        return false;
+  }
+
+}

Added: logging/chainsaw/trunk/src/main/java/org/apache/log4j/db/DBReceiverJob.java
URL: http://svn.apache.org/viewvc/logging/chainsaw/trunk/src/main/java/org/apache/log4j/db/DBReceiverJob.java?rev=1178304&view=auto
==============================================================================
--- logging/chainsaw/trunk/src/main/java/org/apache/log4j/db/DBReceiverJob.java (added)
+++ logging/chainsaw/trunk/src/main/java/org/apache/log4j/db/DBReceiverJob.java Mon Oct  3 06:15:40 2011
@@ -0,0 +1,230 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.log4j.db;
+
+import org.apache.log4j.Level;
+import org.apache.log4j.Logger;
+import org.apache.log4j.scheduler.Job;
+import org.apache.log4j.spi.ComponentBase;
+import org.apache.log4j.spi.LocationInfo;
+import org.apache.log4j.spi.LoggingEvent;
+import org.apache.log4j.spi.ThrowableInformation;
+
+import java.sql.Connection;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.Hashtable;
+import java.util.Vector;
+
+/**
+ * Actual retrieval of data is made by the instance of DBReceiverJob associated
+ * with DBReceiver.
+ * 
+ * @author Ceki G&uuml;lc&uuml;
+ */
+class DBReceiverJob extends ComponentBase implements Job {
+
+  String sqlException = "SELECT trace_line FROM logging_event_exception where event_id=? ORDER by i ASC";
+  String sqlProperties = "SELECT mapped_key, mapped_value FROM logging_event_property WHERE event_id=?";
+  String sqlSelect = 
+    "SELECT " +
+    "sequence_number, timestamp, rendered_message, logger_name, " +
+    "level_string, ndc, thread_name, reference_flag, " +
+    "caller_filename, caller_class, caller_method, caller_line, " +
+    "event_id " +
+    "FROM logging_event " +
+    "WHERE event_id > ?  ORDER BY event_id ASC";
+
+
+  long lastId = Short.MIN_VALUE;
+
+  DBReceiver parentDBReceiver;
+
+  DBReceiverJob(DBReceiver parent) {
+    parentDBReceiver = parent;
+  }
+
+  public void execute() {
+    getLogger().debug("DBReceiverJob.execute() called");
+
+    Connection connection = null;
+
+    try {
+      connection = parentDBReceiver.connectionSource.getConnection();
+      PreparedStatement statement = connection.prepareStatement(sqlSelect);
+      statement.setLong(1, lastId);
+      ResultSet rs = statement.executeQuery();
+      //rs.beforeFirst();
+
+      while (rs.next()) {
+	    Logger logger = null;
+	    long timeStamp = 0L;
+	    String level = null;
+	    String threadName = null;
+	    Object message = null;
+	    String ndc = null;
+	    String className = null;
+	    String methodName = null;
+	    String fileName = null;
+	    String lineNumber = null;
+	    Hashtable properties = new Hashtable();
+	
+
+        //event.setSequenceNumber(rs.getLong(1));
+        timeStamp = rs.getLong(2);
+        message = rs.getString(3);
+		logger = Logger.getLogger(rs.getString(4));
+        level = rs.getString(5);
+		Level levelImpl = Level.toLevel(level.trim());
+
+        ndc = rs.getString(6);
+        threadName = rs.getString(7);
+
+        short mask = rs.getShort(8);
+
+        fileName = rs.getString(9);
+        className = rs.getString(10);
+        methodName = rs.getString(11);
+        lineNumber = rs.getString(12).trim();
+
+		LocationInfo locationInfo = null;
+        if (fileName.equals(LocationInfo.NA)) {
+          locationInfo = LocationInfo.NA_LOCATION_INFO;
+        } else {
+          locationInfo = new LocationInfo(fileName, className,
+              methodName, lineNumber);
+        }
+
+        long id = rs.getLong(13);
+        //LogLog.info("Received event with id=" + id);
+        lastId = id;
+
+		ThrowableInformation throwableInfo = null;
+        if ((mask & DBHelper.EXCEPTION_EXISTS) != 0) {
+          throwableInfo = getException(connection, id);
+        }
+
+	    LoggingEvent event = new LoggingEvent(logger.getName(),
+	            logger, timeStamp, levelImpl, message,
+	            threadName,
+	            throwableInfo,
+	            ndc,
+	            locationInfo,
+	            properties);
+
+
+        // Scott asked for this info to be
+        event.setProperty("log4jid", Long.toString(id));
+
+        if ((mask & DBHelper.PROPERTIES_EXIST) != 0) {
+          getProperties(connection, id, event);
+        }
+
+
+
+
+        if (!parentDBReceiver.isPaused()) {
+          parentDBReceiver.doPost(event);
+        }
+      } // while
+      statement.close();
+      statement = null;
+    } catch (SQLException sqle) {
+      getLogger().error("Problem receiving events", sqle);
+    } finally {
+      closeConnection(connection);
+    }
+  }
+
+  void closeConnection(Connection connection) {
+    if (connection != null) {
+      try {
+        //LogLog.warn("closing the connection. ", new Exception("x"));
+        connection.close();
+      } catch (SQLException sqle) {
+        // nothing we can do here
+      }
+    }
+  }
+
+  /**
+   * Retrieve the event properties from the logging_event_property table.
+   * 
+   * @param connection
+   * @param id
+   * @param event
+   * @throws SQLException
+   */
+  void getProperties(Connection connection, long id, LoggingEvent event)
+      throws SQLException {
+
+    PreparedStatement statement = connection.prepareStatement(sqlProperties);
+    try {
+      statement.setLong(1, id);
+      ResultSet rs = statement.executeQuery();
+
+      while (rs.next()) {
+        String key = rs.getString(1);
+        String value = rs.getString(2);
+        event.setProperty(key, value);
+      }
+    } finally {
+      statement.close();
+    }
+  }
+
+  /**
+   * Retrieve the exception string representation from the
+   * logging_event_exception table.
+   * 
+   * @param connection
+   * @param id
+   * @throws SQLException
+   */
+  ThrowableInformation getException(Connection connection, long id)
+      throws SQLException {
+
+    PreparedStatement statement = null;
+
+    try {
+      statement = connection.prepareStatement(sqlException);
+      statement.setLong(1, id);
+      ResultSet rs = statement.executeQuery();
+
+      Vector v = new Vector();
+
+      while (rs.next()) {
+        //int i = rs.getShort(1);
+        v.add(rs.getString(1));
+      }
+
+      int len = v.size();
+      String[] strRep = new String[len];
+      for (int i = 0; i < len; i++) {
+        strRep[i] = (String) v.get(i);
+      }
+      // we've filled strRep, we now attach it to the event
+      return new ThrowableInformation(strRep);
+    } finally {
+      if (statement != null) {
+        statement.close();
+      }
+    }
+  }
+}
\ No newline at end of file

Added: logging/chainsaw/trunk/src/main/java/org/apache/log4j/db/DataSourceConnectionSource.java
URL: http://svn.apache.org/viewvc/logging/chainsaw/trunk/src/main/java/org/apache/log4j/db/DataSourceConnectionSource.java?rev=1178304&view=auto
==============================================================================
--- logging/chainsaw/trunk/src/main/java/org/apache/log4j/db/DataSourceConnectionSource.java (added)
+++ logging/chainsaw/trunk/src/main/java/org/apache/log4j/db/DataSourceConnectionSource.java Mon Oct  3 06:15:40 2011
@@ -0,0 +1,105 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.log4j.db;
+
+
+import org.apache.log4j.xml.DOMConfigurator;
+import org.apache.log4j.xml.UnrecognizedElementHandler;
+import org.w3c.dom.Element;
+
+import javax.sql.DataSource;
+import java.sql.Connection;
+import java.sql.SQLException;
+import java.util.Properties;
+
+
+/**
+ *  The DataSourceConnectionSource is an implementation of {@link ConnectionSource}
+ *  that obtains the Connection in the recommended JDBC manner based on
+ *  a {@link javax.sql.DataSource DataSource}.
+ *  <p>
+ *
+ *  @author Ray DeCampo
+ *  @author Ceki G&uuml;lc&uuml;
+ */
+public class DataSourceConnectionSource extends ConnectionSourceSkeleton
+        implements UnrecognizedElementHandler {
+
+  private DataSource dataSource;
+
+  
+  public void activateOptions() {
+    //LogLog.debug("**********DataSourceConnectionSource.activateOptions called");
+    if (dataSource == null) {
+      getLogger().warn("WARNING: No data source specified");
+    } else {
+      Connection connection = null;
+      try {
+        connection = getConnection();
+      } catch(SQLException se) {
+        getLogger().warn("Could not get a connection to discover the dialect to use.", se);
+      }
+      if(connection != null) {
+        discoverConnnectionProperties();
+      } 
+      if(!supportsGetGeneratedKeys() && getSQLDialectCode() == ConnectionSource.UNKNOWN_DIALECT) {
+        getLogger().warn("Connection does not support GetGeneratedKey method and could not discover the dialect.");
+      }
+    }
+  }
+
+  /**
+   * @see org.apache.log4j.db.ConnectionSource#getConnection()
+   */
+  public Connection getConnection() throws SQLException {
+    if (dataSource == null) {
+      getLogger().error("WARNING: No data source specified");
+      return null;
+    }
+
+    if (getUser() == null) {
+      return dataSource.getConnection();
+    } else {
+      return dataSource.getConnection(getUser(), getPassword());
+    }
+  }
+
+  public DataSource getDataSource() {
+    return dataSource;
+  }
+
+  public void setDataSource(DataSource dataSource) {
+    this.dataSource = dataSource;
+  }
+
+    /**
+     * @{inheritDoc}
+     */
+  public boolean parseUnrecognizedElement(Element element, Properties props) throws Exception {
+        if ("dataSource".equals(element.getNodeName())) {
+            Object instance =
+                    DOMConfigurator.parseElement(element, props, DataSource.class);
+            if (instance instanceof DataSource) {
+               setDataSource((DataSource) instance);
+            }
+            return true;
+        }
+        return false;
+  }
+
+}

Added: logging/chainsaw/trunk/src/main/java/org/apache/log4j/db/DriverManagerConnectionSource.java
URL: http://svn.apache.org/viewvc/logging/chainsaw/trunk/src/main/java/org/apache/log4j/db/DriverManagerConnectionSource.java?rev=1178304&view=auto
==============================================================================
--- logging/chainsaw/trunk/src/main/java/org/apache/log4j/db/DriverManagerConnectionSource.java (added)
+++ logging/chainsaw/trunk/src/main/java/org/apache/log4j/db/DriverManagerConnectionSource.java Mon Oct  3 06:15:40 2011
@@ -0,0 +1,133 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.log4j.db;
+
+import java.sql.Connection;
+import java.sql.DriverManager;
+import java.sql.SQLException;
+
+
+/**
+ *  The DriverManagerConnectionSource is an implementation of {@link ConnectionSource}
+ *  that obtains the Connection in the traditional JDBC manner based on the
+ *  connection URL.
+ *  <p>
+ *  Note that this class will establish a new Connection for each call to
+ *  {@link #getConnection()}.  It is recommended that you either use a JDBC
+ *  driver that natively supported Connection pooling or that you create
+ *  your own implementation of {@link ConnectionSource} that taps into whatever
+ *  pooling mechanism you are already using.  (If you have access to a JNDI
+ *  implementation that supports {@link javax.sql.DataSource}s, e.g. within
+ *  a J2EE application server, see {@link JNDIConnectionSource}).  See
+ *  <a href="#dbcp">below</a> for a configuration example that uses the
+ *  <a href="http://jakarta.apache.org/commons/dbcp/index.html">commons-dbcp</a>
+ *  package from Apache.
+ *  <p>
+ *  Sample configuration:<br>
+ *  <pre>
+ *     &lt;connectionSource class="org.apache.log4j.jdbc.DriverManagerConnectionSource"&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>
+ *  <p>
+ *  <a name="dbcp">If</a> you do not have another connection pooling mechanism
+ *  built into your application, you can use  the
+ *  <a href="http://jakarta.apache.org/commons/dbcp/index.html">commons-dbcp</a>
+ *  package from Apache:<br>
+ *  <pre>
+ *     &lt;connectionSource class="org.apache.log4j.jdbc.DriverManagerConnectionSource"&gt;
+ *        &lt;param name="driver" value="org.apache.commons.dbcp.PoolingDriver" /&gt;
+ *        &lt;param name="url" value="jdbc:apache:commons:dbcp:/myPoolingDriver" /&gt;
+ *     &lt;/connectionSource&gt;
+ *  </pre>
+ *  Then the configuration information for the commons-dbcp package goes into
+ *  the file myPoolingDriver.jocl and is placed in the classpath.  See the
+ *  <a href="http://jakarta.apache.org/commons/dbcp/index.html">commons-dbcp</a>
+ *  documentation for details.
+ *
+ *  @author <a href="mailto:rdecampo@twcny.rr.com">Ray DeCampo</a>
+ */
+public class DriverManagerConnectionSource extends ConnectionSourceSkeleton {
+  private String driverClass = null;
+  private String url = null;
+
+  public void activateOptions() {
+    try {
+      if (driverClass != null) {
+        Class.forName(driverClass);
+        discoverConnnectionProperties();
+      } else {
+        getLogger().error(
+          "WARNING: No JDBC driver specified for log4j DriverManagerConnectionSource.");
+      }
+    } catch (final ClassNotFoundException cnfe) {
+     getLogger().error("Could not load JDBC driver class: " + driverClass, cnfe);
+    }
+  }
+
+
+  /**
+   * @see org.apache.log4j.db.ConnectionSource#getConnection()
+   */
+  public Connection getConnection() throws SQLException {
+    if (getUser() == null) {
+      return DriverManager.getConnection(url);
+    } else {
+      return DriverManager.getConnection(url, getUser(), getPassword());
+    }
+  }
+
+
+  /**
+   * Returns the url.
+   * @return String
+   */
+  public String getUrl() {
+    return url;
+  }
+
+
+  /**
+   * Sets the url.
+   * @param url The url to set
+   */
+  public void setUrl(String url) {
+    this.url = url;
+  }
+
+
+  /**
+   * Returns the name of the driver class.
+   * @return String
+   */
+  public String getDriverClass() {
+    return driverClass;
+  }
+
+
+  /**
+   * Sets the driver class.
+   * @param driverClass The driver class to set
+   */
+  public void setDriverClass(String driverClass) {
+    this.driverClass = driverClass;
+  }
+}

Added: logging/chainsaw/trunk/src/main/java/org/apache/log4j/db/JNDIConnectionSource.java
URL: http://svn.apache.org/viewvc/logging/chainsaw/trunk/src/main/java/org/apache/log4j/db/JNDIConnectionSource.java?rev=1178304&view=auto
==============================================================================
--- logging/chainsaw/trunk/src/main/java/org/apache/log4j/db/JNDIConnectionSource.java (added)
+++ logging/chainsaw/trunk/src/main/java/org/apache/log4j/db/JNDIConnectionSource.java Mon Oct  3 06:15:40 2011
@@ -0,0 +1,143 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.log4j.db;
+
+import java.sql.Connection;
+import java.sql.SQLException;
+
+import javax.naming.Context;
+import javax.naming.InitialContext;
+import javax.naming.NamingException;
+
+// PortableRemoteObject was introduced in JDK 1.3. We won't use it.
+// import javax.rmi.PortableRemoteObject;
+import javax.sql.DataSource;
+
+
+/**
+ *  The <id>JNDIConnectionSource</id> is an implementation of
+ *  {@link ConnectionSource} that obtains a {@link javax.sql.DataSource} from a
+ *  JNDI provider and uses it to obtain a {@link 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 {@link 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 {@link 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:rdecampo@twcny.rr.com">Ray DeCampo</a>
+ */
+public class JNDIConnectionSource
+       extends ConnectionSourceSkeleton {
+  private String jndiLocation = null;
+  private DataSource dataSource = null;
+
+  /**
+   * @see org.apache.log4j.spi.OptionHandler#activateOptions()
+   */
+  public void activateOptions() {
+    if (jndiLocation == null) {
+      getLogger().error("No JNDI location specified for JNDIConnectionSource.");
+    }
+    
+    discoverConnnectionProperties();
+
+  }
+  
+  /**
+   * @see org.apache.log4j.db.ConnectionSource#getConnection()
+   */
+  public Connection getConnection()
+         throws SQLException {
+    Connection conn = null;
+    try {
+
+      if(dataSource == null) {
+        dataSource = lookupDataSource();
+      }
+      if (getUser() == null) {
+        conn = dataSource.getConnection();
+      } else {
+        conn = dataSource.getConnection(getUser(), getPassword());
+      }
+    } catch (final NamingException ne) {
+         getLogger().error("Error while getting data source", ne);
+      throw new SQLException("NamingException while looking up DataSource: " + ne.getMessage());
+    } catch (final ClassCastException cce) {
+      getLogger().error("ClassCastException while looking up DataSource.", cce);
+      throw new SQLException("ClassCastException while looking up DataSource: " + cce.getMessage());
+    }
+
+    return conn;
+  }
+
+  /**
+   * 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;
+  }
+
+
+  private DataSource lookupDataSource()
+         throws NamingException, SQLException {
+    DataSource ds;
+    Context ctx = new InitialContext();
+    Object obj = ctx.lookup(jndiLocation);
+
+    // PortableRemoteObject was introduced in JDK 1.3. We won't use it.
+    //ds = (DataSource)PortableRemoteObject.narrow(obj, DataSource.class);
+    ds = (DataSource) obj;
+
+    if (ds == null) {
+      throw new SQLException("Failed to obtain data source from JNDI location " + jndiLocation);
+    } else {
+      return ds;
+    }
+  }
+}

Added: logging/chainsaw/trunk/src/main/java/org/apache/log4j/db/dialect/HSQLDBDialect.java
URL: http://svn.apache.org/viewvc/logging/chainsaw/trunk/src/main/java/org/apache/log4j/db/dialect/HSQLDBDialect.java?rev=1178304&view=auto
==============================================================================
--- logging/chainsaw/trunk/src/main/java/org/apache/log4j/db/dialect/HSQLDBDialect.java (added)
+++ logging/chainsaw/trunk/src/main/java/org/apache/log4j/db/dialect/HSQLDBDialect.java Mon Oct  3 06:15:40 2011
@@ -0,0 +1,31 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.log4j.db.dialect; 
+
+/** 
+ * The HSQLDB dialect. 
+ * 
+ * @author <a href="http://www.qos.ch/log4j/">Ceki G&uuml;lc&uuml;</a>
+*/ 
+public class HSQLDBDialect implements SQLDialect { 
+ public static final String SELECT_CURRVAL = "CALL IDENTITY()"; 
+
+ public String getSelectInsertId() { 
+   return SELECT_CURRVAL; 
+ } 
+}

Added: logging/chainsaw/trunk/src/main/java/org/apache/log4j/db/dialect/MsSQLDialect.java
URL: http://svn.apache.org/viewvc/logging/chainsaw/trunk/src/main/java/org/apache/log4j/db/dialect/MsSQLDialect.java?rev=1178304&view=auto
==============================================================================
--- logging/chainsaw/trunk/src/main/java/org/apache/log4j/db/dialect/MsSQLDialect.java (added)
+++ logging/chainsaw/trunk/src/main/java/org/apache/log4j/db/dialect/MsSQLDialect.java Mon Oct  3 06:15:40 2011
@@ -0,0 +1,34 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.log4j.db.dialect; 
+
+/** 
+* The MS SQL Server dialect is untested. 
+* 
+* Note that the dialect is not needed if your JDBC driver supports 
+* the getGeneratedKeys method introduced in JDBC 3.0 specification.
+* 
+* @author James Stauffer 
+*/ 
+public class MsSQLDialect implements SQLDialect { 
+ public static final String SELECT_CURRVAL = "SELECT @@identity id"; 
+
+ public String getSelectInsertId() { 
+   return SELECT_CURRVAL; 
+ } 
+}



Mime
View raw message