logging-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From nickwilli...@apache.org
Subject svn commit: r1481932 [1/2] - in /logging/log4j/log4j2/trunk/core/src: main/java/org/apache/logging/log4j/core/appender/db/ main/java/org/apache/logging/log4j/core/appender/db/jdbc/ main/java/org/apache/logging/log4j/core/appender/db/jpa/ main/java/org/...
Date Mon, 13 May 2013 15:37:29 GMT
Author: nickwilliams
Date: Mon May 13 15:37:27 2013
New Revision: 1481932

URL: http://svn.apache.org/r1481932
Log:
No functional changes: Resolved complaints from CheckStyle, Rat Report, FindBugs, and PMD in the database appenders. Added JavaDoc where missing and/or necessary. Removed extra new lines at the ends of package-info.java files (there were two newlines, should have been one). Removed unnecessary JavaDoc line breaks.

Modified:
    logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/db/AbstractDatabaseAppender.java
    logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/db/AbstractDatabaseManager.java
    logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/db/jdbc/ColumnConfig.java
    logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/db/jdbc/ConnectionSource.java
    logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/db/jdbc/DataSourceConnectionSource.java
    logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/db/jdbc/DriverManagerConnectionSource.java
    logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/db/jdbc/FactoryMethodConnectionSource.java
    logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/db/jdbc/JDBCAppender.java
    logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/db/jdbc/JDBCDatabaseManager.java
    logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/db/jdbc/package-info.java
    logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/db/jpa/AbstractLogEventWrapperEntity.java
    logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/db/jpa/BasicLogEventEntity.java
    logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/db/jpa/JPAAppender.java
    logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/db/jpa/JPADatabaseManager.java
    logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/db/jpa/converter/ContextMapJsonAttributeConverter.java
    logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/db/jpa/converter/ContextStackJsonAttributeConverter.java
    logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/db/jpa/converter/StackTraceElementAttributeConverter.java
    logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/db/jpa/converter/ThrowableAttributeConverter.java
    logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/db/nosql/NoSQLAppender.java
    logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/db/nosql/NoSQLConnection.java
    logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/db/nosql/NoSQLDatabaseManager.java
    logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/db/nosql/NoSQLObject.java
    logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/db/nosql/NoSQLProvider.java
    logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/db/nosql/couch/CouchDBConnection.java
    logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/db/nosql/couch/CouchDBObject.java
    logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/db/nosql/couch/CouchDBProvider.java
    logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/db/nosql/couch/package-info.java
    logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/db/nosql/mongo/MongoDBConnection.java
    logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/db/nosql/mongo/MongoDBObject.java
    logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/db/nosql/mongo/MongoDBProvider.java
    logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/db/nosql/mongo/package-info.java
    logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/db/nosql/package-info.java
    logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/db/package-info.java
    logging/log4j/log4j2/trunk/core/src/test/java/org/apache/logging/log4j/core/appender/db/jpa/TestBasicEntity.java
    logging/log4j/log4j2/trunk/core/src/test/java/org/apache/logging/log4j/core/appender/db/jpa/converter/ContextMapAttributeConverterTest.java
    logging/log4j/log4j2/trunk/core/src/test/java/org/apache/logging/log4j/core/appender/db/jpa/converter/ContextMapJsonAttributeConverterTest.java
    logging/log4j/log4j2/trunk/core/src/test/java/org/apache/logging/log4j/core/appender/db/jpa/converter/ContextStackAttributeConverterTest.java
    logging/log4j/log4j2/trunk/core/src/test/java/org/apache/logging/log4j/core/appender/db/jpa/converter/ContextStackJsonAttributeConverterTest.java
    logging/log4j/log4j2/trunk/core/src/test/java/org/apache/logging/log4j/core/appender/db/jpa/converter/MarkerAttributeConverterTest.java
    logging/log4j/log4j2/trunk/core/src/test/java/org/apache/logging/log4j/core/appender/db/jpa/converter/MessageAttributeConverterTest.java
    logging/log4j/log4j2/trunk/core/src/test/java/org/apache/logging/log4j/core/appender/db/jpa/converter/StackTraceElementAttributeConverterTest.java
    logging/log4j/log4j2/trunk/core/src/test/java/org/apache/logging/log4j/core/appender/db/jpa/converter/ThrowableAttributeConverterTest.java

Modified: logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/db/AbstractDatabaseAppender.java
URL: http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/db/AbstractDatabaseAppender.java?rev=1481932&r1=1481931&r2=1481932&view=diff
==============================================================================
--- logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/db/AbstractDatabaseAppender.java (original)
+++ logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/db/AbstractDatabaseAppender.java Mon May 13 15:37:27 2013
@@ -16,64 +16,45 @@
  */
 package org.apache.logging.log4j.core.appender.db;
 
-import java.util.concurrent.locks.Lock;
-import java.util.concurrent.locks.ReadWriteLock;
-import java.util.concurrent.locks.ReentrantReadWriteLock;
-
 import org.apache.logging.log4j.core.Filter;
 import org.apache.logging.log4j.core.Layout;
 import org.apache.logging.log4j.core.LogEvent;
 import org.apache.logging.log4j.core.appender.AbstractAppender;
 import org.apache.logging.log4j.core.appender.AppenderRuntimeException;
 
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReadWriteLock;
+import java.util.concurrent.locks.ReentrantReadWriteLock;
+
 /**
  * An abstract Appender for writing events to a database of some type, be it relational or NoSQL. All database appenders
  * should inherit from this base appender. Three implementations are currently provided:
  * {@link org.apache.logging.log4j.core.appender.db.jdbc JDBC}, {@link org.apache.logging.log4j.core.appender.db.jpa
  * JPA}, and {@link org.apache.logging.log4j.core.appender.db.nosql NoSQL}.
  * 
- * @param <T>
- *            Specifies which type of {@link AbstractDatabaseManager} this Appender requires.
+ * @param <T> Specifies which type of {@link AbstractDatabaseManager} this Appender requires.
  */
 public abstract class AbstractDatabaseAppender<T extends AbstractDatabaseManager> extends AbstractAppender<LogEvent> {
     private final ReadWriteLock lock = new ReentrantReadWriteLock();
-    private T manager;
     private final Lock readLock = lock.readLock();
     private final Lock writeLock = lock.writeLock();
 
+    private T manager;
+
     /**
      * Instantiates the base appender.
      * 
-     * @param name
-     *            The appender name.
-     * @param filter
-     *            The filter, if any, to use.
-     * @param handleException
-     *            Whether logging exceptions should be reported to the application.
-     * @param manager
-     *            The matching {@link AbstractDatabaseManager} implementation.
+     * @param name The appender name.
+     * @param filter The filter, if any, to use.
+     * @param handleException Whether logging exceptions should be reported to the application.
+     * @param manager The matching {@link AbstractDatabaseManager} implementation.
      */
     protected AbstractDatabaseAppender(final String name, final Filter filter, final boolean handleException,
-            final T manager) {
+                                       final T manager) {
         super(name, filter, null, handleException);
         this.manager = manager;
     }
 
-    @Override
-    public final void append(final LogEvent event) {
-        this.readLock.lock();
-        try {
-            this.getManager().write(event);
-        } catch (final AppenderRuntimeException e) {
-            this.error(
-                    "Unable to write to database [" + this.getManager().getName() + "] for appender [" + this.getName()
-                            + "].", e);
-            throw e;
-        } finally {
-            this.readLock.unlock();
-        }
-    }
-
     /**
      * This always returns {@code null}, as database appenders do not use a single layout. The JPA and NoSQL appenders
      * do not use a layout at all. The JDBC appender has a layout-per-column pattern.
@@ -94,28 +75,6 @@ public abstract class AbstractDatabaseAp
         return this.manager;
     }
 
-    /**
-     * Replaces the underlying manager in use within this appender. This can be useful for manually changing the way log
-     * events are written to the database without losing buffered or in-progress events. The existing manager is
-     * released only after the new manager has been installed. This method is thread-safe.
-     * 
-     * @param manager
-     *            The new manager to install.
-     */
-    protected final void replaceManager(final T manager) {
-        this.writeLock.lock();
-        try {
-            final T old = this.getManager();
-            if (!manager.isConnected()) {
-                manager.connect();
-            }
-            this.manager = manager;
-            old.release();
-        } finally {
-            this.writeLock.unlock();
-        }
-    }
-
     @Override
     public final void start() {
         if (this.getManager() == null) {
@@ -134,4 +93,39 @@ public abstract class AbstractDatabaseAp
             this.getManager().release();
         }
     }
+
+    @Override
+    public final void append(final LogEvent event) {
+        this.readLock.lock();
+        try {
+            this.getManager().write(event);
+        } catch (final AppenderRuntimeException e) {
+            this.error("Unable to write to database [" + this.getManager().getName() + "] for appender [" +
+                    this.getName() + "].", e);
+            throw e;
+        } finally {
+            this.readLock.unlock();
+        }
+    }
+
+    /**
+     * Replaces the underlying manager in use within this appender. This can be useful for manually changing the way log
+     * events are written to the database without losing buffered or in-progress events. The existing manager is
+     * released only after the new manager has been installed. This method is thread-safe.
+     *
+     * @param manager The new manager to install.
+     */
+    protected final void replaceManager(final T manager) {
+        this.writeLock.lock();
+        try {
+            final T old = this.getManager();
+            if (!manager.isConnected()) {
+                manager.connect();
+            }
+            this.manager = manager;
+            old.release();
+        } finally {
+            this.writeLock.unlock();
+        }
+    }
 }

