You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@logging.apache.org by gg...@apache.org on 2021/12/30 18:17:42 UTC

[logging-log4j2] branch master updated (e78db98 -> 409000d)

This is an automated email from the ASF dual-hosted git repository.

ggregory pushed a change to branch master
in repository https://gitbox.apache.org/repos/asf/logging-log4j2.git.


    from e78db98  Log4j 1.2 bridge LogManager class default constructor should be public.
     new 9b62808  Log4j 1.2 bridge interface org.apache.log4j.spi.RendererSupport was in the wrong package and incomplete.
     new 409000d  Log4j 1.2 bridge interface org.apache.log4j.spi.RendererSupport was in the wrong package and incomplete.

The 2 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 .../src/main/java/org/apache/log4j/Category.java   |  49 ++++--
 .../src/main/java/org/apache/log4j/LogManager.java |  12 +-
 .../java/org/apache/log4j/or/DefaultRenderer.java  |  32 ++--
 .../main/java/org/apache/log4j/or/RendererMap.java | 179 +++++++++++++++++++++
 .../java/org/apache/log4j/or/RendererSupport.java  |  26 ---
 .../spi/{ErrorCode.java => RendererSupport.java}   |  22 ++-
 .../spi/{ErrorCode.java => ThrowableRenderer.java} |  23 +--
 ...rrorCode.java => ThrowableRendererSupport.java} |  27 ++--
 ...rrorCode.java => TriggeringEventEvaluator.java} |  31 ++--
 src/changes/changes.xml                            |  14 +-
 10 files changed, 315 insertions(+), 100 deletions(-)
 copy log4j-core/src/main/java/org/apache/logging/log4j/core/lookup/Base64StrLookup.java => log4j-1.2-api/src/main/java/org/apache/log4j/or/DefaultRenderer.java (62%)
 create mode 100644 log4j-1.2-api/src/main/java/org/apache/log4j/or/RendererMap.java
 delete mode 100644 log4j-1.2-api/src/main/java/org/apache/log4j/or/RendererSupport.java
 copy log4j-1.2-api/src/main/java/org/apache/log4j/spi/{ErrorCode.java => RendererSupport.java} (68%)
 copy log4j-1.2-api/src/main/java/org/apache/log4j/spi/{ErrorCode.java => ThrowableRenderer.java} (69%)
 copy log4j-1.2-api/src/main/java/org/apache/log4j/spi/{ErrorCode.java => ThrowableRendererSupport.java} (64%)
 copy log4j-1.2-api/src/main/java/org/apache/log4j/spi/{ErrorCode.java => TriggeringEventEvaluator.java} (57%)

[logging-log4j2] 02/02: Log4j 1.2 bridge interface org.apache.log4j.spi.RendererSupport was in the wrong package and incomplete.

Posted by gg...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

ggregory pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/logging-log4j2.git

commit 409000d90bd3a3d40a8c701ade414d1656375219
Author: Gary Gregory <ga...@gmail.com>
AuthorDate: Thu Dec 30 13:17:39 2021 -0500

    Log4j 1.2 bridge interface org.apache.log4j.spi.RendererSupport was in
    the wrong package and incomplete.
    
    Log4j 1.2 bridge interfaces missing from package org.apache.log4j.spi:
    ThrowableRenderer, ThrowableRendererSupport, TriggeringEventEvaluator.
    
    Log4j 1.2 bridge missing class RendererMap.
---
 src/changes/changes.xml | 14 +++++++++++++-
 1 file changed, 13 insertions(+), 1 deletion(-)

diff --git a/src/changes/changes.xml b/src/changes/changes.xml
index 462cbc2..187d6bd 100644
--- a/src/changes/changes.xml
+++ b/src/changes/changes.xml
@@ -201,7 +201,19 @@
         Log4j 1.2 bridge method org.apache.log4j.Category.getDefaultHierarchy() is missing.
       </action>
       <action dev="ggregory" type="fix">
