X-Git-Url: http://source.jalview.org/gitweb/?a=blobdiff_plain;ds=sidebyside;f=srcjar_unused%2Forg%2Fapache%2Flog4j%2FHierarchy.java;fp=srcjar_unused%2Forg%2Fapache%2Flog4j%2FHierarchy.java;h=6c82c98ff1cd777476573c1e2f5d46af8370138e;hb=4f30214e8098748469c6a4269ac2ed6c5750e4b0;hp=0000000000000000000000000000000000000000;hpb=9dabc02511e3a334a5749a504f57f69d6c9017bd;p=jalview.git diff --git a/srcjar_unused/org/apache/log4j/Hierarchy.java b/srcjar_unused/org/apache/log4j/Hierarchy.java new file mode 100644 index 0000000..6c82c98 --- /dev/null +++ b/srcjar_unused/org/apache/log4j/Hierarchy.java @@ -0,0 +1,578 @@ +/* + * 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. + */ + +// WARNING This class MUST not have references to the Category or +// WARNING RootCategory classes in its static initiliazation neither +// WARNING directly nor indirectly. + +// Contributors: +// Luke Blanshard +// Mario Schomburg - IBM Global Services/Germany +// Anders Kristensen +// Igor Poteryaev + +package org.apache.log4j; + + +import java.util.Hashtable; +import java.util.Enumeration; +import java.util.Vector; + +import org.apache.log4j.spi.LoggerFactory; +import org.apache.log4j.spi.HierarchyEventListener; +import org.apache.log4j.spi.LoggerRepository; +import org.apache.log4j.spi.RendererSupport; +import org.apache.log4j.or.RendererMap; +import org.apache.log4j.or.ObjectRenderer; +import org.apache.log4j.helpers.LogLog; +import org.apache.log4j.spi.ThrowableRendererSupport; +import org.apache.log4j.spi.ThrowableRenderer; + +/** + This class is specialized in retrieving loggers by name and also + maintaining the logger hierarchy. + +

The casual user does not have to deal with this class + directly. + +