Modified: logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/db/AbstractDatabaseManager.java
URL: http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/db/AbstractDatabaseManager.java?rev=1481932&r1=1481931&r2=1481932&view=diff
==============================================================================
--- logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/db/AbstractDatabaseManager.java (original)
+++ logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/db/AbstractDatabaseManager.java Mon May 13 15:37:27 2013
@@ -16,58 +16,17 @@
  */
 package org.apache.logging.log4j.core.appender.db;
 
-import java.util.ArrayList;
-
 import org.apache.logging.log4j.core.LogEvent;
 import org.apache.logging.log4j.core.appender.AbstractManager;
 import org.apache.logging.log4j.core.appender.ManagerFactory;
 
+import java.util.ArrayList;
+
 /**
  * Manager that allows database appenders to have their configuration reloaded without losing events.
  */
 public abstract class AbstractDatabaseManager extends AbstractManager {
-    /**
-     * Implementations should extend this class for passing data between the getManager method and the manager factory
-     * class.
-     */
-    protected abstract static class AbstractFactoryData {
-        public final int bufferSize;
-
-        /**
-         * Constructs the base factory data.
-         * 
-         * @param bufferSize
-         *            The size of the buffer.
-         */
-        protected AbstractFactoryData(final int bufferSize) {
-            this.bufferSize = bufferSize;
-        }
-    }
-
-    /**
-     * Implementations should define their own getManager method and call this method from that to create or get
-     * existing managers.
-     * 
-     * @param name
-     *            The manager name, which should include any configuration details that one might want to be able to
-     *            reconfigure at runtime, such as database name, username, (hashed) password, etc.
-     * @param data
-     *            The concrete instance of {@link AbstractFactoryData} appropriate for the given manager.
-     * @param factory
-     *            A factory instance for creating the appropriate manager.
-     * @param <M>
-     *            The concrete manager type.
-     * @param <T>
-     *            The concrete {@link AbstractFactoryData} type.
-     * @return a new or existing manager of the specified type and name.
-     */
-    protected static <M extends AbstractDatabaseManager, T extends AbstractFactoryData> M getManager(final String name,
-            final T data, final ManagerFactory<M, T> factory) {
-        return AbstractManager.getManager(name, factory, data);
-    }
-
     private final ArrayList<LogEvent> buffer;
-
     private final int bufferSize;
 
     private boolean connected = false;
@@ -75,11 +34,9 @@ public abstract class AbstractDatabaseMa
     /**
      * Instantiates the base manager.
      * 
-     * @param name
-     *            The manager name, which should include any configuration details that one might want to be able to
-     *            reconfigure at runtime, such as database name, username, (hashed) password, etc.
-     * @param bufferSize
-     *            The size of the log event buffer.
+     * @param name The manager name, which should include any configuration details that one might want to be able to
+     *             reconfigure at runtime, such as database name, username, (hashed) password, etc.
+     * @param bufferSize The size of the log event buffer.
      */
     protected AbstractDatabaseManager(final String name, final int bufferSize) {
         super(name);
@@ -88,6 +45,12 @@ public abstract class AbstractDatabaseMa
     }
 
     /**
+     * Implementations should implement this method to perform any proprietary connection operations. This method will
+     * never be called twice on the same instance. It is safe to throw any exceptions from this method.
+     */
+    protected abstract void connectInternal();
+
+    /**
      * This method is called within the appender when the appender is started. If it has not already been called, it
      * calls {@link #connectInternal()} and catches any exceptions it might throw.
      */
@@ -103,10 +66,11 @@ public abstract class AbstractDatabaseMa
     }
 
     /**
-     * Implementations should implement this method to perform any proprietary connection operations. This method will
-     * never be called twice on the same instance. It is safe to throw any exceptions from this method.
+     * Implementations should implement this method to perform any proprietary disconnection / shutdown operations. This
+     * method will never be called twice on the same instance, and it will only be called <em>after</em>
+     * {@link #connectInternal()}. It is safe to throw any exceptions from this method.
      */
-    protected abstract void connectInternal();
+    protected abstract void disconnectInternal();
 
     /**
      * This method is called from the {@link #release()} method when the appender is stopped or the appender's manager
@@ -127,11 +91,22 @@ public abstract class AbstractDatabaseMa
     }
 
     /**
-     * Implementations should implement this method to perform any proprietary disconnection / shutdown operations. This
-     * method will never be called twice on the same instance, and it will only be called <em>after</em>
-     * {@link #connectInternal()}. It is safe to throw any exceptions from this method.
+     * Indicates whether the manager is currently connected {@link #connect()} has been called and {@link #disconnect()}
+     * has not been called).
+     *
+     * @return {@code true} if the manager is connected.
      */
-    protected abstract void disconnectInternal();
+    public final boolean isConnected() {
+        return this.connected;
+    }
+
+    /**
+     * Performs the actual writing of the event in an implementation-specific way. This method is called immediately
+     * from {@link #write(LogEvent)} if buffering is off, or from {@link #flush()} if the buffer has reached its limit.
+     *
+     * @param event The event to write to the database.
+     */
+    protected abstract void writeInternal(LogEvent event);
 
     /**
      * This method is called automatically when the buffer size reaches its maximum or at the beginning of a call to
@@ -147,13 +122,19 @@ public abstract class AbstractDatabaseMa
     }
 
     /**
-     * Indicates whether the manager is currently connected {@link #connect()} has been called and {@link #disconnect()}
-     * has not been called).
-     * 
-     * @return {@code true} if the manager is connected.
+     * This method manages buffering and writing of events.
+     *
+     * @param event The event to write to the database.
      */
-    public final boolean isConnected() {
-        return this.connected;
+    public final synchronized void write(final LogEvent event) {
+        if (this.bufferSize > 0) {
+            this.buffer.add(event);
+            if (this.buffer.size() >= this.bufferSize || event.isEndOfBatch()) {
+                this.flush();
+            }
+        } else {
+            this.writeInternal(event);
+        }
     }
 
     @Override
@@ -167,28 +148,46 @@ public abstract class AbstractDatabaseMa
     }
 
     /**
-     * This method manages buffering and writing of events.
-     * 
-     * @param event
-     *            The event to write to the database.
+     * Implementations should define their own getManager method and call this method from that to create or get
+     * existing managers.
+     *
+     * @param name The manager name, which should include any configuration details that one might want to be able to
+     *             reconfigure at runtime, such as database name, username, (hashed) password, etc.
+     * @param data The concrete instance of {@link AbstractFactoryData} appropriate for the given manager.
+     * @param factory A factory instance for creating the appropriate manager.
+     * @param <M> The concrete manager type.
+     * @param <T> The concrete {@link AbstractFactoryData} type.
+     * @return a new or existing manager of the specified type and name.
      */
-    public final synchronized void write(final LogEvent event) {
-        if (this.bufferSize > 0) {
-            this.buffer.add(event);
-            if (this.buffer.size() >= this.bufferSize || event.isEndOfBatch()) {
-                this.flush();
-            }
-        } else {
-            this.writeInternal(event);
-        }
+    protected static <M extends AbstractDatabaseManager, T extends AbstractFactoryData> M getManager(
+            final String name, final T data, final ManagerFactory<M, T> factory
+    ) {
+        return AbstractManager.getManager(name, factory, data);
     }
 
     /**
-     * Performs the actual writing of the event in an implementation-specific way. This method is called immediately
-     * from {@link #write(LogEvent)} if buffering is off, or from {@link #flush()} if the buffer has reached its limit.
-     * 
-     * @param event
-     *            The event to write to the database.
+     * Implementations should extend this class for passing data between the getManager method and the manager factory
+     * class.
      */
-    protected abstract void writeInternal(LogEvent event);
+    protected abstract static class AbstractFactoryData {
+        private final int bufferSize;
+
+        /**
+         * Constructs the base factory data.
+         *
+         * @param bufferSize The size of the buffer.
+         */
+        protected AbstractFactoryData(final int bufferSize) {
+            this.bufferSize = bufferSize;
+        }
+
+        /**
+         * Gets the buffer size.
+         *
+         * @return the buffer size.
+         */
+        public int getBufferSize() {
+            return bufferSize;
+        }
+    }
 }

