logging-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From ggreg...@apache.org
Subject svn commit: r1481026 [2/2] - in /logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/db: ./ jdbc/ jpa/ nosql/ nosql/couch/ nosql/mongo/
Date Fri, 10 May 2013 14:32:04 GMT
Added: logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/db/nosql/NoSQLAppender.java
URL: http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/db/nosql/NoSQLAppender.java?rev=1481026&view=auto
==============================================================================
--- logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/db/nosql/NoSQLAppender.java (added)
+++ logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/db/nosql/NoSQLAppender.java Fri May 10 14:32:03 2013
@@ -0,0 +1,100 @@
+/*
+ * 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.nosql;
+
+import org.apache.logging.log4j.core.Filter;
+import org.apache.logging.log4j.core.appender.db.AbstractDatabaseAppender;
+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.PluginElement;
+import org.apache.logging.log4j.core.config.plugins.PluginFactory;
+
+/**
+ * This Appender writes logging events to a NoSQL database using a configured NoSQL provider. It requires
+ * implementations of {@link NoSQLObject}, {@link NoSQLConnection}, and {@link NoSQLProvider} to "know" how to write
+ * events to the chosen NoSQL database. Two provider implementations are provided: MongoDB
+ * (org.mongodb:mongo-java-driver:2.11.1 or newer must be on the classpath) and Apache CouchDB
+ * (org.lightcouch:lightcouch:0.0.5 or newer must be on the classpath). For examples on how to write your own NoSQL
+ * provider, see the simple source code for the MongoDB and CouchDB providers.
+ * 
+ * @see NoSQLObject
+ * @see NoSQLConnection
+ * @see NoSQLProvider
+ */
+@Plugin(name = "NoSql", category = "Core", elementType = "appender", printObject = true)
+public final class NoSQLAppender extends AbstractDatabaseAppender<NoSQLDatabaseManager<?>> {
+    /**
+     * Factory method for creating a NoSQL 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 provider
+     *            The NoSQL provider that provides connections to the chosen NoSQL database.
+     * @return a new NoSQL appender.
+     */
+    @PluginFactory
+    public static NoSQLAppender createAppender(@PluginAttr("name") final String name,
+            @PluginAttr("suppressExceptions") final String suppressExceptions,
+            @PluginElement("filter") final Filter filter, @PluginAttr("bufferSize") final String bufferSize,
+            @PluginElement("noSqlProvider") final NoSQLProvider<?> provider) {
+        if (provider == null) {
+            LOGGER.error("NoSQL provider not specified for appender [{}].", name);
+            return null;
+        }
+
+        int bufferSizeInt;
+        try {
+            bufferSizeInt = bufferSize == null || bufferSize.length() == 0 ? 0 : Integer.parseInt(bufferSize);
+        } catch (final NumberFormatException e) {
+            LOGGER.warn("Buffer size [" + bufferSize + "] not an integer, using no buffer.");
+            bufferSizeInt = 0;
+        }
+
+        final boolean handleExceptions = suppressExceptions == null || !Boolean.parseBoolean(suppressExceptions);
+
+        final String managerName = "noSqlManager{ description=" + name + ", bufferSize=" + bufferSizeInt
+                + ", provider=" + provider + " }";
+
+        final NoSQLDatabaseManager<?> manager = NoSQLDatabaseManager.getNoSQLDatabaseManager(managerName,
+                bufferSizeInt, provider);
+        if (manager == null) {
+            return null;
+        }
+
+        return new NoSQLAppender(name, filter, handleExceptions, manager);
+    }
+
+    private final String description;
+
+    private NoSQLAppender(final String name, final Filter filter, final boolean handleException,
+            final NoSQLDatabaseManager<?> manager) {
+        super(name, filter, handleException, manager);
+        this.description = this.getName() + "{ manager=" + this.getManager() + " }";
+    }
+
+    @Override
+    public String toString() {
+        return this.description;
+    }
+}

Propchange: logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/db/nosql/NoSQLAppender.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/db/nosql/NoSQLAppender.java
------------------------------------------------------------------------------
    svn:keywords = Id

Added: logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/db/nosql/NoSQLConnection.java
URL: http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/db/nosql/NoSQLConnection.java?rev=1481026&view=auto
==============================================================================
--- logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/db/nosql/NoSQLConnection.java (added)
+++ logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/db/nosql/NoSQLConnection.java Fri May 10 14:32:03 2013
@@ -0,0 +1,38 @@
+/*
+ * 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.nosql;
+
+/**
+ * Represents a connection to the NoSQL database. Serves as a factory for new (empty) objects and an endpoint for
+ * inserted objects.
+ * 
+ * @param <T>
+ *            Specifies which implementation of {@link NoSQLObject} this connection provides.
+ * @param <W>
+ *            Specifies which type of database object is wrapped by the {@link NoSQLObject} implementation provided.
+ */
+public interface NoSQLConnection<W, T extends NoSQLObject<W>> {
+    void close();
+
+    T[] createList(int length);
+
+    T createObject();
+
+    void insertObject(NoSQLObject<W> object);
+
+    boolean isClosed();
+}

Propchange: logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/db/nosql/NoSQLConnection.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/db/nosql/NoSQLConnection.java
------------------------------------------------------------------------------
    svn:keywords = Id