The structure of the logger hierarchy is maintained by the + {@link #getLogger} method. The hierarchy is such that children link + to their parent but parents do not have any pointers to their + children. Moreover, loggers can be instantiated in any order, in + particular descendant before ancestor. + +

In case a descendant is created before a particular ancestor, + then it creates a provision node for the ancestor and adds itself + to the provision node. Other descendants of the same ancestor add + themselves to the previously created provision node. + + @author Ceki Gülcü + +*/ +public class Hierarchy implements LoggerRepository, RendererSupport, ThrowableRendererSupport { + + private LoggerFactory defaultFactory; + private Vector listeners; + + Hashtable ht; + Logger root; + RendererMap rendererMap; + + int thresholdInt; + Level threshold; + + boolean emittedNoAppenderWarning = false; + boolean emittedNoResourceBundleWarning = false; + + private ThrowableRenderer throwableRenderer = null; + + /** + Create a new logger hierarchy. + + @param root The root of the new hierarchy. + + */ + public + Hierarchy(Logger root) { + ht = new Hashtable(); + listeners = new Vector(1); + this.root = root; + // Enable all level levels by default. + setThreshold(Level.ALL); + this.root.setHierarchy(this); + rendererMap = new RendererMap(); + defaultFactory = new DefaultCategoryFactory(); + } + + /** + Add an object renderer for a specific class. + */ + public + void addRenderer(Class classToRender, ObjectRenderer or) { + rendererMap.put(classToRender, or); + } + + public + void addHierarchyEventListener(HierarchyEventListener listener) { + if(listeners.contains(listener)) { + LogLog.warn("Ignoring attempt to add an existent listener."); + } else { + listeners.addElement(listener); + } + } + + /** + This call will clear all logger definitions from the internal + hashtable. Invoking this method will irrevocably mess up the + logger hierarchy. + +

You should really know what you are doing before + invoking this method. + + @since 0.9.0 */ + public + void clear() { + //System.out.println("\n\nAbout to clear internal hash table."); + ht.clear(); + } + + public + void emitNoAppenderWarning(Category cat) { + // No appenders in hierarchy, warn user only once. + if(!this.emittedNoAppenderWarning) { + LogLog.warn("No appenders could be found for logger (" + + cat.getName() + ")."); + LogLog.warn("Please initialize the log4j system properly."); + LogLog.warn("See http://logging.apache.org/log4j/1.2/faq.html#noconfig for more info."); + this.emittedNoAppenderWarning = true; + } + } + + /** + Check if the named logger exists in the hierarchy. If so return + its reference, otherwise returns null. + + @param name The name of the logger to search for. + + */ + public + Logger exists(String name) { + Object o = ht.get(new CategoryKey(name)); + if(o instanceof Logger) { + return (Logger) o; + } else { + return null; + } + } + + /** + The string form of {@link #setThreshold(Level)}. + */ + public + void setThreshold(String levelStr) { + Level l = Level.toLevel(levelStr, null); + if(l != null) { + setThreshold(l); + } else { + LogLog.warn("Could not convert ["+levelStr+"] to Level."); + } + } + + + /** + Enable logging for logging requests with level l or + higher. By default all levels are enabled. + + @param l The minimum level for which logging requests are sent to + their appenders. */ + public + void setThreshold(Level l) { + if(l != null) { + thresholdInt = l.level; + threshold = l; + } + } + + public + void fireAddAppenderEvent(Category logger, Appender appender) { + if(listeners != null) { + int size = listeners.size(); + HierarchyEventListener listener; + for(int i = 0; i < size; i++) { + listener = (HierarchyEventListener) listeners.elementAt(i); + listener.addAppenderEvent(logger, appender); + } + } + } + + void fireRemoveAppenderEvent(Category logger, Appender appender) { + if(listeners != null) { + int size = listeners.size(); + HierarchyEventListener listener; + for(int i = 0; i < size; i++) { + listener = (HierarchyEventListener) listeners.elementAt(i); + listener.removeAppenderEvent(logger, appender); + } + } + } + + /** + Returns a {@link Level} representation of the enable + state. + + @since 1.2 */ + public + Level getThreshold() { + return threshold; + } + + /** + Returns an integer representation of the this repository's + threshold. + + @since 1.2 */ + //public + //int getThresholdInt() { + // return thresholdInt; + //} + + + /** + Return a new logger instance named as the first parameter using + the default factory. + +

If a logger of that name already exists, then it will be + returned. Otherwise, a new logger will be instantiated and + then linked with its existing ancestors as well as children. + + @param name The name of the logger to retrieve. + + */ + public + Logger getLogger(String name) { + return getLogger(name, defaultFactory); + } + + /** + Return a new logger instance named as the first parameter using + factory. + +

If a logger of that name already exists, then it will be + returned. Otherwise, a new logger will be instantiated by the + factory parameter and linked with its existing + ancestors as well as children. + + @param name The name of the logger to retrieve. + @param factory The factory that will make the new logger instance. + + */ + public + Logger getLogger(String name, LoggerFactory factory) { + //System.out.println("getInstance("+name+") called."); + CategoryKey key = new CategoryKey(name); + // Synchronize to prevent write conflicts. Read conflicts (in + // getChainedLevel method) are possible only if variable + // assignments are non-atomic. + Logger logger; + + synchronized(ht) { + Object o = ht.get(key); + if(o == null) { + logger = factory.makeNewLoggerInstance(name); + logger.setHierarchy(this); + ht.put(key, logger); + updateParents(logger); + return logger; + } else if(o instanceof Logger) { + return (Logger) o; + } else if (o instanceof ProvisionNode) { + //System.out.println("("+name+") ht.get(this) returned ProvisionNode"); + logger = factory.makeNewLoggerInstance(name); + logger.setHierarchy(this); + ht.put(key, logger); + updateChildren((ProvisionNode) o, logger); + updateParents(logger); + return logger; + } + else { + // It should be impossible to arrive here + return null; // but let's keep the compiler happy. + } + } + } + + /** + Returns all the currently defined categories in this hierarchy as + an {@link java.util.Enumeration Enumeration}. + +

The root logger is not included in the returned + {@link Enumeration}. */ + public + Enumeration getCurrentLoggers() { + // The accumlation in v is necessary because not all elements in + // ht are Logger objects as there might be some ProvisionNodes + // as well. + Vector v = new Vector(ht.size()); + + Enumeration elems = ht.elements(); + while(elems.hasMoreElements()) { + Object o = elems.nextElement(); + if(o instanceof Logger) { + v.addElement(o); + } + } + return v.elements(); + } + + /** + @deprecated Please use {@link #getCurrentLoggers} instead. + */ + public + Enumeration getCurrentCategories() { + return getCurrentLoggers(); + } + + + /** + Get the renderer map for this hierarchy. + */ + public + RendererMap getRendererMap() { + return rendererMap; + } + + + /** + Get the root of this hierarchy. + + @since 0.9.0 + */ + public + Logger getRootLogger() { + return root; + } + + /** + This method will return true if this repository is + disabled for level object passed as parameter and + false otherwise. See also the {@link + #setThreshold(Level) threshold} emthod. */ + public + boolean isDisabled(int level) { + return thresholdInt > level; + } + + /** + @deprecated Deprecated with no replacement. + */ + public + void overrideAsNeeded(String override) { + LogLog.warn("The Hiearchy.overrideAsNeeded method has been deprecated."); + } + + /** + Reset all values contained in this hierarchy instance to their + default. This removes all appenders from all categories, sets + the level of all non-root categories to null, + sets their additivity flag to true and sets the level + of the root logger to {@link Level#DEBUG DEBUG}. Moreover, + message disabling is set its default "off" value. + +

Existing categories are not removed. They are just reset. + +

This method should be used sparingly and with care as it will + block all logging until it is completed.

+ + @since 0.8.5 */ + public + void resetConfiguration() { + + getRootLogger().setLevel(Level.DEBUG); + root.setResourceBundle(null); + setThreshold(Level.ALL); + + // the synchronization is needed to prevent JDK 1.2.x hashtable + // surprises + synchronized(ht) { + shutdown(); // nested locks are OK + + Enumeration cats = getCurrentLoggers(); + while(cats.hasMoreElements()) { + Logger c = (Logger) cats.nextElement(); + c.setLevel(null); + c.setAdditivity(true); + c.setResourceBundle(null); + } + } + rendererMap.clear(); + throwableRenderer = null; + } + + /** + Does nothing. + + @deprecated Deprecated with no replacement. + */ + public + void setDisableOverride(String override) { + LogLog.warn("The Hiearchy.setDisableOverride method has been deprecated."); + } + + + + /** + Used by subclasses to add a renderer to the hierarchy passed as parameter. + */ + public + void setRenderer(Class renderedClass, ObjectRenderer renderer) { + rendererMap.put(renderedClass, renderer); + } + + /** + * {@inheritDoc} + */ + public void setThrowableRenderer(final ThrowableRenderer renderer) { + throwableRenderer = renderer; + } + + /** + * {@inheritDoc} + */ + public ThrowableRenderer getThrowableRenderer() { + return throwableRenderer; + } + + + /** + Shutting down a hierarchy will safely close and remove + all appenders in all categories including the root logger. + +

Some appenders such as {@link org.apache.log4j.net.SocketAppender} + and {@link AsyncAppender} need to be closed before the + application exists. Otherwise, pending logging events might be + lost. + +

The shutdown method is careful to close nested + appenders before closing regular appenders. This is allows + configurations where a regular appender is attached to a logger + and again to a nested appender. + + + @since 1.0 */ + public + void shutdown() { + Logger root = getRootLogger(); + + // begin by closing nested appenders + root.closeNestedAppenders(); + + synchronized(ht) { + Enumeration cats = this.getCurrentLoggers(); + while(cats.hasMoreElements()) { + Logger c = (Logger) cats.nextElement(); + c.closeNestedAppenders(); + } + + // then, remove all appenders + root.removeAllAppenders(); + cats = this.getCurrentLoggers(); + while(cats.hasMoreElements()) { + Logger c = (Logger) cats.nextElement(); + c.removeAllAppenders(); + } + } + } + + + /** + This method loops through all the *potential* parents of + 'cat'. There 3 possible cases: + + 1) No entry for the potential parent of 'cat' exists + + We create a ProvisionNode for this potential parent and insert + 'cat' in that provision node. + + 2) There entry is of type Logger for the potential parent. + + The entry is 'cat's nearest existing parent. We update cat's + parent field with this entry. We also break from the loop + because updating our parent's parent is our parent's + responsibility. + + 3) There entry is of type ProvisionNode for this potential parent. + + We add 'cat' to the list of children for this potential parent. + */ + final + private + void updateParents(Logger cat) { + String name = cat.name; + int length = name.length(); + boolean parentFound = false; + + //System.out.println("UpdateParents called for " + name); + + // if name = "w.x.y.z", loop thourgh "w.x.y", "w.x" and "w", but not "w.x.y.z" + for(int i = name.lastIndexOf('.', length-1); i >= 0; + i = name.lastIndexOf('.', i-1)) { + String substr = name.substring(0, i); + + //System.out.println("Updating parent : " + substr); + CategoryKey key = new CategoryKey(substr); // simple constructor + Object o = ht.get(key); + // Create a provision node for a future parent. + if(o == null) { + //System.out.println("No parent "+substr+" found. Creating ProvisionNode."); + ProvisionNode pn = new ProvisionNode(cat); + ht.put(key, pn); + } else if(o instanceof Category) { + parentFound = true; + cat.parent = (Category) o; + //System.out.println("Linking " + cat.name + " -> " + ((Category) o).name); + break; // no need to update the ancestors of the closest ancestor + } else if(o instanceof ProvisionNode) { + ((ProvisionNode) o).addElement(cat); + } else { + Exception e = new IllegalStateException("unexpected object type " + + o.getClass() + " in ht."); + e.printStackTrace(); + } + } + // If we could not find any existing parents, then link with root. + if(!parentFound) { + cat.parent = root; + } + } + + /** + We update the links for all the children that placed themselves + in the provision node 'pn'. The second argument 'cat' is a + reference for the newly created Logger, parent of all the + children in 'pn' + + We loop on all the children 'c' in 'pn': + + If the child 'c' has been already linked to a child of + 'cat' then there is no need to update 'c'. + + Otherwise, we set cat's parent field to c's parent and set + c's parent field to cat. + + */ + final + private + void updateChildren(ProvisionNode pn, Logger logger) { + //System.out.println("updateChildren called for " + logger.name); + final int last = pn.size(); + + for(int i = 0; i < last; i++) { + Logger l = (Logger) pn.elementAt(i); + //System.out.println("Updating child " +p.name); + + // Unless this child already points to a correct (lower) parent, + // make cat.parent point to l.parent and l.parent to cat. + if(!l.parent.name.startsWith(logger.name)) { + logger.parent = l.parent; + l.parent = logger; + } + } + } + +} + +