Modified: logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/db/jdbc/ColumnConfig.java
URL: http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/db/jdbc/ColumnConfig.java?rev=1481932&r1=1481931&r2=1481932&view=diff
==============================================================================
--- logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/db/jdbc/ColumnConfig.java (original)
+++ logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/db/jdbc/ColumnConfig.java Mon May 13 15:37:27 2013
@@ -32,64 +32,13 @@ import org.apache.logging.log4j.status.S
 public final class ColumnConfig {
     private static final Logger LOGGER = StatusLogger.getLogger();
 
-    /**
-     * Factory method for creating a column config within the plugin manager.
-     * 
-     * @param config
-     *            The configuration object
-     * @param name
-     *            The name of the database column as it exists within the database table.
-     * @param pattern
-     *            The {@link PatternLayout} pattern to insert in this column. Mutually exclusive with
-     *            {@code literalValue!=null} and {@code eventTimestamp=true}
-     * @param literalValue
-     *            The literal value to insert into the column as-is without any quoting or escaping. Mutually exclusive
-     *            with {@code pattern!=null} and {@code eventTimestamp=true}.
-     * @param eventTimestamp
-     *            If {@code "true"}, indicates that this column is a date-time column in which the event timestamp
-     *            should be inserted. Mutually exclusive with {@code pattern!=null} and {@code literalValue!=null}.
-     * @return the created column config.
-     */
-    @PluginFactory
-    public static ColumnConfig createColumnConfig(@PluginConfiguration final Configuration config,
-            @PluginAttr("name") final String name, @PluginAttr("pattern") final String pattern,
-            @PluginAttr("literal") final String literalValue,
-            @PluginAttr("isEventTimestamp") final String eventTimestamp) {
-        if (name == null || name.length() == 0) {
-            LOGGER.error("The column config is not valid because it does not contain a column name.");
-            return null;
-        }
-
-        final boolean isEventTimestamp = eventTimestamp != null && Boolean.parseBoolean(eventTimestamp);
-        final boolean isLiteralValue = literalValue != null && literalValue.length() > 0;
-        final boolean isPattern = pattern != null && pattern.length() > 0;
-
-        if ((isEventTimestamp && isLiteralValue) || (isEventTimestamp && isPattern) || (isLiteralValue && isPattern)) {
-            LOGGER.error("The pattern, literal, and isEventTimestamp attributes are mutually exclusive.");
-            return null;
-        }
-
-        if (isEventTimestamp) {
-            return new ColumnConfig(name, null, null, true);
-        }
-        if (isLiteralValue) {
-            return new ColumnConfig(name, null, literalValue, false);
-        }
-        if (isPattern) {
-            return new ColumnConfig(name, PatternLayout.createLayout(pattern, config, null, null, "true"), null, false);
-        }
-
-        LOGGER.error("To configure a column you must specify a pattern or literal or set isEventDate to true.");
-        return null;
-    }
-
     private final String columnName;
     private final boolean eventTimestamp;
     private final PatternLayout layout;
     private final String literalValue;
 
     private ColumnConfig(final String columnName, final PatternLayout layout, final String literalValue,
-            final boolean eventDate) {
+                         final boolean eventDate) {
         this.columnName = columnName;
         this.layout = layout;
         this.literalValue = literalValue;
@@ -117,4 +66,52 @@ public final class ColumnConfig {
         return "{ name=" + this.columnName + ", layout=" + this.layout + ", literal=" + this.literalValue
                 + ", timestamp=" + this.eventTimestamp + " }";
     }
+
+    /**
+     * Factory method for creating a column config within the plugin manager.
+     *
+     * @param config The configuration object
+     * @param name The name of the database column as it exists within the database table.
+     * @param pattern The {@link PatternLayout} pattern to insert in this column. Mutually exclusive with
+     *                {@code literalValue!=null} and {@code eventTimestamp=true}
+     * @param literalValue The literal value to insert into the column as-is without any quoting or escaping. Mutually
+     *                     exclusive with {@code pattern!=null} and {@code eventTimestamp=true}.
+     * @param eventTimestamp If {@code "true"}, indicates that this column is a date-time column in which the event
+     *                       timestamp should be inserted. Mutually exclusive with {@code pattern!=null} and
+     *                       {@code literalValue!=null}.
+     * @return the created column config.
+     */
+    @PluginFactory
+    public static ColumnConfig createColumnConfig(@PluginConfiguration final Configuration config,
+                                                  @PluginAttr("name") final String name,
+                                                  @PluginAttr("pattern") final String pattern,
+                                                  @PluginAttr("literal") final String literalValue,
+                                                  @PluginAttr("isEventTimestamp") final String eventTimestamp) {
+        if (name == null || name.length() == 0) {
+            LOGGER.error("The column config is not valid because it does not contain a column name.");
+            return null;
+        }
+
+        final boolean isEventTimestamp = eventTimestamp != null && Boolean.parseBoolean(eventTimestamp);
+        final boolean isLiteralValue = literalValue != null && literalValue.length() > 0;
+        final boolean isPattern = pattern != null && pattern.length() > 0;
+
+        if (isEventTimestamp && isLiteralValue || isEventTimestamp && isPattern || isLiteralValue && isPattern) {
+            LOGGER.error("The pattern, literal, and isEventTimestamp attributes are mutually exclusive.");
+            return null;
+        }
+
+        if (isEventTimestamp) {
+            return new ColumnConfig(name, null, null, true);
+        }
+        if (isLiteralValue) {
+            return new ColumnConfig(name, null, literalValue, false);
+        }
+        if (isPattern) {
+            return new ColumnConfig(name, PatternLayout.createLayout(pattern, config, null, null, "true"), null, false);
+        }
+
+        LOGGER.error("To configure a column you must specify a pattern or literal or set isEventDate to true.");
+        return null;
+    }
 }

Modified: logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/db/jdbc/ConnectionSource.java
URL: http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/db/jdbc/ConnectionSource.java?rev=1481932&r1=1481931&r2=1481932&view=diff
==============================================================================
--- logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/db/jdbc/ConnectionSource.java (original)
+++ logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/db/jdbc/ConnectionSource.java Mon May 13 15:37:27 2013
@@ -28,11 +28,16 @@ public interface ConnectionSource {
      * This should return a new connection every time it is called.
      * 
      * @return the SQL connection object.
-     * @throws SQLException
-     *             if a database error occurs.
+     * @throws SQLException if a database error occurs.
      */
     Connection getConnection() throws SQLException;
 
+    /**
+     * All implementations must override {@link Object#toString()} to provide information about the connection
+     * configuration (obscuring passwords with one-way hashes).
+     *
+     * @return the string representation of this connection source.
+     */
     @Override
     String toString();
 }

Modified: logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/db/jdbc/DataSourceConnectionSource.java
URL: http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/db/jdbc/DataSourceConnectionSource.java?rev=1481932&r1=1481931&r2=1481932&view=diff
==============================================================================
--- logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/db/jdbc/DataSourceConnectionSource.java (original)
+++ logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/db/jdbc/DataSourceConnectionSource.java Mon May 13 15:37:27 2013
@@ -16,19 +16,18 @@
  */
 package org.apache.logging.log4j.core.appender.db.jdbc;
 
-import java.sql.Connection;
-import java.sql.SQLException;
-
-import javax.naming.InitialContext;
-import javax.naming.NamingException;
-import javax.sql.DataSource;
-
 import org.apache.logging.log4j.Logger;
 import org.apache.logging.log4j.core.config.plugins.Plugin;
 import org.apache.logging.log4j.core.config.plugins.PluginAttr;
 import org.apache.logging.log4j.core.config.plugins.PluginFactory;
 import org.apache.logging.log4j.status.StatusLogger;
 
+import javax.naming.InitialContext;
+import javax.naming.NamingException;
+import javax.sql.DataSource;
+import java.sql.Connection;
+import java.sql.SQLException;
+
 /**
  * A {@link JDBCAppender} connection source that uses a {@link DataSource} to connect to the database.
  */
@@ -36,12 +35,29 @@ import org.apache.logging.log4j.status.S
 public final class DataSourceConnectionSource implements ConnectionSource {
     private static final Logger LOGGER = StatusLogger.getLogger();
 
+    private final DataSource dataSource;
+    private final String description;
+
+    private DataSourceConnectionSource(final String dataSourceName, final DataSource dataSource) {
+        this.dataSource = dataSource;
+        this.description = "dataSource{ name=" + dataSourceName + ", value=" + dataSource + " }";
+    }
+
+    @Override
+    public Connection getConnection() throws SQLException {
+        return this.dataSource.getConnection();
+    }
+
+    @Override
+    public String toString() {
+        return this.description;
+    }
+
     /**
      * Factory method for creating a connection source within the plugin manager.
-     * 
-     * @param jndiName
-     *            The full JNDI path where the data source is bound. Should start with java:/comp/env or
-     *            environment-equivalent.
+     *
+     * @param jndiName The full JNDI path where the data source is bound. Should start with java:/comp/env or
+     *                 environment-equivalent.
      * @return the created connection source.
      */
     @PluginFactory
@@ -65,23 +81,4 @@ public final class DataSourceConnectionS
             return null;
         }
     }
-
-    private final DataSource dataSource;
-
-    private final String description;
-
-    private DataSourceConnectionSource(final String dataSourceName, final DataSource dataSource) {
-        this.dataSource = dataSource;
-        this.description = "dataSource{ name=" + dataSourceName + ", value=" + dataSource + " }";
-    }
-
-    @Override
-    public Connection getConnection() throws SQLException {
-        return this.dataSource.getConnection();
-    }
-
-    @Override
-    public String toString() {
-        return this.description;
-    }
 }