Added: logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/db/nosql/NoSQLDatabaseManager.java
URL: http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/db/nosql/NoSQLDatabaseManager.java?rev=1481026&view=auto
==============================================================================
--- logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/db/nosql/NoSQLDatabaseManager.java (added)
+++ logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/db/nosql/NoSQLDatabaseManager.java Fri May 10 14:32:03 2013
@@ -0,0 +1,200 @@
+/*
+ * 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.nosql;
+
+import java.util.Map;
+
+import org.apache.logging.log4j.Marker;
+import org.apache.logging.log4j.ThreadContext;
+import org.apache.logging.log4j.core.LogEvent;
+import org.apache.logging.log4j.core.appender.ManagerFactory;
+import org.apache.logging.log4j.core.appender.db.AbstractDatabaseManager;
+
+/**
+ * An {@link AbstractDatabaseManager} implementation for all NoSQL databases.
+ * 
+ * @param <W>
+ *            A type parameter for reassuring the compiler that all operations are using the same {@link NoSQLObject}.
+ */
+public final class NoSQLDatabaseManager<W> extends AbstractDatabaseManager {
+    private static final class FactoryData extends AbstractDatabaseManager.AbstractFactoryData {
+        private final NoSQLProvider<?> provider;
+
+        protected FactoryData(final int bufferSize, final NoSQLProvider<?> provider) {
+            super(bufferSize);
+            this.provider = provider;
+        }
+    }
+
+    private static final class NoSQLDatabaseManagerFactory implements
+            ManagerFactory<NoSQLDatabaseManager<?>, FactoryData> {
+        @Override
+        @SuppressWarnings("unchecked")
+        public NoSQLDatabaseManager<?> createManager(final String name, final FactoryData data) {
+            return new NoSQLDatabaseManager(name, data.bufferSize, data.provider);
+        }
+    }
+
+    private static final NoSQLDatabaseManagerFactory FACTORY = new NoSQLDatabaseManagerFactory();
+
+    /**
+     * Creates a NoSQL manager for use within the {@link NoSQLAppender}, 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 provider
+     *            A provider instance which will be used to obtain connections to the chosen NoSQL database.
+     * @return a new or existing NoSQL manager as applicable.
+     */
+    public static NoSQLDatabaseManager<?> getNoSQLDatabaseManager(final String name, final int bufferSize,
+            final NoSQLProvider<?> provider) {
+        return AbstractDatabaseManager.getManager(name, new FactoryData(bufferSize, provider), FACTORY);
+    }
+
+    private NoSQLConnection<W, ? extends NoSQLObject<W>> connection;
+
+    private final NoSQLProvider<NoSQLConnection<W, ? extends NoSQLObject<W>>> provider;
+
+    private NoSQLDatabaseManager(final String name, final int bufferSize,
+            final NoSQLProvider<NoSQLConnection<W, ? extends NoSQLObject<W>>> provider) {
+        super(name, bufferSize);
+        this.provider = provider;
+    }
+
+    @Override
+    protected void connectInternal() {
+        try {
+            this.connection = this.provider.getConnection();
+        } catch (final Exception e) {
+            LOGGER.error("Failed to obtain a connection to the NoSQL database in manager [{}].", this.getName(), e);
+        }
+    }
+
+    private NoSQLObject<W>[] convertStackTrace(final StackTraceElement[] stackTrace) {
+        final NoSQLObject<W>[] stackTraceEntities = this.connection.createList(stackTrace.length);
+        for (int i = 0; i < stackTrace.length; i++) {
+            stackTraceEntities[i] = this.convertStackTraceElement(stackTrace[i]);
+        }
+        return stackTraceEntities;
+    }
+
+    private NoSQLObject<W> convertStackTraceElement(final StackTraceElement element) {
+        final NoSQLObject<W> elementEntity = this.connection.createObject();
+        elementEntity.set("className", element.getClassName());
+        elementEntity.set("methodName", element.getMethodName());
+        elementEntity.set("fileName", element.getFileName());
+        elementEntity.set("lineNumber", element.getLineNumber());
+        return elementEntity;
+    }
+
+    @Override
+    protected void disconnectInternal() {
+        try {
+            if (this.connection != null && !this.connection.isClosed()) {
+                this.connection.close();
+            }
+        } catch (final Exception e) {
+            LOGGER.warn("Error while closing NoSQL database connection in manager [{}].", this.getName(), e);
+        }
+    }
+
+    @Override
+    protected void writeInternal(final LogEvent event) {
+        if (!this.isConnected() || this.connection == null || this.connection.isClosed()) {
+            LOGGER.error("Cannot write logging event; manager [{}] not connected to the database.", this.getName());
+            return;
+        }
+
+        final NoSQLObject<W> entity = this.connection.createObject();
+        entity.set("level", event.getLevel());
+        entity.set("loggerName", event.getLoggerName());
+        entity.set("message", event.getMessage() == null ? null : event.getMessage().getFormattedMessage());
+
+        final StackTraceElement source = event.getSource();
+        if (source == null) {
+            entity.set("source", (Object) null);
+        } else {
+            entity.set("source", this.convertStackTraceElement(source));
+        }
+
+        Marker marker = event.getMarker();
+        if (marker == null) {
+            entity.set("marker", (Object) null);
+        } else {
+            final NoSQLObject<W> originalMarkerEntity = this.connection.createObject();
+            NoSQLObject<W> markerEntity = originalMarkerEntity;
+            markerEntity.set("name", marker.getName());
+            while (marker.getParent() != null) {
+                marker = marker.getParent();
+                final NoSQLObject<W> parentMarkerEntity = this.connection.createObject();
+                parentMarkerEntity.set("name", marker.getName());
+                markerEntity.set("parent", parentMarkerEntity);
+                markerEntity = parentMarkerEntity;
+            }
+            entity.set("marker", originalMarkerEntity);
+        }
+
+        entity.set("threadName", event.getThreadName());
+        entity.set("millis", event.getMillis());
+        entity.set("date", new java.util.Date(event.getMillis()));
+
+        @SuppressWarnings("ThrowableResultOfMethodCallIgnored")
+        Throwable thrown = event.getThrown();
+        if (thrown == null) {
+            entity.set("thrown", (Object) null);
+        } else {
+            final NoSQLObject<W> originalExceptionEntity = this.connection.createObject();
+            NoSQLObject<W> exceptionEntity = originalExceptionEntity;
+            exceptionEntity.set("type", thrown.getClass().getName());
+            exceptionEntity.set("message", thrown.getMessage());
+            exceptionEntity.set("stackTrace", this.convertStackTrace(thrown.getStackTrace()));
+            while (thrown.getCause() != null) {
+                thrown = thrown.getCause();
+                final NoSQLObject<W> causingExceptionEntity = this.connection.createObject();
+                causingExceptionEntity.set("type", thrown.getClass().getName());
+                causingExceptionEntity.set("message", thrown.getMessage());
+                causingExceptionEntity.set("stackTrace", this.convertStackTrace(thrown.getStackTrace()));
+                exceptionEntity.set("cause", causingExceptionEntity);
+                exceptionEntity = causingExceptionEntity;
+            }
+
+            entity.set("thrown", originalExceptionEntity);
+        }
+
+        final Map<String, String> contextMap = event.getContextMap();
+        if (contextMap == null) {
+            entity.set("contextMap", (Object) null);
+        } else {
+            final NoSQLObject<W> contextMapEntity = this.connection.createObject();
+            for (final Map.Entry<String, String> entry : contextMap.entrySet()) {
+                contextMapEntity.set(entry.getKey(), entry.getValue());
+            }
+            entity.set("contextMap", contextMapEntity);
+        }
+
+        final ThreadContext.ContextStack contextStack = event.getContextStack();
+        if (contextStack == null) {
+            entity.set("contextStack", (Object) null);
+        } else {
+            entity.set("contextStack", contextStack.asList().toArray());
+        }
+
+        this.connection.insertObject(entity);
+    }
+}