-        Log4j 1.2 bridge LogManager class default constructor should be public.
+        Log4j 1.2 bridge methods missing in org.apache.log4j.Category: getDefaultHierarchy(), getHierarchy(), getLoggerRepository().
+      </action>
+      <action dev="ggregory" type="fix">
+        Log4j 1.2 bridge class LogManager default constructor should be public.
+      </action>
+      <action dev="ggregory" type="fix">
+        Log4j 1.2 bridge interface org.apache.log4j.spi.RendererSupport was in the wrong package and incomplete.
+      </action>
+      <action dev="ggregory" type="fix">
+        Log4j 1.2 bridge interfaces missing from package org.apache.log4j.spi: ThrowableRenderer, ThrowableRendererSupport, TriggeringEventEvaluator.
+      </action>
+      <action dev="ggregory" type="fix">
+        Log4j 1.2 bridge missing class org.apache.log4j.or.RendererMap.
       </action>
     </release>
     <release version="2.17.1" date="2021-MM-DD" description="GA Release 2.17.1">

[logging-log4j2] 01/02: Log4j 1.2 bridge interface org.apache.log4j.spi.RendererSupport was in the wrong package and incomplete.

Posted by gg...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

ggregory pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/logging-log4j2.git

commit 9b628088307bab42a06c78f30641a140d954b376
Author: Gary Gregory <ga...@gmail.com>
AuthorDate: Thu Dec 30 13:14:59 2021 -0500

    Log4j 1.2 bridge interface org.apache.log4j.spi.RendererSupport was in
    the wrong package and incomplete.
    
    Log4j 1.2 bridge interfaces missing from package org.apache.log4j.spi:
    ThrowableRenderer, ThrowableRendererSupport, TriggeringEventEvaluator.
    
    Log4j 1.2 bridge missing class RendererMap.
---
 .../src/main/java/org/apache/log4j/Category.java   |  49 ++++--
 .../src/main/java/org/apache/log4j/LogManager.java |  12 +-
 .../java/org/apache/log4j/or/DefaultRenderer.java  |  40 +++++
 .../main/java/org/apache/log4j/or/RendererMap.java | 179 +++++++++++++++++++++
 .../apache/log4j/{or => spi}/RendererSupport.java  |  29 ++--
 .../org/apache/log4j/spi/ThrowableRenderer.java    |  34 ++++
 .../apache/log4j/spi/ThrowableRendererSupport.java |  38 +++++
 .../apache/log4j/spi/TriggeringEventEvaluator.java |  40 +++++
 8 files changed, 396 insertions(+), 25 deletions(-)

diff --git a/log4j-1.2-api/src/main/java/org/apache/log4j/Category.java b/log4j-1.2-api/src/main/java/org/apache/log4j/Category.java
index ef913ae..8438243 100644
--- a/log4j-1.2-api/src/main/java/org/apache/log4j/Category.java
+++ b/log4j-1.2-api/src/main/java/org/apache/log4j/Category.java
@@ -26,22 +26,22 @@ import java.util.concurrent.ConcurrentMap;
 import org.apache.log4j.helpers.NullEnumeration;
 import org.apache.log4j.legacy.core.CategoryUtil;
 import org.apache.log4j.or.ObjectRenderer;
-import org.apache.log4j.or.RendererSupport;
+import org.apache.log4j.or.RendererMap;
 import org.apache.log4j.spi.AppenderAttachable;
 import org.apache.log4j.spi.LoggerFactory;
 import org.apache.log4j.spi.LoggerRepository;
 import org.apache.log4j.spi.LoggingEvent;
-import org.apache.logging.log4j.message.MapMessage;
-import org.apache.logging.log4j.message.SimpleMessage;
-import org.apache.logging.log4j.spi.ExtendedLogger;
-import org.apache.logging.log4j.spi.LoggerContext;
+import org.apache.log4j.spi.RendererSupport;
 import org.apache.logging.log4j.message.LocalizedMessage;
+import org.apache.logging.log4j.message.MapMessage;
 import org.apache.logging.log4j.message.Message;
 import org.apache.logging.log4j.message.ObjectMessage;