Modified: logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/db/jdbc/DriverManagerConnectionSource.java
URL: http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/db/jdbc/DriverManagerConnectionSource.java?rev=1481932&r1=1481931&r2=1481932&view=diff
==============================================================================
--- logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/db/jdbc/DriverManagerConnectionSource.java (original)
+++ logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/db/jdbc/DriverManagerConnectionSource.java Mon May 13 15:37:27 2013
@@ -16,11 +16,6 @@
  */
 package org.apache.logging.log4j.core.appender.db.jdbc;
 
-import java.sql.Connection;
-import java.sql.Driver;
-import java.sql.DriverManager;
-import java.sql.SQLException;
-
 import org.apache.logging.log4j.Logger;
 import org.apache.logging.log4j.core.config.plugins.Plugin;
 import org.apache.logging.log4j.core.config.plugins.PluginAttr;
@@ -28,6 +23,11 @@ import org.apache.logging.log4j.core.con
 import org.apache.logging.log4j.core.helpers.NameUtil;
 import org.apache.logging.log4j.status.StatusLogger;
 
+import java.sql.Connection;
+import java.sql.Driver;
+import java.sql.DriverManager;
+import java.sql.SQLException;
+
 /**
  * A {@link JDBCAppender} connection source that uses a standard JDBC URL, username, and password to connect to the
  * database.
@@ -36,21 +36,46 @@ import org.apache.logging.log4j.status.S
 public final class DriverManagerConnectionSource implements ConnectionSource {
     private static final Logger LOGGER = StatusLogger.getLogger();
 
+    private final String databasePassword;
+    private final String databaseUrl;
+    private final String databaseUsername;
+    private final String description;
+
+    private DriverManagerConnectionSource(final String databaseUrl, final String databaseUsername,
+                                          final String databasePassword) {
+        this.databaseUrl = databaseUrl;
+        this.databaseUsername = databaseUsername;
+        this.databasePassword = databasePassword;
+        this.description = "driverManager{ url=" + this.databaseUrl + ", username=" + this.databaseUsername
+                + ", passwordHash=" + NameUtil.md5(this.databasePassword + this.getClass().getName()) + " }";
+    }
+
+    @Override
+    public Connection getConnection() throws SQLException {
+        if (this.databaseUsername == null) {
+            return DriverManager.getConnection(this.databaseUrl);
+        }
+        return DriverManager.getConnection(this.databaseUrl, this.databaseUsername, this.databasePassword);
+    }
+
+    @Override
+    public String toString() {
+        return this.description;
+    }
+
     /**
      * Factory method for creating a connection source within the plugin manager.
-     * 
-     * @param url
-     *            The JDBC URL to use to connect to the logging database. A driver that can accept this URL must be on
+     *
+     * @param url The JDBC URL to use to connect to the logging database. A driver that can accept this URL must be on
      *            the classpath.
-     * @param username
-     *            The username with which to log in to the database, if applicable.
-     * @param password
-     *            The password with which to log in to the database, if applicable.
+     * @param username The username with which to log in to the database, if applicable.
+     * @param password The password with which to log in to the database, if applicable.
      * @return the created connection source.
      */
     @PluginFactory
     public static DriverManagerConnectionSource createConnectionSource(@PluginAttr("url") final String url,
-            @PluginAttr("username") String username, @PluginAttr("password") String password) {
+                                                                       @PluginAttr("username") String username,
+                                                                       @PluginAttr("password") String password) {
         if (url == null || url.length() == 0) {
             LOGGER.error("No JDBC URL specified for the database.", url);
             return null;
@@ -76,32 +101,4 @@ public final class DriverManagerConnecti
 
         return new DriverManagerConnectionSource(url, username, password);
     }
-
-    private final String databasePassword;
-    private final String databaseUrl;
-    private final String databaseUsername;
-
-    private final String description;
-
-    private DriverManagerConnectionSource(final String databaseUrl, final String databaseUsername,
-            final String databasePassword) {
-        this.databaseUrl = databaseUrl;
-        this.databaseUsername = databaseUsername;
-        this.databasePassword = databasePassword;
-        this.description = "driverManager{ url=" + this.databaseUrl + ", username=" + this.databaseUsername
-                + ", passwordHash=" + NameUtil.md5(this.databasePassword + this.getClass().getName()) + " }";
-    }
-
-    @Override
-    public Connection getConnection() throws SQLException {
-        if (this.databaseUsername == null) {
-            return DriverManager.getConnection(this.databaseUrl);
-        }
-        return DriverManager.getConnection(this.databaseUrl, this.databaseUsername, this.databasePassword);
-    }
-
-    @Override
-    public String toString() {
-        return this.description;
-    }
 }

Modified: logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/db/jdbc/FactoryMethodConnectionSource.java
URL: http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/db/jdbc/FactoryMethodConnectionSource.java?rev=1481932&r1=1481931&r2=1481932&view=diff
==============================================================================
--- logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/db/jdbc/FactoryMethodConnectionSource.java (original)
+++ logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/db/jdbc/FactoryMethodConnectionSource.java Mon May 13 15:37:27 2013
@@ -16,19 +16,18 @@
  */
 package org.apache.logging.log4j.core.appender.db.jdbc;
 
-import java.io.PrintWriter;
-import java.lang.reflect.Method;
-import java.sql.Connection;
-import java.sql.SQLException;
-
-import javax.sql.DataSource;
-
 import org.apache.logging.log4j.Logger;
 import org.apache.logging.log4j.core.config.plugins.Plugin;
 import org.apache.logging.log4j.core.config.plugins.PluginAttr;
 import org.apache.logging.log4j.core.config.plugins.PluginFactory;
 import org.apache.logging.log4j.status.StatusLogger;
 
+import javax.sql.DataSource;
+import java.io.PrintWriter;
+import java.lang.reflect.Method;
+import java.sql.Connection;
+import java.sql.SQLException;
+
 /**
  * A {@link JDBCAppender} connection source that uses a public static factory method to obtain a {@link Connection} or
  * {@link DataSource}.
@@ -37,20 +36,38 @@ import org.apache.logging.log4j.status.S
 public final class FactoryMethodConnectionSource implements ConnectionSource {
     private static final Logger LOGGER = StatusLogger.getLogger();
 
+    private final DataSource dataSource;
+    private final String description;
+
+    private FactoryMethodConnectionSource(final DataSource dataSource, final String className, final String methodName,
+                                          final String returnType) {
+        this.dataSource = dataSource;
+        this.description = "factory{ public static " + returnType + " " + className + "." + methodName + "() }";
+    }
+
+    @Override
+    public Connection getConnection() throws SQLException {
+        return this.dataSource.getConnection();
+    }
+
+    @Override
+    public String toString() {
+        return this.description;
+    }
+
     /**
      * Factory method for creating a connection source within the plugin manager.
-     * 
-     * @param className
-     *            The name of a public class that contains a static method capable of returning either a
-     *            {@link DataSource} or a {@link Connection}.
-     * @param methodName
-     *            The name of the public static method on the aforementioned class that returns the data source or
-     *            connection. If this method returns a {@link Connection}, it should return a new connection every call.
+     *
+     * @param className The name of a public class that contains a static method capable of returning either a
+     *                  {@link DataSource} or a {@link Connection}.
+     * @param methodName The name of the public static method on the aforementioned class that returns the data source
+     *                   or connection. If this method returns a {@link Connection}, it should return a new connection
+     *                   every call.
      * @return the created connection source.
      */
     @PluginFactory
     public static FactoryMethodConnectionSource createConnectionSource(@PluginAttr("class") final String className,
-            @PluginAttr("method") final String methodName) {
+                                                                       @PluginAttr("method") final String methodName) {
         if (className == null || className.length() == 0 || methodName == null || methodName.length() == 0) {
             LOGGER.error("No class name or method name specified for the connection factory method.");
             return null;
@@ -129,30 +146,11 @@ public final class FactoryMethodConnecti
                 }
             };
         } else {
-            LOGGER.error("Method [{}.{}()] returns unsupported type [{}].", className, methodName, returnType.getName());
+            LOGGER.error("Method [{}.{}()] returns unsupported type [{}].", className, methodName,
+                    returnType.getName());
             return null;
         }
 
         return new FactoryMethodConnectionSource(dataSource, className, methodName, returnTypeString);
     }
-
-    private final DataSource dataSource;
-
-    private final String description;
-
-    private FactoryMethodConnectionSource(final DataSource dataSource, final String className, final String methodName,
-            final String returnType) {
-        this.dataSource = dataSource;
-        this.description = "factory{ public static " + returnType + " " + className + "." + methodName + "() }";
-    }
-
-    @Override
-    public Connection getConnection() throws SQLException {
-        return this.dataSource.getConnection();
-    }
-
-    @Override
-    public String toString() {
-        return this.description;
-    }
 }