Propchange: logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/db/nosql/NoSQLDatabaseManager.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/db/nosql/NoSQLDatabaseManager.java
------------------------------------------------------------------------------
    svn:keywords = Id

Added: logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/db/nosql/NoSQLObject.java
URL: http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/db/nosql/NoSQLObject.java?rev=1481026&view=auto
==============================================================================
--- logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/db/nosql/NoSQLObject.java (added)
+++ logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/db/nosql/NoSQLObject.java Fri May 10 14:32:03 2013
@@ -0,0 +1,35 @@
+/*
+ * 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.nosql;
+
+/**
+ * Represents a simple POJO object inserted into a NoSQL object.
+ * 
+ * @param <W>
+ *            Specifies what type of underlying object (such as a MongoDB BasicDBObject) this NoSQLObject wraps.
+ */
+public interface NoSQLObject<W> {
+    void set(String field, NoSQLObject<W> value);
+
+    void set(String field, NoSQLObject<W>[] values);
+
+    void set(String field, Object value);
+
+    void set(String field, Object[] values);
+
+    W unwrap();
+}

Propchange: logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/db/nosql/NoSQLObject.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/db/nosql/NoSQLObject.java
------------------------------------------------------------------------------
    svn:keywords = Id

Added: logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/db/nosql/NoSQLProvider.java
URL: http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/db/nosql/NoSQLProvider.java?rev=1481026&view=auto
==============================================================================
--- logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/db/nosql/NoSQLProvider.java (added)
+++ logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/db/nosql/NoSQLProvider.java Fri May 10 14:32:03 2013
@@ -0,0 +1,28 @@
+/*
+ * 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.nosql;
+
+/**
+ * Implementations of this class are plugins for configuring the {@link NoSQLAppender} with the proper provider
+ * (MongoDB, etc.).
+ * 
+ * @param <C>
+ *            Specifies which implementation of {@link NoSQLConnection} this provider provides.
+ */
+public interface NoSQLProvider<C extends NoSQLConnection<?, ? extends NoSQLObject<?>>> {
+    C getConnection();
+}

Propchange: logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/db/nosql/NoSQLProvider.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/db/nosql/NoSQLProvider.java
------------------------------------------------------------------------------
    svn:keywords = Id

Added: logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/db/nosql/couch/CouchDBConnection.java
URL: http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/db/nosql/couch/CouchDBConnection.java?rev=1481026&view=auto
==============================================================================
--- logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/db/nosql/couch/CouchDBConnection.java (added)
+++ logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/db/nosql/couch/CouchDBConnection.java Fri May 10 14:32:03 2013
@@ -0,0 +1,73 @@
+/*
+ * 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.nosql.couch;
+
+import java.util.Map;
+
+import org.apache.logging.log4j.Logger;
+import org.apache.logging.log4j.core.appender.db.nosql.NoSQLConnection;
+import org.apache.logging.log4j.core.appender.db.nosql.NoSQLObject;
+import org.apache.logging.log4j.status.StatusLogger;
+import org.lightcouch.CouchDbClient;
+import org.lightcouch.Response;
+
+/**
+ * The Apache CouchDB implementation of {@link NoSQLConnection}.
+ */
+public final class CouchDBConnection implements NoSQLConnection<Map<String, Object>, CouchDBObject> {
+    private static final Logger LOGGER = StatusLogger.getLogger();
+
+    private final CouchDbClient client;
+    private boolean closed = false;
+
+    public CouchDBConnection(final CouchDbClient client) {
+        this.client = client;
+    }
+
+    @Override
+    public synchronized void close() {
+        this.closed = true;
+        this.client.shutdown();
+    }
+
+    @Override
+    public CouchDBObject[] createList(final int length) {
+        return new CouchDBObject[length];
+    }
+
+    @Override
+    public CouchDBObject createObject() {
+        return new CouchDBObject();
+    }
+
+    @Override
+    public void insertObject(final NoSQLObject<Map<String, Object>> object) {
+        try {
+            final Response response = this.client.save(object.unwrap());
+            if (response.getError() != null && response.getError().length() > 0) {
+                LOGGER.error("Failed to write log event to CouchDB due to error: [{}].", response.getError());
+            }
+        } catch (final Exception e) {
+            LOGGER.error("Failed to write log event to CouchDB due to error.", e);
+        }
+    }
+
+    @Override
+    public synchronized boolean isClosed() {
+        return this.closed;
+    }
+}

