org.apache.log4j.or.RendererMap Maven / Gradle / Ivy
Show all versions of reload4j Show documentation
/*
* 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 org.apache.log4j.spi.RendererSupport;
import org.apache.log4j.helpers.LogLog;
import org.apache.log4j.helpers.Loader;
import org.apache.log4j.helpers.OptionConverter;
import java.util.Hashtable;
/**
* 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) {
LogLog.debug("Rendering class: [" + renderingClassName + "], Rendered class: [" + renderedClassName + "].");
ObjectRenderer renderer = (ObjectRenderer) OptionConverter.instantiateByClassName(renderingClassName,
ObjectRenderer.class, null);
if (renderer == null) {
LogLog.error("Could not instantiate renderer [" + renderingClassName + "].");
return;
} else {
try {
Class renderedClass = Loader.loadClass(renderedClassName);
repository.setRenderer(renderedClass, renderer);
} catch (ClassNotFoundException e) {
LogLog.error("Could not find class [" + renderedClassName + "].", e);
}
}
}
/**
* Find the appropriate renderer for the class type of the o
* parameter. This is accomplished by calling the {@link #get(Class)} method.
* Once a renderer is found, it is applied on the object o
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 clazz
for a renderer. The renderer closest
* in the hierarchy will be returned. If no renderers could be found, then the
* default renderer is returned.
*
*
* The search first looks for a renderer configured for clazz
. If a
* renderer could not be found, then the search continues by looking at all the
* interfaces implemented by clazz
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 clazz
. If that
* fails, then all the interfaces implemented by the parent of
* clazz
are searched and so on.
*
*
* 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.
*
*
* The table below shows the results returned by the get(A2.class)
* method depending on the renderers added to the map.
*
*
*
*
* Added renderers
* Value returned by get(A2.class)
*
*
* A0Renderer
* A0Renderer
*
*
* A0Renderer, A1Renderer
* A1Renderer
*
*
* X0Renderer
* X0Renderer
*
*
* A1Renderer, X0Renderer
* X0Renderer
*
*
*
*
* This search algorithm is not the most natural, although it is particularly
* easy to implement. Future log4j versions may 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;
} else {
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 clazz
.
*/
public void put(Class clazz, ObjectRenderer or) {
map.put(clazz, or);
}
}