Modified: logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/db/jdbc/JDBCAppender.java
URL: http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/db/jdbc/JDBCAppender.java?rev=1481932&r1=1481931&r2=1481932&view=diff
==============================================================================
--- logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/db/jdbc/JDBCAppender.java (original)
+++ logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/db/jdbc/JDBCAppender.java Mon May 13 15:37:27 2013
@@ -34,33 +34,43 @@ import org.apache.logging.log4j.core.con
  */
 @Plugin(name = "Jdbc", category = "Core", elementType = "appender", printObject = true)
 public final class JDBCAppender extends AbstractDatabaseAppender<JDBCDatabaseManager> {
+    private final String description;
+
+    private JDBCAppender(final String name, final Filter filter, final boolean handleException,
+                         final JDBCDatabaseManager manager) {
+        super(name, filter, handleException, manager);
+        this.description = this.getName() + "{ manager=" + this.getManager() + " }";
+    }
+
+    @Override
+    public String toString() {
+        return this.description;
+    }
+
     /**
      * Factory method for creating a JDBC appender within the plugin manager.
-     * 
-     * @param name
-     *            The name of the appender.
-     * @param suppressExceptions
-     *            {@code "true"} (default) if logging exceptions should be hidden from the application, false otherwise.
-     * @param filter
-     *            The filter, if any, to use.
-     * @param connectionSource
-     *            The connections source from which database connections should be retrieved.
-     * @param bufferSize
-     *            If an integer greater than 0, this causes the appender to buffer log events and flush whenever the
-     *            buffer reaches this size.
-     * @param tableName
-     *            The name of the database table to insert log events into.
-     * @param columnConfigs
-     *            Information about the columns that log event data should be inserted into and how to insert that data.
+     *
+     * @param name The name of the appender.
+     * @param suppressExceptions {@code "true"} (default) if logging exceptions should be hidden from the application,
+     *                           {@code "false"} otherwise.
+     * @param filter The filter, if any, to use.
+     * @param connectionSource The connections source from which database connections should be retrieved.
+     * @param bufferSize If an integer greater than 0, this causes the appender to buffer log events and flush whenever
+     *                   the buffer reaches this size.
+     * @param tableName The name of the database table to insert log events into.
+     * @param columnConfigs Information about the columns that log event data should be inserted into and how to insert
+     *                      that data.
      * @return a new JDBC appender.
      */
     @PluginFactory
     public static JDBCAppender createAppender(@PluginAttr("name") final String name,
-            @PluginAttr("suppressExceptions") final String suppressExceptions,
-            @PluginElement("filter") final Filter filter,
-            @PluginElement("connectionSource") final ConnectionSource connectionSource,
-            @PluginAttr("bufferSize") final String bufferSize, @PluginAttr("tableName") final String tableName,
-            @PluginElement("columnConfigs") final ColumnConfig[] columnConfigs) {
+                                              @PluginAttr("suppressExceptions") final String suppressExceptions,
+                                              @PluginElement("filter") final Filter filter,
+                                              @PluginElement("connectionSource") final ConnectionSource
+                                                      connectionSource,
+                                              @PluginAttr("bufferSize") final String bufferSize,
+                                              @PluginAttr("tableName") final String tableName,
+                                              @PluginElement("columnConfigs") final ColumnConfig[] columnConfigs) {
         int bufferSizeInt;
         try {
             bufferSizeInt = bufferSize == null || bufferSize.length() == 0 ? 0 : Integer.parseInt(bufferSize);
@@ -85,25 +95,13 @@ public final class JDBCAppender extends 
 
         managerName.append(" ] }");
 
-        final JDBCDatabaseManager manager = JDBCDatabaseManager.getJDBCDatabaseManager(managerName.toString(),
-                bufferSizeInt, connectionSource, tableName, columnConfigs);
+        final JDBCDatabaseManager manager = JDBCDatabaseManager.getJDBCDatabaseManager(
+                managerName.toString(), bufferSizeInt, connectionSource, tableName, columnConfigs
+        );
         if (manager == null) {
             return null;
         }
 
         return new JDBCAppender(name, filter, handleExceptions, manager);
     }
-
-    private final String description;
-
-    private JDBCAppender(final String name, final Filter filter, final boolean handleException,
-            final JDBCDatabaseManager manager) {
-        super(name, filter, handleException, manager);
-        this.description = this.getName() + "{ manager=" + this.getManager() + " }";
-    }
-
-    @Override
-    public String toString() {
-        return this.description;
-    }
 }

Modified: logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/db/jdbc/JDBCDatabaseManager.java
URL: http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/db/jdbc/JDBCDatabaseManager.java?rev=1481932&r1=1481931&r2=1481932&view=diff
==============================================================================
--- logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/db/jdbc/JDBCDatabaseManager.java (original)
+++ logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/db/jdbc/JDBCDatabaseManager.java Mon May 13 15:37:27 2013
@@ -16,6 +16,11 @@
  */
 package org.apache.logging.log4j.core.appender.db.jdbc;
 
+import org.apache.logging.log4j.core.LogEvent;
+import org.apache.logging.log4j.core.appender.ManagerFactory;
+import org.apache.logging.log4j.core.appender.db.AbstractDatabaseManager;
+import org.apache.logging.log4j.core.layout.PatternLayout;
+
 import java.sql.Connection;
 import java.sql.PreparedStatement;
 import java.sql.SQLException;
@@ -23,105 +28,21 @@ import java.sql.Timestamp;
 import java.util.ArrayList;
 import java.util.List;
 
-import org.apache.logging.log4j.core.LogEvent;
-import org.apache.logging.log4j.core.appender.ManagerFactory;
-import org.apache.logging.log4j.core.appender.db.AbstractDatabaseManager;
-import org.apache.logging.log4j.core.layout.PatternLayout;
-
 /**
  * An {@link AbstractDatabaseManager} implementation for relational databases accessed via JDBC.
  */
 public final class JDBCDatabaseManager extends AbstractDatabaseManager {
-    private static final class Column {
-        private final boolean isEventTimestamp;
-        private final PatternLayout layout;
-
-        private Column(final PatternLayout layout, final boolean isEventDate) {
-            this.layout = layout;
-            this.isEventTimestamp = isEventDate;
-        }
-    }
-
-    private static final class FactoryData extends AbstractDatabaseManager.AbstractFactoryData {
-        private final ColumnConfig[] columnConfigs;
-        private final ConnectionSource connectionSource;
-        private final String tableName;
-
-        protected FactoryData(final int bufferSize, final ConnectionSource connectionSource, final String tableName,
-                final ColumnConfig[] columnConfigs) {
-            super(bufferSize);
-            this.connectionSource = connectionSource;
-            this.tableName = tableName;
-            this.columnConfigs = columnConfigs;
-        }
-    }
-
-    private static final class JDBCDatabaseManagerFactory implements ManagerFactory<JDBCDatabaseManager, FactoryData> {
-        @Override
-        public JDBCDatabaseManager createManager(final String name, final FactoryData data) {
-            final StringBuilder columnPart = new StringBuilder();
-            final StringBuilder valuePart = new StringBuilder();
-            final List<Column> columns = new ArrayList<Column>();
-            int i = 0;
-            for (final ColumnConfig config : data.columnConfigs) {
-                if (i++ > 0) {
-                    columnPart.append(',');
-                    valuePart.append(',');
-                }
-
-                columnPart.append(config.getColumnName());
-
-                if (config.getLiteralValue() != null) {
-                    valuePart.append(config.getLiteralValue());
-                } else {
-                    columns.add(new Column(config.getLayout(), config.isEventTimestamp()));
-                    valuePart.append('?');
-                }
-            }
-
-            final String sqlStatement = "INSERT INTO " + data.tableName + " (" + columnPart + ") VALUES (" + valuePart
-                    + ")";
-
-            return new JDBCDatabaseManager(name, data.bufferSize, data.connectionSource, sqlStatement, columns);
-        }
-    }
-
     private static final JDBCDatabaseManagerFactory FACTORY = new JDBCDatabaseManagerFactory();
 
-    /**
-     * Creates a JDBC manager for use within the {@link JDBCAppender}, or returns a suitable one if it already exists.
-     * 
-     * @param name
-     *            The name of the manager, which should include connection details and hashed passwords where possible.
-     * @param bufferSize
-     *            The size of the log event buffer.
-     * @param connectionSource
-     *            The source for connections to the database.
-     * @param tableName
-     *            The name of the database table to insert log events into.
-     * @param columnConfigs
-     *            Configuration information about the log table columns.
-     * @return a new or existing JDBC manager as applicable.
-     */
-    public static JDBCDatabaseManager getJDBCDatabaseManager(final String name, final int bufferSize,
-            final ConnectionSource connectionSource, final String tableName, final ColumnConfig[] columnConfigs) {
-
-        return AbstractDatabaseManager.getManager(name, new FactoryData(bufferSize, connectionSource, tableName,
-                columnConfigs), FACTORY);
-    }
-
     private final List<Column> columns;
-
-    private Connection connection;
-
     private final ConnectionSource connectionSource;
-
     private final String sqlStatement;
 
+    private Connection connection;
     private PreparedStatement statement;
 
     private JDBCDatabaseManager(final String name, final int bufferSize, final ConnectionSource connectionSource,
-            final String sqlStatement, final List<Column> columns) {
+                                final String sqlStatement, final List<Column> columns) {
         super(name, bufferSize);
         this.connectionSource = connectionSource;
         this.sqlStatement = sqlStatement;
@@ -182,4 +103,87 @@ public final class JDBCDatabaseManager e
             LOGGER.error("Failed to insert record for log event in manager [{}].", this.getName(), e);
         }
     }
+
+    /**
+     * Creates a JDBC manager for use within the {@link JDBCAppender}, or returns a suitable one if it already exists.
+     *
+     * @param name The name of the manager, which should include connection details and hashed passwords where possible.
+     * @param bufferSize The size of the log event buffer.
+     * @param connectionSource The source for connections to the database.
+     * @param tableName The name of the database table to insert log events into.
+     * @param columnConfigs Configuration information about the log table columns.
+     * @return a new or existing JDBC manager as applicable.
+     */
+    public static JDBCDatabaseManager getJDBCDatabaseManager(final String name, final int bufferSize,
+                                                             final ConnectionSource connectionSource,
+                                                             final String tableName,
+                                                             final ColumnConfig[] columnConfigs) {
+
+        return AbstractDatabaseManager.getManager(
+                name, new FactoryData(bufferSize, connectionSource, tableName, columnConfigs), FACTORY
+        );
+    }
+
+    /**
+     * Encapsulates data that {@link JDBCDatabaseManagerFactory} uses to create managers.
+     */
+    private static final class FactoryData extends AbstractDatabaseManager.AbstractFactoryData {
+        private final ColumnConfig[] columnConfigs;
+        private final ConnectionSource connectionSource;
+        private final String tableName;
+
+        protected FactoryData(final int bufferSize, final ConnectionSource connectionSource, final String tableName,
+                              final ColumnConfig[] columnConfigs) {
+            super(bufferSize);
+            this.connectionSource = connectionSource;
+            this.tableName = tableName;
+            this.columnConfigs = columnConfigs;
+        }
+    }
+
+    /**
+     * Creates managers.
+     */
+    private static final class JDBCDatabaseManagerFactory implements ManagerFactory<JDBCDatabaseManager, FactoryData> {
+        @Override
+        public JDBCDatabaseManager createManager(final String name, final FactoryData data) {
+            final StringBuilder columnPart = new StringBuilder();
+            final StringBuilder valuePart = new StringBuilder();
+            final List<Column> columns = new ArrayList<Column>();
+            int i = 0;
+            for (final ColumnConfig config : data.columnConfigs) {
+                if (i++ > 0) {
+                    columnPart.append(',');
+                    valuePart.append(',');
+                }
+
+                columnPart.append(config.getColumnName());
+
+                if (config.getLiteralValue() != null) {
+                    valuePart.append(config.getLiteralValue());
+                } else {
+                    columns.add(new Column(config.getLayout(), config.isEventTimestamp()));
+                    valuePart.append('?');
+                }
+            }
+
+            final String sqlStatement = "INSERT INTO " + data.tableName + " (" + columnPart + ") VALUES (" +
+                    valuePart + ")";
+
+            return new JDBCDatabaseManager(name, data.getBufferSize(), data.connectionSource, sqlStatement, columns);
+        }
+    }
+
+    /**
+     * Encapsulates information about a database column and how to persist data to it.
+     */
+    private static final class Column {
+        private final boolean isEventTimestamp;
+        private final PatternLayout layout;
+
+        private Column(final PatternLayout layout, final boolean isEventDate) {
+            this.layout = layout;
+            this.isEventTimestamp = isEventDate;
+        }
+    }
 }