Propchange: logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/db/nosql/couch/CouchDBConnection.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/db/nosql/couch/CouchDBConnection.java
------------------------------------------------------------------------------
    svn:keywords = Id

Added: logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/db/nosql/couch/CouchDBObject.java
URL: http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/db/nosql/couch/CouchDBObject.java?rev=1481026&view=auto
==============================================================================
--- logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/db/nosql/couch/CouchDBObject.java (added)
+++ logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/db/nosql/couch/CouchDBObject.java Fri May 10 14:32:03 2013
@@ -0,0 +1,64 @@
+/*
+ * 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.nosql.couch;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.logging.log4j.core.appender.db.nosql.NoSQLObject;
+
+/**
+ * The Apache CouchDB implementation of {@link NoSQLObject}.
+ */
+public final class CouchDBObject implements NoSQLObject<Map<String, Object>> {
+    private final Map<String, Object> map;
+
+    public CouchDBObject() {
+        this.map = new HashMap<String, Object>();
+    }
+
+    @Override
+    public void set(final String field, final NoSQLObject<Map<String, Object>> value) {
+        this.map.put(field, value.unwrap());
+    }
+
+    @Override
+    public void set(final String field, final NoSQLObject<Map<String, Object>>[] values) {
+        final ArrayList<Map<String, Object>> list = new ArrayList<Map<String, Object>>();
+        for (final NoSQLObject<Map<String, Object>> value : values) {
+            list.add(value.unwrap());
+        }
+        this.map.put(field, list);
+    }
+
+    @Override
+    public void set(final String field, final Object value) {
+        this.map.put(field, value);
+    }
+
+    @Override
+    public void set(final String field, final Object[] values) {
+        this.map.put(field, Arrays.asList(values));
+    }
+
+    @Override
+    public Map<String, Object> unwrap() {
+        return this.map;
+    }
+}

Propchange: logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/db/nosql/couch/CouchDBObject.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/db/nosql/couch/CouchDBObject.java
------------------------------------------------------------------------------
    svn:keywords = Id

