Added documentation and example on how to extend log4cxx
diff --git a/src/examples/cpp/CMakeLists.txt b/src/examples/cpp/CMakeLists.txt
index 05614b3..4677ebb 100644
--- a/src/examples/cpp/CMakeLists.txt
+++ b/src/examples/cpp/CMakeLists.txt
@@ -1,4 +1,4 @@
-set(ALL_LOG4CXX_EXAMPLES console delayedloop stream trivial)
+set(ALL_LOG4CXX_EXAMPLES console delayedloop stream trivial custom-appender)
 
 foreach(exampleName IN LISTS ALL_LOG4CXX_EXAMPLES)
     add_executable(${exampleName} ${exampleName}.cpp)
@@ -6,3 +6,7 @@
     target_include_directories(${exampleName} PRIVATE ${CMAKE_CURRENT_LIST_DIR} $<TARGET_PROPERTY:log4cxx,INCLUDE_DIRECTORIES>)
     target_link_libraries(${exampleName} PRIVATE log4cxx ${APR_UTIL_LIBRARIES} ${XMLLIB_LIBRARIES} ${APR_LIBRARIES} ${APR_SYSTEM_LIBS})
 endforeach()
+
+configure_file( custom-appender.xml
+    ${CMAKE_CURRENT_BINARY_DIR}/custom-appender.xml
+    COPYONLY )
diff --git a/src/examples/cpp/custom-appender.cpp b/src/examples/cpp/custom-appender.cpp
new file mode 100644
index 0000000..5154090
--- /dev/null
+++ b/src/examples/cpp/custom-appender.cpp
@@ -0,0 +1,71 @@
+/*
+ * 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.
+ */
+
+#include <stdlib.h>
+#include <log4cxx/basicconfigurator.h>
+#include <log4cxx/helpers/object.h>
+#include <log4cxx/appenderskeleton.h>
+#include <log4cxx/helpers/stringhelper.h>
+#include <log4cxx/xml/domconfigurator.h>
+
+namespace log4cxx {
+
+class NullWriterAppender : public log4cxx::AppenderSkeleton {
+public:
+	DECLARE_LOG4CXX_OBJECT(NullWriterAppender)
+	BEGIN_LOG4CXX_CAST_MAP()
+	LOG4CXX_CAST_ENTRY(NullWriterAppender)
+	LOG4CXX_CAST_ENTRY_CHAIN(AppenderSkeleton)
+	END_LOG4CXX_CAST_MAP()
+
+	NullWriterAppender(){}
+
+	virtual void close(){}
+
+	virtual bool requiresLayout() const {
+		return false;
+	}
+
+	virtual void append(const spi::LoggingEventPtr& event, log4cxx::helpers::Pool& p){
+		// This gets called whenever there is a valid event for our appender.
+	}
+
+	virtual void activateOptions(log4cxx::helpers::Pool& /* pool */) {
+		// Given all of our options, do something useful(e.g. open a file)
+	}
+
+	virtual void setOption(const LogString& option, const LogString& value){
+		if (helpers::StringHelper::equalsIgnoreCase(option,
+										   LOG4CXX_STR("SOMEVALUE"), LOG4CXX_STR("somevalue"))){
+			// Do something with the 'value' here.
+		}
+	}
+};
+
+IMPLEMENT_LOG4CXX_OBJECT(NullWriterAppender)
+
+}
+
+int main( int argc, char** argv ){
+	log4cxx::xml::DOMConfigurator::configure( "custom-appender.xml" );
+
+	log4cxx::LoggerPtr rootLogger = log4cxx::Logger::getRootLogger();
+	log4cxx::LoggerPtr nullLogger = log4cxx::Logger::getLogger( "NullLogger" );
+
+	LOG4CXX_INFO( rootLogger, "This is some root message" );
+	LOG4CXX_INFO( nullLogger, "This message will be discarded" );
+}
diff --git a/src/examples/cpp/custom-appender.xml b/src/examples/cpp/custom-appender.xml
new file mode 100644
index 0000000..f7b40e8
--- /dev/null
+++ b/src/examples/cpp/custom-appender.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">
+  <appender name="ConsoleAppender" class="org.apache.log4j.ConsoleAppender">
+    <param name="Target" value="System.out"/>
+    <layout class="org.apache.log4j.PatternLayout">
+      <param name="ConversionPattern" value="[%d{yyyy-MM-dd HH:mm:ss}] %c %-5p - %m%n"/>
+    </layout>
+  </appender>
+
+  <appender name="NullAppender" class="NullWriterAppender">
+    <param name="SomeValue" value="Nothing"/>
+  </appender>
+
+  <root>
+     <priority value="info" />
+     <appender-ref ref="ConsoleAppender"/>
+  </root>
+
+  <logger name="NullLogger" additivity="false">
+     <appender-ref ref="NullAppender"/>
+  </logger>
+</log4j:configuration>
diff --git a/src/site/markdown/1-usage.md b/src/site/markdown/1-usage.md
index bdc3adb..97ccaef 100644
--- a/src/site/markdown/1-usage.md
+++ b/src/site/markdown/1-usage.md
@@ -24,5 +24,6 @@
 See the following pages for usage information:
 
 * @subpage usage