+import org.apache.logging.log4j.message.SimpleMessage;
 import org.apache.logging.log4j.spi.AbstractLoggerAdapter;
+import org.apache.logging.log4j.spi.ExtendedLogger;
+import org.apache.logging.log4j.spi.LoggerContext;
 import org.apache.logging.log4j.util.Strings;
 
-
 /**
  * Implementation of the Category class for compatibility, despite it having been deprecated a long, long time ago.
  */
@@ -56,7 +56,7 @@ public class Category implements AppenderAttachable {
 
     private static final boolean isCoreAvailable;
 
-    private final Map<Class<?>, ObjectRenderer> rendererMap;
+    private final RendererMap rendererMap;
 
     static {
         boolean available;
@@ -76,14 +76,18 @@ public class Category implements AppenderAttachable {
 
     private final org.apache.logging.log4j.Logger logger;
 
+    /** Categories need to know what Hierarchy they are in. */
+    protected LoggerRepository repository;
+
     /**
      * Constructor used by Logger to specify a LoggerContext.
      * @param context The LoggerContext.
      * @param name The name of the Logger.
      */
     protected Category(final LoggerContext context, final String name) {
-        this.logger = context.getLogger(name);
-        rendererMap = ((RendererSupport) LogManager.getLoggerRepository()).getRendererMap();
+        logger = context.getLogger(name);
+        repository = LogManager.getLoggerRepository();
+        rendererMap = ((RendererSupport) repository).getRendererMap();
     }
 
     /**
@@ -228,6 +232,26 @@ public class Category implements AppenderAttachable {
         }
     }
 
+    /**
+     * Gets the the {@link LoggerRepository} where this <code>Category</code> instance is attached.
+     * 
+     * @deprecated Please use {@link #getLoggerRepository()} instead.
+     * @since 1.1
+     */
+    @Deprecated
+    public LoggerRepository getHierarchy() {
+        return repository;
+    }
+
+    /**
+     * Gets the the {@link LoggerRepository} where this <code>Category</code> is attached.
+     * 
+     * @since 1.2
+     */
+    public LoggerRepository getLoggerRepository() {
+        return repository;
+    }
+
     public final Priority getChainedPriority() {
         return getEffectiveLevel();
     }
@@ -444,6 +468,13 @@ public class Category implements AppenderAttachable {
         }
     }
 
+    /**
+     * Only the Hiearchy class can set the hiearchy of a category. Default package access is MANDATORY here.
+     */
+    final void setHierarchy(LoggerRepository repository) {
+        this.repository = repository;
+    }
+
     public void setResourceBundle(final ResourceBundle bundle) {
         this.bundle = bundle;
     }
diff --git a/log4j-1.2-api/src/main/java/org/apache/log4j/LogManager.java b/log4j-1.2-api/src/main/java/org/apache/log4j/LogManager.java
index d7d4018..5ef657e 100644
--- a/log4j-1.2-api/src/main/java/org/apache/log4j/LogManager.java
+++ b/log4j-1.2-api/src/main/java/org/apache/log4j/LogManager.java
@@ -23,10 +23,11 @@ import java.util.Map;
 import org.apache.log4j.helpers.NullEnumeration;
 import org.apache.log4j.legacy.core.ContextUtil;
 import org.apache.log4j.or.ObjectRenderer;
-import org.apache.log4j.or.RendererSupport;
+import org.apache.log4j.or.RendererMap;
 import org.apache.log4j.spi.HierarchyEventListener;
 import org.apache.log4j.spi.LoggerFactory;
 import org.apache.log4j.spi.LoggerRepository;
+import org.apache.log4j.spi.RendererSupport;
 import org.apache.log4j.spi.RepositorySelector;
 import org.apache.logging.log4j.spi.LoggerContext;
 import org.apache.logging.log4j.util.Strings;
@@ -149,10 +150,10 @@ public final class LogManager {
      */
     private static class Repository implements LoggerRepository, RendererSupport {
 
-        private final Map<Class<?>, ObjectRenderer> rendererMap = new HashMap<>();
+        private final RendererMap rendererMap = new RendererMap();
 
         @Override
-        public Map<Class<?>, ObjectRenderer> getRendererMap() {
+        public RendererMap getRendererMap() {
             return rendererMap;
         }
 
@@ -229,6 +230,11 @@ public final class LogManager {
         @Override
         public void resetConfiguration() {
         }
+
+        @Override
+        public void setRenderer(Class renderedClass, ObjectRenderer renderer) {
+            rendererMap.put(renderedClass, renderer);
+        }
     }
 
     /**
diff --git a/log4j-1.2-api/src/main/java/org/apache/log4j/or/DefaultRenderer.java b/log4j-1.2-api/src/main/java/org/apache/log4j/or/DefaultRenderer.java
new file mode 100644
index 0000000..e8f6321
--- /dev/null
+++ b/log4j-1.2-api/src/main/java/org/apache/log4j/or/DefaultRenderer.java
@@ -0,0 +1,40 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.log4j.or;
+
+/**
+ * The default ObjectRenderer renders objects by calling their {@code toString()} method.
+ * 
+ * @since 1.0
+ */
+class DefaultRenderer implements ObjectRenderer {
+
+    DefaultRenderer() {
+    }
+
+    /**
+     * Render the object passed as parameter by calling its {@code toString()} method.
+     */
+    public String doRender(final Object o) {
+        try {
+            return o.toString();
+        } catch (Exception ex) {
+            return ex.toString();
+        }
+    }
+}
diff --git a/log4j-1.2-api/src/main/java/org/apache/log4j/or/RendererMap.java b/log4j-1.2-api/src/main/java/org/apache/log4j/or/RendererMap.java
new file mode 100644
index 0000000..b70b1a5
--- /dev/null
+++ b/log4j-1.2-api/src/main/java/org/apache/log4j/or/RendererMap.java
@@ -0,0 +1,179 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.log4j.or;
+
+import java.util.Hashtable;
+
+import org.apache.log4j.helpers.OptionConverter;
+import org.apache.log4j.spi.RendererSupport;
+import org.apache.logging.log4j.core.util.Loader;
+import org.apache.logging.log4j.status.StatusLogger;
+
+/**
+ * Map class objects to an {@link ObjectRenderer}.
+ * 
+ * @author Ceki G&uuml;lc&uuml;
+ * @since version 1.0
+ */
+public class RendererMap {
+
+    Hashtable map;
+
+    static ObjectRenderer defaultRenderer = new DefaultRenderer();
+
+    public RendererMap() {
+        map = new Hashtable();
+    }
+
+    /**
+     * Add a renderer to a hierarchy passed as parameter.
+     */
+    static public void addRenderer(RendererSupport repository, String renderedClassName, String renderingClassName) {
+        StatusLogger.getLogger().debug("Rendering class: [" + renderingClassName + "], Rendered class: [" + renderedClassName + "].");
+        ObjectRenderer renderer = (ObjectRenderer) OptionConverter.instantiateByClassName(renderingClassName, ObjectRenderer.class, null);
+        if (renderer == null) {
+            StatusLogger.getLogger().error("Could not instantiate renderer [" + renderingClassName + "].");
+            return;
+        }
+        try {
+            Class renderedClass = Loader.loadClass(renderedClassName);
+            repository.setRenderer(renderedClass, renderer);
+        } catch (ClassNotFoundException e) {
+            StatusLogger.getLogger().error("Could not find class [" + renderedClassName + "].", e);
+        }
+    }
+
+    /**
+     * Find the appropriate renderer for the class type of the <code>o</code> parameter. This is accomplished by calling the
+     * {@link #get(Class)} method. Once a renderer is found, it is applied on the object <code>o</code> and the result is
+     * returned as a {@link String}.
+     */
+    public String findAndRender(Object o) {
+        if (o == null)
+            return null;
+        else
+            return get(o.getClass()).doRender(o);
+    }
+
+    /**
+     * Syntactic sugar method that calls {@link #get(Class)} with the class of the object parameter.
+     */
+    public ObjectRenderer get(Object o) {
+        if (o == null)
+            return null;
+        else
+            return get(o.getClass());
+    }
+
+    /**
+     * Search the parents of <code>clazz</code> for a renderer. The renderer closest in the hierarchy will be returned. If
+     * no renderers could be found, then the default renderer is returned.
+     * 
+     * <p>
+     * The search first looks for a renderer configured for <code>clazz</code>. If a renderer could not be found, then the
+     * search continues by looking at all the interfaces implemented by <code>clazz</code> including the super-interfaces of
+     * each interface. If a renderer cannot be found, then the search looks for a renderer defined for the parent
+     * (superclass) of <code>clazz</code>. If that fails, then all the interfaces implemented by the parent of
+     * <code>clazz</code> are searched and so on.
+     * 
+     * <p>
+     * For example, if A0, A1, A2 are classes and X0, X1, X2, Y0, Y1 are interfaces where A2 extends A1 which in turn
+     * extends A0 and similarly X2 extends X1 which extends X0 and Y1 extends Y0. Let us also assume that A1 implements the
+     * Y0 interface and that A2 implements the X2 interface.
+     * 
+     * <p>
+     * The table below shows the results returned by the <code>get(A2.class)</code> method depending on the renderers added
+     * to the map.
+     * 
+     * <p>
+     * <table border="1">
+     * <tr>
+     * <th>Added renderers</th>
+     * <th>Value returned by <code>get(A2.class)</code></th>
+     * 
+     * <tr>
+     * <td><code>A0Renderer</code>
+     * <td align="center"><code>A0Renderer</code>
+     * 
+     * <tr>
+     * <td><code>A0Renderer, A1Renderer</code>
+     * <td align="center"><code>A1Renderer</code>
+     * 
+     * <tr>
+     * <td><code>X0Renderer</code>
+     * <td align="center"><code>X0Renderer</code>
+     * 
+     * <tr>
+     * <td><code>A1Renderer, X0Renderer</code>
+     * <td align="center"><code>X0Renderer</code>
+     * 
+     * </table>
+     * 
+     * <p>
+     * This search algorithm is not the most natural, although it is particularly easy to implement. Future log4j versions
+     * <em>may</em> implement a more intuitive search algorithm. However, the present algorithm should be acceptable in the
+     * vast majority of circumstances.
+     * 
+     */
+    public ObjectRenderer get(Class clazz) {
+        // System.out.println("\nget: "+clazz);
+        ObjectRenderer r = null;
+        for (Class c = clazz; c != null; c = c.getSuperclass()) {
+            // System.out.println("Searching for class: "+c);
+            r = (ObjectRenderer) map.get(c);
+            if (r != null) {
+                return r;
+            }
+            r = searchInterfaces(c);
+            if (r != null)
+                return r;
+        }
+        return defaultRenderer;
+    }
+
+    ObjectRenderer searchInterfaces(Class c) {
+        // System.out.println("Searching interfaces of class: "+c);
+
+        ObjectRenderer r = (ObjectRenderer) map.get(c);
+        if (r != null) {
+            return r;
+        }
+        Class[] ia = c.getInterfaces();
+        for (int i = 0; i < ia.length; i++) {
+            r = searchInterfaces(ia[i]);
+            if (r != null)
+                return r;
+        }
+        return null;
+    }
+
+    public ObjectRenderer getDefaultRenderer() {
+        return defaultRenderer;
+    }
+
+    public void clear() {
+        map.clear();
+    }
+
+    /**
+     * Register an {@link ObjectRenderer} for <code>clazz</code>.
+     */
+    public void put(Class clazz, ObjectRenderer or) {
+        map.put(clazz, or);
+    }
+}
diff --git a/log4j-1.2-api/src/main/java/org/apache/log4j/or/RendererSupport.java b/log4j-1.2-api/src/main/java/org/apache/log4j/spi/RendererSupport.java
similarity index 50%
rename from log4j-1.2-api/src/main/java/org/apache/log4j/or/RendererSupport.java
rename to log4j-1.2-api/src/main/java/org/apache/log4j/spi/RendererSupport.java
index 9b8728d..0a0b740 100644
--- a/log4j-1.2-api/src/main/java/org/apache/log4j/or/RendererSupport.java
+++ b/log4j-1.2-api/src/main/java/org/apache/log4j/spi/RendererSupport.java
@@ -1,26 +1,29 @@
 /*
  * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
+ * 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 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
- *
+ * 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.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
  */
-package org.apache.log4j.or;
 
-import java.util.Map;
+package org.apache.log4j.spi;
+
+import org.apache.log4j.or.ObjectRenderer;
+import org.apache.log4j.or.RendererMap;
 
-/**
- * Interface that indicates the Renderer Map is available. This interface differs
- */
 public interface RendererSupport {
-    Map<Class<?>, ObjectRenderer> getRendererMap();
+
+    public RendererMap getRendererMap();
+
+    public void setRenderer(Class renderedClass, ObjectRenderer renderer);
+
 }
diff --git a/log4j-1.2-api/src/main/java/org/apache/log4j/spi/ThrowableRenderer.java b/log4j-1.2-api/src/main/java/org/apache/log4j/spi/ThrowableRenderer.java
new file mode 100644
index 0000000..e2e87a1
--- /dev/null
+++ b/log4j-1.2-api/src/main/java/org/apache/log4j/spi/ThrowableRenderer.java
@@ -0,0 +1,34 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.log4j.spi;
+
+/**
+ * Implemented by classes that render instances of java.lang.Throwable (exceptions and errors) into a string
+ * representation.
+ *
+ * @since 1.2.16
+ */
+public interface ThrowableRenderer {
+
+    /**
+     * Render Throwable.
+     * 
+     * @param t throwable, may not be null.
+     * @return String representation.
+     */
+    public String[] doRender(Throwable t);
+}
diff --git a/log4j-1.2-api/src/main/java/org/apache/log4j/spi/ThrowableRendererSupport.java b/log4j-1.2-api/src/main/java/org/apache/log4j/spi/ThrowableRendererSupport.java
new file mode 100644
index 0000000..37b17e0
--- /dev/null
+++ b/log4j-1.2-api/src/main/java/org/apache/log4j/spi/ThrowableRendererSupport.java
@@ -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.log4j.spi;
+
+/**
+ * Implemented by logger repositories that support configurable rendering of Throwables.
+ *
+ * @since 1.2.16
+ */
+public interface ThrowableRendererSupport {
+    /**
+     * Get throwable renderer.
+     * 
+     * @return throwable renderer, may be null.
+     */
+    ThrowableRenderer getThrowableRenderer();
+
+    /**
+     * Set throwable renderer.
+     * 
+     * @param renderer renderer, may be null.
+     */
+    void setThrowableRenderer(ThrowableRenderer renderer);
+}
diff --git a/log4j-1.2-api/src/main/java/org/apache/log4j/spi/TriggeringEventEvaluator.java b/log4j-1.2-api/src/main/java/org/apache/log4j/spi/TriggeringEventEvaluator.java
new file mode 100644
index 0000000..96e86af
--- /dev/null
+++ b/log4j-1.2-api/src/main/java/org/apache/log4j/spi/TriggeringEventEvaluator.java
@@ -0,0 +1,40 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.log4j.spi;
+
+/**
+ * Implementors decide when to perform an appender specific action.
+ * 
+ * <p>
+ * For example, the {@code org.apache.log4j.net.SMTPAppender} sends an email when the
+ * {@link #isTriggeringEvent(LoggingEvent)} method returns {@code true} and adds the event to an internal buffer when
+ * the returned result is {@code false}.
+ * </p>
+ * 
+ * @since version 1.0
+ */
+public interface TriggeringEventEvaluator {
+
+    /**
+     * Tests if this the triggering event.
+     * 
+     * @param event The vent to test.
+     * @return Whether this the triggering event.
+     */
+    public boolean isTriggeringEvent(LoggingEvent event);
+}