Added: logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/db/nosql/couch/CouchDBProvider.java
URL: http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/db/nosql/couch/CouchDBProvider.java?rev=1481026&view=auto
==============================================================================
--- logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/db/nosql/couch/CouchDBProvider.java (added)
+++ logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/db/nosql/couch/CouchDBProvider.java Fri May 10 14:32:03 2013
@@ -0,0 +1,174 @@
+/*
+ * 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.nosql.couch;
+
+import java.lang.reflect.Method;
+
+import org.apache.logging.log4j.Logger;
+import org.apache.logging.log4j.core.appender.db.nosql.NoSQLProvider;
+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.core.helpers.NameUtil;
+import org.apache.logging.log4j.status.StatusLogger;
+import org.lightcouch.CouchDbClient;
+import org.lightcouch.CouchDbProperties;
+
+/**
+ * The Apache CouchDB implementation of {@link NoSQLProvider}.
+ */
+@Plugin(name = "CouchDb", category = "Core", printObject = true)
+public final class CouchDBProvider implements NoSQLProvider<CouchDBConnection> {
+    private static final int HTTP = 80;
+    private static final int HTTPS = 443;
+    private static final Logger LOGGER = StatusLogger.getLogger();
+
+    /**
+     * Factory method for creating an Apache CouchDB provider within the plugin manager.
+     * 
+     * @param databaseName
+     *            The name of the database to which log event documents will be written.
+     * @param protocol
+     *            Either "http" or "https," defaults to "http" and mutually exclusive with
+     *            {@code factoryClassName&factoryMethodName!=null}.
+     * @param server
+     *            The host name of the CouchDB server, defaults to localhost and mutually exclusive with
+     *            {@code factoryClassName&factoryMethodName!=null}.
+     * @param port
+     *            The port that CouchDB is listening on, defaults to 80 if {@code protocol} is "http" and 443 if
+     *            {@code protocol} is "https," and mutually exclusive with
+     *            {@code factoryClassName&factoryMethodName!=null}.
+     * @param username
+     *            The username to authenticate against the MongoDB server with, mutually exclusive with
+     *            {@code factoryClassName&factoryMethodName!=null}.
+     * @param password
+     *            The password to authenticate against the MongoDB server with, mutually exclusive with
+     *            {@code factoryClassName&factoryMethodName!=null}.
+     * @param factoryClassName
+     *            A fully qualified class name containing a static factory method capable of returning a
+     *            {@link CouchDbClient} or {@link CouchDbProperties}.
+     * @param factoryMethodName
+     *            The name of the public static factory method belonging to the aforementioned factory class.
+     * @return a new Apache CouchDB provider.
+     */
+    @PluginFactory
+    public static CouchDBProvider createNoSQLProvider(@PluginAttr("databaseName") final String databaseName,
+            @PluginAttr("protocol") String protocol, @PluginAttr("server") String server,
+            @PluginAttr("port") final String port, @PluginAttr("username") final String username,
+            @PluginAttr("password") final String password,
+            @PluginAttr("factoryClassName") final String factoryClassName,
+            @PluginAttr("factoryMethodName") final String factoryMethodName) {
+        CouchDbClient client;
+        String description;
+        if (factoryClassName != null && factoryClassName.length() > 0 && factoryMethodName != null
+                && factoryMethodName.length() > 0) {
+            try {
+                final Class<?> factoryClass = Class.forName(factoryClassName);
+                final Method method = factoryClass.getMethod(factoryMethodName);
+                final Object object = method.invoke(null);
+
+                if (object instanceof CouchDbClient) {
+                    client = (CouchDbClient) object;
+                    description = "uri=" + client.getDBUri();
+                } else if (object instanceof CouchDbProperties) {
+                    final CouchDbProperties properties = (CouchDbProperties) object;
+                    client = new CouchDbClient(properties);
+                    description = "uri=" + client.getDBUri() + ", username=" + properties.getUsername()
+                            + ", passwordHash=" + NameUtil.md5(password + CouchDBProvider.class.getName())
+                            + ", maxConnections=" + properties.getMaxConnections() + ", connectionTimeout="
+                            + properties.getConnectionTimeout() + ", socketTimeout=" + properties.getSocketTimeout();
+                } else if (object == null) {
+                    LOGGER.error("The factory method [{}.{}()] returned null.", factoryClassName, factoryMethodName);
+                    return null;
+                } else {
+                    LOGGER.error("The factory method [{}.{}()] returned an unsupported type [{}].", factoryClassName,
+                            factoryMethodName, object.getClass().getName());
+                    return null;
+                }
+            } catch (final ClassNotFoundException e) {
+                LOGGER.error("The factory class [{}] could not be loaded.", factoryClassName, e);
+                return null;
+            } catch (final NoSuchMethodException e) {
+                LOGGER.error("The factory class [{}] does not have a no-arg method named [{}].", factoryClassName,
+                        factoryMethodName, e);
+                return null;
+            } catch (final Exception e) {
+                LOGGER.error("The factory method [{}.{}()] could not be invoked.", factoryClassName, factoryMethodName,
+                        e);
+                return null;
+            }
+        } else if (databaseName != null && databaseName.length() > 0) {
+            if (protocol != null && protocol.length() > 0) {
+                if (!protocol.equals("http") && !protocol.equals("https")) {
+                    LOGGER.error("Only protocols [http] and [https] are supported, [{}] specified.", protocol);
+                    return null;
+                }
+            } else {
+                protocol = "http";
+                LOGGER.warn("No protocol specified, using default port [http].");
+            }
+
+            int portInt = protocol.equals("https") ? HTTPS : HTTP;
+            if (port != null && port.length() > 0) {
+                try {
+                    portInt = Integer.parseInt(port);
+                } catch (final NumberFormatException ignore) { /* */
+                }
+            } else {
+                LOGGER.warn("No port specified, using default port [{}] for protocol [{}].", portInt, protocol);
+            }
+
+            if (server == null || server.length() == 0) {
+                server = "localhost";
+                LOGGER.warn("No server specified, using default server localhost.");
+            }
+
+            if (username == null || username.length() == 0 || password == null || password.length() == 0) {
+                LOGGER.error("You must provide a username and password for the CouchDB provider.");
+                return null;
+            }
+
+            client = new CouchDbClient(databaseName, false, protocol, server, portInt, username, password);
+            description = "uri=" + client.getDBUri() + ", username=" + username + ", passwordHash="
+                    + NameUtil.md5(password + CouchDBProvider.class.getName());
+        } else {
+            LOGGER.error("No factory method was provided so the database name is required.");
+            return null;
+        }
+
+        return new CouchDBProvider(client, description);
+    }
+
+    private final CouchDbClient client;
+
+    private final String description;
+
+    private CouchDBProvider(final CouchDbClient client, final String description) {
+        this.client = client;
+        this.description = "couchDb{ " + description + " }";
+    }
+
+    @Override
+    public CouchDBConnection getConnection() {
+        return new CouchDBConnection(this.client);
+    }
+
+    @Override
+    public String toString() {
+        return this.description;
+    }
+}

Propchange: logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/db/nosql/couch/CouchDBProvider.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/db/nosql/couch/CouchDBProvider.java
------------------------------------------------------------------------------
    svn:keywords = Id

Added: logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/db/nosql/couch/package-info.java
URL: http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/db/nosql/couch/package-info.java?rev=1481026&view=auto
==============================================================================
--- logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/db/nosql/couch/package-info.java (added)
+++ logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/db/nosql/couch/package-info.java Fri May 10 14:32:03 2013
@@ -0,0 +1,21 @@
+/*
+ * 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.
+ */
+/**
+ * The classes in this package contain the Apache CouchDB provider for the NoSQL Appender.
+ */
+package org.apache.logging.log4j.core.appender.db.nosql.couch;
+

Propchange: logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/db/nosql/couch/package-info.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/db/nosql/couch/package-info.java
------------------------------------------------------------------------------
    svn:keywords = Id