+* @subpage extending-log4cxx
 * @subpage faq
 * @subpage configuration-samples
diff --git a/src/site/markdown/extending.md b/src/site/markdown/extending.md
new file mode 100644
index 0000000..ede583f
--- /dev/null
+++ b/src/site/markdown/extending.md
@@ -0,0 +1,141 @@
+Extending Log4cxx {#extending-log4cxx}
+===
+<!--
+ Note: License header cannot be first, as doxygen does not generate
+ cleanly if it before the '==='
+-->
+<!--
+ 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.
+-->
+
+Sometimes, you may want to extend log4cxx, for example by creating
+a new appender to write out data in a new format.  The following
+guide shows how you can extend log4cxx in order to add a new appender.
+
+The full sample application can be found in the src/examples/cpp
+directory.
+
+The first thing for our example is to create a class that extends
+log4cxx.AppenderSkeleton so that we don't need to implement all of
+the virtual methods that are defined in log4cxx.Appender:
+
+~~~{.cpp}
+namespace log4cxx {
+
+class NullWriterAppender : public log4cxx::AppenderSkeleton {
+};
+
+}
+~~~
+
+Next, we need to add in a few macros in order to properly register
+our new appender with log4cxx:
+
+~~~{.cpp}
+namespace log4cxx {
+
+class NullWriterAppender : public log4cxx::AppenderSkeleton {
+public:
+	DECLARE_LOG4CXX_OBJECT(NullWriterAppender)
+	BEGIN_LOG4CXX_CAST_MAP()
+	LOG4CXX_CAST_ENTRY(NullWriterAppender)
+	LOG4CXX_CAST_ENTRY_CHAIN(AppenderSkeleton)
+	END_LOG4CXX_CAST_MAP()
+
+};
+
+IMPLEMENT_LOG4CXX_OBJECT(NullWriterAppender)
+
+}
+~~~
+
+These macros tell log4cxx what the name of our class is, as well as giving
+log4cxx a way of instansiating our class.  Without these macros, the custom
+class will not work.
+
+Now, let's add some basic functionality to our class.  As the name of
+our class implies, we are going to do nothing with our appender here, as
+this is just an example.  To that end, we need to implement the following:
+1. Default constructor
+2. `close` method
+3. `requiresLayout` method
+4. `append` method, which does the actual writing of the log event
+5. `activateOptions`, which causes the class to reconfigure itself
+6. `setOption`, which gets called whenever we get an option in a config file
+
+These are basically stub methods, with a few comments on their use:
+
+~~~{.cpp}
+	NullWriterAppender(){}
+
+	virtual void close(){}
+
+	virtual bool requiresLayout() const {
+		return false;
+	}
+
+	virtual void append(const spi::LoggingEventPtr& event, log4cxx::helpers::Pool& p){
+		// This gets called whenever there is a valid event for our appender.
+	}
+
+	virtual void activateOptions(log4cxx::helpers::Pool& /* pool */) {
+		// Given all of our options, do something useful(e.g. open a file)
+	}
+
+	virtual void setOption(const LogString& option, const LogString& value){
+		if (helpers::StringHelper::equalsIgnoreCase(option,
+			   LOG4CXX_STR("SOMEVALUE"), LOG4CXX_STR("somevalue"))){
+			// Do something with the 'value' here.
+		}
+	}
+~~~
+
+At this point, we now have a fully functioning(if useless) custom appender.  We can now
+refer to this appender in our configuration file like so:
+
+~~~{.xml}
+<?xml version="1.0" encoding="UTF-8" ?>
+<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">
+  <appender name="ConsoleAppender" class="org.apache.log4j.ConsoleAppender">
+    <param name="Target" value="System.out"/>
+    <layout class="org.apache.log4j.PatternLayout">
+      <param name="ConversionPattern" value="[%d{yyyy-MM-dd HH:mm:ss}] %c %-5p - %m%n"/>
+    </layout>
+  </appender>
+
+  <appender name="NullAppender" class="NullWriterAppender">
+    <param name="SomeValue" value="Nothing"/>
+  </appender>
+
+  <root>
+     <priority value="info" />
+     <appender-ref ref="ConsoleAppender"/>
+  </root>
+
+  <logger name="NullLogger" additivity="false">
+     <appender-ref ref="NullAppender"/>
+  </logger>
+</log4j:configuration>
+~~~
+
+When log4cxx is configured, any messages that go to the `NullLogger` will
+then be forwarded on to the `NullWriterAppender`.
+
+This same technique can be used to add new classes of many different kinds
+to log4cxx, including(but not limited to):
+* [Appenders](@ref log4cxx.Appender)
+* [Layouts](@ref log4cxx.Layout)
+* [Filters](@ref log4cxx.spi.Filter)