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 <garydgreg...@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ülcü + * @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); +}