Added: logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/db/nosql/mongo/MongoDBConnection.java
URL: http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/db/nosql/mongo/MongoDBConnection.java?rev=1481026&view=auto
==============================================================================
--- logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/db/nosql/mongo/MongoDBConnection.java (added)
+++ logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/db/nosql/mongo/MongoDBConnection.java Fri May 10 14:32:03 2013
@@ -0,0 +1,79 @@
+/*
+ * 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.nosql.mongo;
+
+import org.apache.logging.log4j.Logger;
+import org.apache.logging.log4j.core.appender.db.nosql.NoSQLConnection;
+import org.apache.logging.log4j.core.appender.db.nosql.NoSQLObject;
+import org.apache.logging.log4j.status.StatusLogger;
+
+import com.mongodb.BasicDBObject;
+import com.mongodb.DB;
+import com.mongodb.DBCollection;
+import com.mongodb.Mongo;
+import com.mongodb.MongoException;
+import com.mongodb.WriteConcern;
+import com.mongodb.WriteResult;
+
+/**
+ * The MongoDB implementation of {@link NoSQLConnection}.
+ */
+public final class MongoDBConnection implements NoSQLConnection<BasicDBObject, MongoDBObject> {
+    private static final Logger LOGGER = StatusLogger.getLogger();
+
+    private final DBCollection collection;
+    private final Mongo mongo;
+    private final WriteConcern writeConcern;
+
+    public MongoDBConnection(final DB database, final WriteConcern writeConcern, final String collectionName) {
+        this.mongo = database.getMongo();
+        this.collection = database.getCollection(collectionName);
+        this.writeConcern = writeConcern;
+    }
+
+    @Override
+    public void close() {
+        this.mongo.close();
+    }
+
+    @Override
+    public MongoDBObject[] createList(final int length) {
+        return new MongoDBObject[length];
+    }
+
+    @Override
+    public MongoDBObject createObject() {
+        return new MongoDBObject();
+    }
+
+    @Override
+    public void insertObject(final NoSQLObject<BasicDBObject> object) {
+        try {
+            final WriteResult result = this.collection.insert(object.unwrap(), this.writeConcern);
+            if (result.getN() < 1) {
+                LOGGER.error("Failed to write log event to MongoDB due to invalid result [{}].", result.getN());
+            }
+        } catch (final MongoException e) {
+            LOGGER.error("Failed to write log event to MongoDB due to error.", e);
+        }
+    }
+
+    @Override
+    public boolean isClosed() {
+        return !this.mongo.getConnector().isOpen();
+    }
+}

Propchange: logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/db/nosql/mongo/MongoDBConnection.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/db/nosql/mongo/MongoDBConnection.java
------------------------------------------------------------------------------
    svn:keywords = Id

Added: logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/db/nosql/mongo/MongoDBObject.java
URL: http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/db/nosql/mongo/MongoDBObject.java?rev=1481026&view=auto
==============================================================================
--- logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/db/nosql/mongo/MongoDBObject.java (added)
+++ logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/db/nosql/mongo/MongoDBObject.java Fri May 10 14:32:03 2013
@@ -0,0 +1,66 @@
+/*
+ * 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.nosql.mongo;
+
+import java.util.Collections;
+
+import org.apache.logging.log4j.core.appender.db.nosql.NoSQLObject;
+
+import com.mongodb.BasicDBList;
+import com.mongodb.BasicDBObject;
+
+/**
+ * The MongoDB implementation of {@link NoSQLObject}.
+ */
+public final class MongoDBObject implements NoSQLObject<BasicDBObject> {
+    private final BasicDBObject mongoObject;
+
+    public MongoDBObject() {
+        this.mongoObject = new BasicDBObject();
+    }
+
+    @Override
+    public void set(final String field, final NoSQLObject<BasicDBObject> value) {
+        this.mongoObject.append(field, value.unwrap());
+    }
+
+    @Override
+    public void set(final String field, final NoSQLObject<BasicDBObject>[] values) {
+        final BasicDBList list = new BasicDBList();
+        for (final NoSQLObject<BasicDBObject> value : values) {
+            list.add(value.unwrap());
+        }
+        this.mongoObject.append(field, list);
+    }
+
+    @Override
+    public void set(final String field, final Object value) {
+        this.mongoObject.append(field, value);
+    }
+
+    @Override
+    public void set(final String field, final Object[] values) {
+        final BasicDBList list = new BasicDBList();
+        Collections.addAll(list, values);
+        this.mongoObject.append(field, list);
+    }
+
+    @Override
+    public BasicDBObject unwrap() {
+        return this.mongoObject;
+    }
+}

Propchange: logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/db/nosql/mongo/MongoDBObject.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/db/nosql/mongo/MongoDBObject.java
------------------------------------------------------------------------------
    svn:keywords = Id