Modified: logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/db/jdbc/package-info.java
URL: http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/db/jdbc/package-info.java?rev=1481932&r1=1481931&r2=1481932&view=diff
==============================================================================
--- logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/db/jdbc/package-info.java (original)
+++ logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/db/jdbc/package-info.java Mon May 13 15:37:27 2013
@@ -19,4 +19,3 @@
  * a JDBC driver on your classpath for the database you wish to log to.
  */
 package org.apache.logging.log4j.core.appender.db.jdbc;
-

Modified: logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/db/jpa/AbstractLogEventWrapperEntity.java
URL: http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/db/jpa/AbstractLogEventWrapperEntity.java?rev=1481932&r1=1481931&r2=1481932&view=diff
==============================================================================
--- logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/db/jpa/AbstractLogEventWrapperEntity.java (original)
+++ logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/db/jpa/AbstractLogEventWrapperEntity.java Mon May 13 15:37:27 2013
@@ -30,8 +30,8 @@ import java.util.Map;
  * Users of the JPA appender MUST extend this class, using JPA annotations on the concrete class and all of its
  * accessor methods (as needed) to map them to the proper table and columns. Accessors you do not want persisted should
  * be annotated with {@link Transient @Transient}. All accessors should call {@link #getWrappedEvent()} and delegate the
- * call to the underlying event. Users may want to instead extend {@link BasicLogEventEntity}, which takes care of all of
- * this for you.<br>
+ * call to the underlying event. Users may want to instead extend {@link BasicLogEventEntity}, which takes care of all
+ * of this for you.<br>
  * <br>
  * The concrete class must have two constructors: a public no-arg constructor to convince the JPA provider that it's a
  * valid entity, and a public constructor that takes a single {@link LogEvent event} and passes it to the parent class
@@ -56,23 +56,25 @@ import java.util.Map;
  */
 @MappedSuperclass
 public abstract class AbstractLogEventWrapperEntity implements LogEvent {
-    /**
-     * Generated serial version ID.
-     */
     private static final long serialVersionUID = 1L;
+
     private final LogEvent wrappedEvent;
 
-    @SuppressWarnings("unused") // JPA requires this
+    /**
+     * Instantiates this base class. All concrete implementations must have a constructor matching this constructor's
+     * signature. The no-argument constructor is required for a standards-compliant JPA provider to accept this as an
+     * entity.
+     */
+    @SuppressWarnings("unused")
     protected AbstractLogEventWrapperEntity() {
         this(null);
     }
 
     /**
-     * Instantiates the base class. All concrete implementations must have two constructors: a no-arg constructor that
-     * calls this constructor with a null argument, and a constructor matching this constructor's signature.
+     * Instantiates this base class. All concrete implementations must have a constructor matching this constructor's
+     * signature. This constructor is used for wrapping this entity around a logged event.
      * 
-     * @param wrappedEvent
-     *            The underlying event from which information is obtained.
+     * @param wrappedEvent The underlying event from which information is obtained.
      */
     protected AbstractLogEventWrapperEntity(final LogEvent wrappedEvent) {
         this.wrappedEvent = wrappedEvent;
@@ -80,6 +82,7 @@ public abstract class AbstractLogEventWr
 
     /**
      * All eventual accessor methods must call this method and delegate the method call to the underlying wrapped event.
+     * Annotated {@link @Transient} so as not to be included in the persisted entity.
      * 
      * @return The underlying event from which information is obtained.
      */
@@ -198,6 +201,12 @@ public abstract class AbstractLogEventWr
         // this entity is write-only
     }
 
+    /**
+     * Indicates whether the source of the logging request is required downstream. Annotated {@link @Transient} so as
+     * not to be included in the persisted entity.
+     *
+     * @return whether the source of the logging request is required downstream.
+     */
     @Override
     @Transient
     public final boolean isIncludeLocation() {
@@ -205,11 +214,16 @@ public abstract class AbstractLogEventWr
     }
 
     @Override
-    @Transient
     public final void setIncludeLocation(final boolean locationRequired) {
         this.getWrappedEvent().setIncludeLocation(locationRequired);
     }
 
+    /**
+     * Indicates whether this event is the last one in a batch. Annotated {@link @Transient} so as not to be included
+     * in the persisted entity.
+     *
+     * @return whether this event is the last one in a batch.
+     */
     @Override
     @Transient
     public final boolean isEndOfBatch() {
@@ -217,7 +231,6 @@ public abstract class AbstractLogEventWr
     }
 
     @Override
-    @Transient
     public final void setEndOfBatch(final boolean endOfBatch) {
         this.getWrappedEvent().setEndOfBatch(endOfBatch);
     }

Modified: logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/db/jpa/BasicLogEventEntity.java
URL: http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/db/jpa/BasicLogEventEntity.java?rev=1481932&r1=1481931&r2=1481932&view=diff
==============================================================================
--- logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/db/jpa/BasicLogEventEntity.java (original)
+++ logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/db/jpa/BasicLogEventEntity.java Mon May 13 15:37:27 2013
@@ -1,3 +1,19 @@
+/*
+ * 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.logging.log4j.core.appender.db.jpa;
 
 import org.apache.logging.log4j.Level;
@@ -48,15 +64,33 @@ import java.util.Map;
  */
 @MappedSuperclass
 public abstract class BasicLogEventEntity extends AbstractLogEventWrapperEntity {
-    @SuppressWarnings("unused") // JPA requires this
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * Instantiates this base class. All concrete implementations must have a constructor matching this constructor's
+     * signature. The no-argument constructor is required for a standards-compliant JPA provider to accept this as an
+     * entity.
+     */
+    @SuppressWarnings("unused")
     public BasicLogEventEntity() {
         super();
     }
 
-    public BasicLogEventEntity(final LogEvent wrapped) {
-        super(wrapped);
+    /**
+     * Instantiates this base class. All concrete implementations must have a constructor matching this constructor's
+     * signature. This constructor is used for wrapping this entity around a logged event.
+     *
+     * @param wrappedEvent The underlying event from which information is obtained.
+     */
+    public BasicLogEventEntity(final LogEvent wrappedEvent) {
+        super(wrappedEvent);
     }
 
+    /**
+     * Gets the level. Annotated with {@code @Basic} and {@code @Enumerated(EnumType.STRING)}.
+     *
+     * @return the level.
+     */
     @Override
     @Basic
     @Enumerated(EnumType.STRING)
@@ -64,60 +98,119 @@ public abstract class BasicLogEventEntit
         return this.getWrappedEvent().getLevel();
     }
 
+    /**
+     * Gets the logger name. Annotated with {@code @Basic}.
+     *
+     * @return the logger name.
+     */
     @Override
     @Basic
     public String getLoggerName() {
         return this.getWrappedEvent().getLoggerName();
     }
 
+    /**
+     * Gets the source location information. Annotated with
+     * {@code @Convert(converter = StackTraceElementAttributeConverter.class)}.
+     *
+     * @return the source location information.
+     * @see StackTraceElementAttributeConverter
+     */
     @Override
     @Convert(converter = StackTraceElementAttributeConverter.class)
     public StackTraceElement getSource() {
         return this.getWrappedEvent().getSource();
     }
 
+    /**
+     * Gets the message. Annotated with {@code @Convert(converter = MessageAttributeConverter.class)}.
+     *
+     * @return the message.
+     * @see MessageAttributeConverter
+     */
     @Override
     @Convert(converter = MessageAttributeConverter.class)
     public Message getMessage() {
         return this.getWrappedEvent().getMessage();
     }
 
+    /**
+     * Gets the marker. Annotated with {@code @Convert(converter = MarkerAttributeConverter.class)}.
+     *
+     * @return the marker.
+     * @see MarkerAttributeConverter
+     */
     @Override
     @Convert(converter = MarkerAttributeConverter.class)
     public Marker getMarker() {
         return this.getWrappedEvent().getMarker();
     }
 
+    /**
+     * Gets the thread name. Annotated with {@code @Basic}.
+     *
+     * @return the thread name.
+     */
     @Override
     @Basic
     public String getThreadName() {
         return this.getWrappedEvent().getThreadName();
     }
 
+    /**
+     * Gets the number of milliseconds since JVM launch. Annotated with {@code @Basic}.
+     *
+     * @return the number of milliseconds since JVM launch.
+     */
     @Override
     @Basic
     public long getMillis() {
         return this.getWrappedEvent().getMillis();
     }
 
+    /**
+     * Gets the exception logged. Annotated with {@code @Convert(converter = ThrowableAttributeConverter.class)}.
+     *
+     * @return the exception logged.
+     * @see ThrowableAttributeConverter
+     */
     @Override
     @Convert(converter = ThrowableAttributeConverter.class)
     public Throwable getThrown() {
         return this.getWrappedEvent().getThrown();
     }
 
+    /**
+     * Gets the context map. Annotated with {@code @Convert(converter = ContextMapAttributeConverter.class)}.
+     *
+     * @return the context map.
+     * @see ContextMapAttributeConverter
+     * @see org.apache.logging.log4j.core.appender.db.jpa.converter.ContextMapJsonAttributeConverter
+     */
     @Override
     @Convert(converter = ContextMapAttributeConverter.class)
     public Map<String, String> getContextMap() {
         return this.getWrappedEvent().getContextMap();
     }
 
+    /**
+     * Gets the context stack. Annotated with {@code @Convert(converter = ContextStackAttributeConverter.class)}.
+     *
+     * @return the context stack.
+     * @see ContextStackAttributeConverter
+     * @see org.apache.logging.log4j.core.appender.db.jpa.converter.ContextStackJsonAttributeConverter
+     */
     @Override
     @Convert(converter = ContextStackAttributeConverter.class)
     public ThreadContext.ContextStack getContextStack() {
         return this.getWrappedEvent().getContextStack();
     }
 
+    /**
+     * Gets the fully qualified class name of the caller of the logger API. Annotated with {@code @Basic}.
+     *
+     * @return the fully qualified class name of the caller of the logger API.
+     */
     @Override
     @Basic
     public String getFQCN() {

Modified: logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/db/jpa/JPAAppender.java
URL: http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/db/jpa/JPAAppender.java?rev=1481932&r1=1481931&r2=1481932&view=diff
==============================================================================
--- logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/db/jpa/JPAAppender.java (original)
+++ logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/db/jpa/JPAAppender.java Mon May 13 15:37:27 2013
@@ -28,40 +28,49 @@ import java.lang.reflect.Constructor;
 
 /**
  * This Appender writes logging events to a relational database using the Java Persistence API. It requires a
- * pre-configured JPA persistence unit and a concrete implementation of the abstract {@link AbstractLogEventWrapperEntity} class
- * decorated with JPA annotations.
+ * pre-configured JPA persistence unit and a concrete implementation of the abstract
+ * {@link AbstractLogEventWrapperEntity} class decorated with JPA annotations.
  * 
  * @see AbstractLogEventWrapperEntity
  */
 @Plugin(name = "Jpa", category = "Core", elementType = "appender", printObject = true)
 public final class JPAAppender extends AbstractDatabaseAppender<JPADatabaseManager> {
+    private final String description;
+
+    private JPAAppender(final String name, final Filter filter, final boolean handleException,
+            final JPADatabaseManager manager) {
+        super(name, filter, handleException, manager);
+        this.description = this.getName() + "{ manager=" + this.getManager() + " }";
+    }
+
+    @Override
+    public String toString() {
+        return this.description;
+    }
+
     /**
      * Factory method for creating a JPA appender within the plugin manager.
-     * 
-     * @param name
-     *            The name of the appender.
-     * @param suppressExceptions
-     *            {@code "true"} (default) if logging exceptions should be hidden from the application, false otherwise.
-     * @param filter
-     *            The filter, if any, to use.
-     * @param bufferSize
-     *            If an integer greater than 0, this causes the appender to buffer log events and flush whenever the
-     *            buffer reaches this size.
-     * @param entityClassName
-     *            The fully qualified name of the concrete {@link AbstractLogEventWrapperEntity} implementation that has JPA
-     *            annotations mapping it to a database table.
-     * @param persistenceUnitName
-     *            The name of the JPA persistence unit that should be used for persisting log events.
+     *
+     * @param name The name of the appender.
+     * @param suppressExceptions {@code "true"} (default) if logging exceptions should be hidden from the application,
+     *                           {@code "false"} otherwise.
+     * @param filter The filter, if any, to use.
+     * @param bufferSize If an integer greater than 0, this causes the appender to buffer log events and flush whenever
+     *                   the buffer reaches this size.
+     * @param entityClassName The fully qualified name of the concrete {@link AbstractLogEventWrapperEntity}
+     *                        implementation that has JPA annotations mapping it to a database table.
+     * @param persistenceUnitName The name of the JPA persistence unit that should be used for persisting log events.
      * @return a new JPA appender.
      */
     @PluginFactory
     public static JPAAppender createAppender(@PluginAttr("name") final String name,
-            @PluginAttr("suppressExceptions") final String suppressExceptions,
-            @PluginElement("filter") final Filter filter, @PluginAttr("bufferSize") final String bufferSize,
-            @PluginAttr("entityClassName") final String entityClassName,
-            @PluginAttr("persistenceUnitName") final String persistenceUnitName) {
-        if (entityClassName == null || entityClassName.length() == 0 || persistenceUnitName == null
-                || persistenceUnitName.length() == 0) {
+                                             @PluginAttr("suppressExceptions") final String suppressExceptions,
+                                             @PluginElement("filter") final Filter filter,
+                                             @PluginAttr("bufferSize") final String bufferSize,
+                                             @PluginAttr("entityClassName") final String entityClassName,
+                                             @PluginAttr("persistenceUnitName") final String persistenceUnitName) {
+        if (entityClassName == null || entityClassName.length() == 0 ||
+                persistenceUnitName == null || persistenceUnitName.length() == 0) {
             LOGGER.error("Attributes entityClassName and persistenceUnitName are required for JPA Appender.");
             return null;
         }
@@ -78,8 +87,8 @@ public final class JPAAppender extends A
 
         try {
             @SuppressWarnings("unchecked")
-            final Class<? extends AbstractLogEventWrapperEntity> entityClass = (Class<? extends AbstractLogEventWrapperEntity>) Class
-                    .forName(entityClassName);
+            final Class<? extends AbstractLogEventWrapperEntity> entityClass =
+                    (Class<? extends AbstractLogEventWrapperEntity>) Class.forName(entityClassName);
 
             if (!AbstractLogEventWrapperEntity.class.isAssignableFrom(entityClass)) {
                 LOGGER.error("Entity class [{}] does not extend AbstractLogEventWrapperEntity.", entityClassName);
@@ -94,14 +103,15 @@ public final class JPAAppender extends A
                 return null;
             }
 
-            final Constructor<? extends AbstractLogEventWrapperEntity> entityConstructor = entityClass
-                    .getConstructor(LogEvent.class);
+            final Constructor<? extends AbstractLogEventWrapperEntity> entityConstructor =
+                    entityClass.getConstructor(LogEvent.class);
 
             final String managerName = "jpaManager{ description=" + name + ", bufferSize=" + bufferSizeInt
                     + ", persistenceUnitName=" + persistenceUnitName + ", entityClass=" + entityClass.getName() + "}";
 
-            final JPADatabaseManager manager = JPADatabaseManager.getJPADatabaseManager(managerName, bufferSizeInt,
-                    entityClass, entityConstructor, persistenceUnitName);
+            final JPADatabaseManager manager = JPADatabaseManager.getJPADatabaseManager(
+                    managerName, bufferSizeInt, entityClass, entityConstructor, persistenceUnitName
+            );
             if (manager == null) {
                 return null;
             }
@@ -116,17 +126,4 @@ public final class JPAAppender extends A
             return null;
         }
     }
-
-    private final String description;
-
-    private JPAAppender(final String name, final Filter filter, final boolean handleException,
-            final JPADatabaseManager manager) {
-        super(name, filter, handleException, manager);
-        this.description = this.getName() + "{ manager=" + this.getManager() + " }";
-    }
-
-    @Override
-    public String toString() {
-        return this.description;
-    }
 }

Modified: logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/db/jpa/JPADatabaseManager.java
URL: http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/db/jpa/JPADatabaseManager.java?rev=1481932&r1=1481931&r2=1481932&view=diff
==============================================================================
--- logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/db/jpa/JPADatabaseManager.java (original)
+++ logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/db/jpa/JPADatabaseManager.java Mon May 13 15:37:27 2013
@@ -30,67 +30,20 @@ import java.lang.reflect.Constructor;
  * An {@link AbstractDatabaseManager} implementation for relational databases accessed via JPA.
  */
 public final class JPADatabaseManager extends AbstractDatabaseManager {
-    private static final class FactoryData extends AbstractDatabaseManager.AbstractFactoryData {
-        private final Class<? extends AbstractLogEventWrapperEntity> entityClass;
-        private final Constructor<? extends AbstractLogEventWrapperEntity> entityConstructor;
-        private final String persistenceUnitName;
-
-        protected FactoryData(final int bufferSize, final Class<? extends AbstractLogEventWrapperEntity> entityClass,
-                final Constructor<? extends AbstractLogEventWrapperEntity> entityConstructor, final String persistenceUnitName) {
-            super(bufferSize);
-
-            this.entityClass = entityClass;
-            this.entityConstructor = entityConstructor;
-            this.persistenceUnitName = persistenceUnitName;
-        }
-    }
-
-    private static final class JPADatabaseManagerFactory implements ManagerFactory<JPADatabaseManager, FactoryData> {
-        @Override
-        public JPADatabaseManager createManager(final String name, final FactoryData data) {
-            return new JPADatabaseManager(name, data.bufferSize, data.entityClass, data.entityConstructor,
-                    data.persistenceUnitName);
-        }
-    }
-
     private static final JPADatabaseManagerFactory FACTORY = new JPADatabaseManagerFactory();
 
-    /**
-     * Creates a JPA manager for use within the {@link JPAAppender}, or returns a suitable one if it already exists.
-     * 
-     * @param name
-     *            The name of the manager, which should include connection details, entity class name, etc.
-     * @param bufferSize
-     *            The size of the log event buffer.
-     * @param entityClass
-     *            The fully-qualified class name of the {@link AbstractLogEventWrapperEntity} concrete implementation.
-     * @param entityConstructor
-     *            The one-arg {@link LogEvent} constructor for the concrete entity class.
-     * @param persistenceUnitName
-     *            The name of the JPA persistence unit that should be used for persisting log events.
-     * @return a new or existing JPA manager as applicable.
-     */
-    public static JPADatabaseManager getJPADatabaseManager(final String name, final int bufferSize,
-            final Class<? extends AbstractLogEventWrapperEntity> entityClass,
-            final Constructor<? extends AbstractLogEventWrapperEntity> entityConstructor, final String persistenceUnitName) {
-
-        return AbstractDatabaseManager.getManager(name, new FactoryData(bufferSize, entityClass, entityConstructor,
-                persistenceUnitName), FACTORY);
-    }
-
     private final String entityClassName;
     private final Constructor<? extends AbstractLogEventWrapperEntity> entityConstructor;
-    private EntityManager entityManager;
-
-    private EntityManagerFactory entityManagerFactory;
-
     private final String persistenceUnitName;
 
+    private EntityManager entityManager;
+    private EntityManagerFactory entityManagerFactory;
     private EntityTransaction transaction;
 
     private JPADatabaseManager(final String name, final int bufferSize,
-            final Class<? extends AbstractLogEventWrapperEntity> entityClass,
-            final Constructor<? extends AbstractLogEventWrapperEntity> entityConstructor, final String persistenceUnitName) {
+                               final Class<? extends AbstractLogEventWrapperEntity> entityClass,
+                               final Constructor<? extends AbstractLogEventWrapperEntity> entityConstructor,
+                               final String persistenceUnitName) {
         super(name, bufferSize);
         this.entityClassName = entityClass.getName();
         this.entityConstructor = entityConstructor;
@@ -142,4 +95,58 @@ public final class JPADatabaseManager ex
             this.transaction.rollback();
         }
     }
+
+    /**
+     * Creates a JPA manager for use within the {@link JPAAppender}, or returns a suitable one if it already exists.
+     *
+     * @param name The name of the manager, which should include connection details, entity class name, etc.
+     * @param bufferSize The size of the log event buffer.
+     * @param entityClass The fully-qualified class name of the {@link AbstractLogEventWrapperEntity} concrete
+     *                    implementation.
+     * @param entityConstructor The one-arg {@link LogEvent} constructor for the concrete entity class.
+     * @param persistenceUnitName The name of the JPA persistence unit that should be used for persisting log events.
+     * @return a new or existing JPA manager as applicable.
+     */
+    public static JPADatabaseManager getJPADatabaseManager(final String name, final int bufferSize,
+                                                           final Class<? extends AbstractLogEventWrapperEntity>
+                                                                   entityClass,
+                                                           final Constructor<? extends AbstractLogEventWrapperEntity>
+                                                                   entityConstructor,
+                                                           final String persistenceUnitName) {
+
+        return AbstractDatabaseManager.getManager(
+                name, new FactoryData(bufferSize, entityClass, entityConstructor, persistenceUnitName), FACTORY
+        );
+    }
+
+    /**
+     * Encapsulates data that {@link JPADatabaseManagerFactory} uses to create managers.
+     */
+    private static final class FactoryData extends AbstractDatabaseManager.AbstractFactoryData {
+        private final Class<? extends AbstractLogEventWrapperEntity> entityClass;
+        private final Constructor<? extends AbstractLogEventWrapperEntity> entityConstructor;
+        private final String persistenceUnitName;
+
+        protected FactoryData(final int bufferSize, final Class<? extends AbstractLogEventWrapperEntity> entityClass,
+                              final Constructor<? extends AbstractLogEventWrapperEntity> entityConstructor,
+                              final String persistenceUnitName) {
+            super(bufferSize);
+
+            this.entityClass = entityClass;
+            this.entityConstructor = entityConstructor;
+            this.persistenceUnitName = persistenceUnitName;
+        }
+    }
+
+    /**
+     * Creates managers.
+     */
+    private static final class JPADatabaseManagerFactory implements ManagerFactory<JPADatabaseManager, FactoryData> {
+        @Override
+        public JPADatabaseManager createManager(final String name, final FactoryData data) {
+            return new JPADatabaseManager(
+                    name, data.getBufferSize(), data.entityClass, data.entityConstructor, data.persistenceUnitName
+            );
+        }
+    }
 }

Modified: logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/db/jpa/converter/ContextMapJsonAttributeConverter.java
URL: http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/db/jpa/converter/ContextMapJsonAttributeConverter.java?rev=1481932&r1=1481931&r2=1481932&view=diff
==============================================================================
--- logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/db/jpa/converter/ContextMapJsonAttributeConverter.java (original)
+++ logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/db/jpa/converter/ContextMapJsonAttributeConverter.java Mon May 13 15:37:27 2013
@@ -1,3 +1,19 @@
+/*
+ * 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.logging.log4j.core.appender.db.jpa.converter;
 
 import org.codehaus.jackson.map.ObjectMapper;



Mime
View raw message