Added: logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/db/nosql/mongo/MongoDBProvider.java
URL: http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/db/nosql/mongo/MongoDBProvider.java?rev=1481026&view=auto
==============================================================================
--- logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/db/nosql/mongo/MongoDBProvider.java (added)
+++ logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/db/nosql/mongo/MongoDBProvider.java Fri May 10 14:32:03 2013
@@ -0,0 +1,226 @@
+/*
+ * 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.nosql.mongo;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.util.List;
+
+import org.apache.logging.log4j.Logger;
+import org.apache.logging.log4j.core.appender.db.nosql.NoSQLProvider;
+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.core.helpers.NameUtil;
+import org.apache.logging.log4j.status.StatusLogger;
+
+import com.mongodb.DB;
+import com.mongodb.MongoClient;
+import com.mongodb.ServerAddress;
+import com.mongodb.WriteConcern;
+
+/**
+ * The MongoDB implementation of {@link NoSQLProvider}.
+ */
+@Plugin(name = "MongoDb", category = "Core", printObject = true)
+public final class MongoDBProvider implements NoSQLProvider<MongoDBConnection> {
+    private static final Logger LOGGER = StatusLogger.getLogger();
+
+    /**
+     * Factory method for creating a MongoDB provider within the plugin manager.
+     * 
+     * @param collectionName
+     *            The name of the MongoDB collection to which log events should be written.
+     * @param writeConcernConstant
+     *            The {@link WriteConcern} constant to control writing details, defaults to
+     *            {@link WriteConcern#ACKNOWLEDGED}.
+     * @param writeConcernConstantClassName
+     *            The name of a class containing the aforementioned static WriteConcern constant. Defaults to
+     *            {@link WriteConcern}.
+     * @param databaseName
+     *            The name of the MongoDB database containing the collection to which log events should be written.
+     *            Mutually exclusive with {@code factoryClassName&factoryMethodName!=null}.
+     * @param server
+     *            The host name of the MongoDB server, defaults to localhost and mutually exclusive with
+     *            {@code factoryClassName&factoryMethodName!=null}.
+     * @param port
+     *            The port the MongoDB server is listening on, defaults to the default MongoDB port and mutually
+     *            exclusive with {@code factoryClassName&factoryMethodName!=null}.
+     * @param username
+     *            The username to authenticate against the MongoDB server with.
+     * @param password
+     *            The password to authenticate against the MongoDB server with.
+     * @param factoryClassName
+     *            A fully qualified class name containing a static factory method capable of returning a {@link DB} or a
+     *            {@link MongoClient}.
+     * @param factoryMethodName
+     *            The name of the public static factory method belonging to the aforementioned factory class.
+     * @return a new MongoDB provider.
+     */
+    @PluginFactory
+    public static MongoDBProvider createNoSQLProvider(@PluginAttr("collectionName") final String collectionName,
+            @PluginAttr("writeConcernConstant") final String writeConcernConstant,
+            @PluginAttr("writeConcernConstantClass") final String writeConcernConstantClassName,
+            @PluginAttr("databaseName") final String databaseName, @PluginAttr("server") final String server,
+            @PluginAttr("port") final String port, @PluginAttr("username") final String username,
+            @PluginAttr("password") final String password,
+            @PluginAttr("factoryClassName") final String factoryClassName,
+            @PluginAttr("factoryMethodName") final String factoryMethodName) {
+        DB database;
+        String description;
+        if (factoryClassName != null && factoryClassName.length() > 0 && factoryMethodName != null
+                && factoryMethodName.length() > 0) {
+            try {
+                final Class<?> factoryClass = Class.forName(factoryClassName);
+                final Method method = factoryClass.getMethod(factoryMethodName);
+                final Object object = method.invoke(null);
+
+                if (object instanceof DB) {
+                    database = (DB) object;
+                } else if (object instanceof MongoClient) {
+                    if (databaseName != null && databaseName.length() > 0) {
+                        database = ((MongoClient) object).getDB(databaseName);
+                    } else {
+                        LOGGER.error("The factory method [{}.{}()] returned a MongoClient so the database name is "
+                                + "required.", factoryClassName, factoryMethodName);
+                        return null;
+                    }
+                } else if (object == null) {
+                    LOGGER.error("The factory method [{}.{}()] returned null.", factoryClassName, factoryMethodName);
+                    return null;
+                } else {
+                    LOGGER.error("The factory method [{}.{}()] returned an unsupported type [{}].", factoryClassName,
+                            factoryMethodName, object.getClass().getName());
+                    return null;
+                }
+
+                description = "database=" + database.getName();
+                final List<ServerAddress> addresses = database.getMongo().getAllAddress();
+                if (addresses.size() == 1) {
+                    description += ", server=" + addresses.get(0).getHost() + ", port=" + addresses.get(0).getPort();
+                } else {
+                    description += ", servers=[";
+                    for (final ServerAddress address : addresses) {
+                        description += " { " + address.getHost() + ", " + address.getPort() + " } ";
+                    }
+                    description += "]";
+                }
+            } catch (final ClassNotFoundException e) {
+                LOGGER.error("The factory class [{}] could not be loaded.", factoryClassName, e);
+                return null;
+            } catch (final NoSuchMethodException e) {
+                LOGGER.error("The factory class [{}] does not have a no-arg method named [{}].", factoryClassName,
+                        factoryMethodName, e);
+                return null;
+            } catch (final Exception e) {
+                LOGGER.error("The factory method [{}.{}()] could not be invoked.", factoryClassName, factoryMethodName,
+                        e);
+                return null;
+            }
+        } else if (databaseName != null && databaseName.length() > 0) {
+            description = "database=" + databaseName;
+            try {
+                if (server != null && server.length() > 0) {
+                    int portInt = 0;
+                    if (port != null && port.length() > 0) {
+                        try {
+                            portInt = Integer.parseInt(port);
+                        } catch (final NumberFormatException ignore) { /* */
+                        }
+                    }
+
+                    description += ", server=" + server;
+                    if (portInt > 0) {
+                        description += ", port=" + portInt;
+                        database = new MongoClient(server, portInt).getDB(databaseName);
+                    } else {
+                        database = new MongoClient(server).getDB(databaseName);
+                    }
+                } else {
+                    database = new MongoClient().getDB(databaseName);
+                }
+            } catch (final Exception e) {
+                LOGGER.error("Failed to obtain a database instance from the MongoClient at server [{}] and "
+                        + "port [{}].", server, port);
+                return null;
+            }
+        } else {
+            LOGGER.error("No factory method was provided so the database name is required.");
+            return null;
+        }
+
+        if (!database.isAuthenticated()) {
+            if (username != null && username.length() > 0 && password != null && password.length() > 0) {
+                description += ", username=" + username + ", passwordHash="
+                        + NameUtil.md5(password + MongoDBProvider.class.getName());
+            } else {
+                LOGGER.error("The database is not already authenticated so you must supply a username and password "
+                        + "for the MongoDB provider.");
+                return null;
+            }
+        }
+
+        WriteConcern writeConcern;
+        if (writeConcernConstant != null && writeConcernConstant.length() > 0) {
+            if (writeConcernConstantClassName != null && writeConcernConstantClassName.length() > 0) {
+                try {
+                    final Class<?> writeConcernConstantClass = Class.forName(writeConcernConstantClassName);
+                    final Field field = writeConcernConstantClass.getField(writeConcernConstant);
+                    writeConcern = (WriteConcern) field.get(null);
+                } catch (final Exception e) {
+                    LOGGER.error("Write concern constant [{}.{}] not found, using default.",
+                            writeConcernConstantClassName, writeConcernConstant);
+                    writeConcern = WriteConcern.ACKNOWLEDGED;
+                }
+            } else {
+                writeConcern = WriteConcern.valueOf(writeConcernConstant);
+                if (writeConcern == null) {
+                    LOGGER.warn("Write concern constant [{}] not found, using default.", writeConcernConstant);
+                    writeConcern = WriteConcern.ACKNOWLEDGED;
+                }
+            }
+        } else {
+            writeConcern = WriteConcern.ACKNOWLEDGED;
+        }
+
+        return new MongoDBProvider(database, writeConcern, collectionName, description);
+    }
+
+    private final String collectionName;
+    private final DB database;
+    private final String description;
+
+    private final WriteConcern writeConcern;
+
+    private MongoDBProvider(final DB database, final WriteConcern writeConcern, final String collectionName,
+            final String description) {
+        this.database = database;
+        this.writeConcern = writeConcern;
+        this.collectionName = collectionName;
+        this.description = "mongoDb{ " + description + " }";
+    }
+
+    @Override
+    public MongoDBConnection getConnection() {
+        return new MongoDBConnection(this.database, this.writeConcern, this.collectionName);
+    }
+
+    @Override
+    public String toString() {
+        return this.description;
+    }
+}

Propchange: logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/db/nosql/mongo/MongoDBProvider.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/db/nosql/mongo/MongoDBProvider.java
------------------------------------------------------------------------------
    svn:keywords = Id

Added: logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/db/nosql/mongo/package-info.java
URL: http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/db/nosql/mongo/package-info.java?rev=1481026&view=auto
==============================================================================
--- logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/db/nosql/mongo/package-info.java (added)
+++ logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/db/nosql/mongo/package-info.java Fri May 10 14:32:03 2013
@@ -0,0 +1,21 @@
+/*
+ * 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.
+ */
+/**
+ * The classes in this package contain the MongoDB provider for the NoSQL Appender.
+ */
+package org.apache.logging.log4j.core.appender.db.nosql.mongo;
+

Propchange: logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/db/nosql/mongo/package-info.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/db/nosql/mongo/package-info.java
------------------------------------------------------------------------------
    svn:keywords = Id

Added: logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/db/nosql/package-info.java
URL: http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/db/nosql/package-info.java?rev=1481026&view=auto
==============================================================================
--- logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/db/nosql/package-info.java (added)
+++ logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/db/nosql/package-info.java Fri May 10 14:32:03 2013
@@ -0,0 +1,32 @@
+/*
+ * 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.
+ */
+/**
+ * The NoSQL Appender supports writing log events to NoSQL databases. The following NoSQL databases are currently
+ * supported. You can also easily extend this to support other NoSQL databases by implementing just three interfaces:
+ * {@link NoSQLObject}, {@link NoSQLConnection}, and {@link NoSQLProvider}. You will need the client library for your
+ * NoSQL database of choice on the classpath to use this appender; these Maven dependencies are optional and will not
+ * automatically be added to your classpath.<br>
+ * <br>
+ * <ul>
+ *     <li><a href="http://www.mongodb.org/" target="_blank">MongoDB</a>: org.mongodb:mongo-java-driver:2.11.1 or newer
+ *     must be on the classpath.</li>
+ *     <li><a href="http://couchdb.apache.org/" target="_blank">Apache CouchDB</a>: org.lightcouch:lightcouch:0.0.5 or
+ *     newer must be on the classpath.</li>
+ * </ul>
+ */
+package org.apache.logging.log4j.core.appender.db.nosql;
+

Propchange: logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/db/nosql/package-info.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/db/nosql/package-info.java
------------------------------------------------------------------------------
    svn:keywords = Id

Added: logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/db/package-info.java
URL: http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/db/package-info.java?rev=1481026&view=auto
==============================================================================
--- logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/db/package-info.java (added)
+++ logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/db/package-info.java Fri May 10 14:32:03 2013
@@ -0,0 +1,22 @@
+/*
+ * 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.
+ */
+/**
+ * The classes in this package and sub packages provide appenders for various types of databases and methods for
+ * accessing databases.
+ */
+package org.apache.logging.log4j.core.appender.db;
+

Propchange: logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/db/package-info.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/db/package-info.java
------------------------------------------------------------------------------
    svn:keywords = Id



Mime
View raw message