Advertisement
Guest User

Logger.java

a guest
Feb 5th, 2016
76
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Java 17.05 KB | None | 0 0
  1. /*
  2.  * Licensed to the Apache Software Foundation (ASF) under one or more
  3.  * contributor license agreements. See the NOTICE file distributed with
  4.  * this work for additional information regarding copyright ownership.
  5.  * The ASF licenses this file to You under the Apache license, Version 2.0
  6.  * (the "License"); you may not use this file except in compliance with
  7.  * the License. You may obtain a copy of the License at
  8.  *
  9.  *      http://www.apache.org/licenses/LICENSE-2.0
  10.  *
  11.  * Unless required by applicable law or agreed to in writing, software
  12.  * distributed under the License is distributed on an "AS IS" BASIS,
  13.  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14.  * See the license for the specific language governing permissions and
  15.  * limitations under the license.
  16.  */
  17. package org.apache.logging.log4j.core;
  18.  
  19. import java.io.ObjectStreamException;
  20. import java.io.Serializable;
  21. import java.util.ArrayList;
  22. import java.util.Iterator;
  23. import java.util.List;
  24. import java.util.Map;
  25.  
  26. import org.apache.logging.log4j.Level;
  27. import org.apache.logging.log4j.Marker;
  28. import org.apache.logging.log4j.core.config.Configuration;
  29. import org.apache.logging.log4j.core.config.LoggerConfig;
  30. import org.apache.logging.log4j.core.config.ReliabilityStrategy;
  31. import org.apache.logging.log4j.core.filter.CompositeFilter;
  32. import org.apache.logging.log4j.message.Message;
  33. import org.apache.logging.log4j.message.MessageFactory;
  34. import org.apache.logging.log4j.message.SimpleMessage;
  35. import org.apache.logging.log4j.spi.AbstractLogger;
  36. import org.apache.logging.log4j.util.Strings;
  37. import org.apache.logging.log4j.util.Supplier;
  38.  
  39. /**
  40.  * The core implementation of the {@link org.apache.logging.log4j.Logger} interface. Besides providing an implementation
  41.  * of all the Logger methods, this class also provides some convenience methods for Log4j 1.x compatibility as well as
  42.  * access to the {@link org.apache.logging.log4j.core.Filter Filters} and {@link org.apache.logging.log4j.core.Appender
  43.  * Appenders} associated with this Logger. Note that access to these underlying objects is provided primarily for use in
  44.  * unit tests or bridging legacy Log4j 1.x code. Future versions of this class may or may not include the various
  45.  * methods that are noted as not being part of the public API.
  46.  *
  47.  * TODO All the isEnabled methods could be pushed into a filter interface. Not sure of the utility of having isEnabled
  48.  * be able to examine the message pattern and parameters. (RG) Moving the isEnabled methods out of Logger noticeably
  49.  * impacts performance. The message pattern and parameters are required so that they can be used in global filters.
  50.  */
  51. public class Logger extends AbstractLogger implements Supplier<LoggerConfig> {
  52.  
  53.     private static final long serialVersionUID = 1L;
  54.  
  55.     /**
  56.      * Config should be consistent across threads.
  57.      */
  58.     protected volatile PrivateConfig privateConfig;
  59.  
  60.     // FIXME: ditto to the above
  61.     private final LoggerContext context;
  62.  
  63.     /**
  64.      * The constructor.
  65.      *
  66.      * @param context The LoggerContext this Logger is associated with.
  67.      * @param messageFactory The message factory.
  68.      * @param name The name of the Logger.
  69.      */
  70.     protected Logger(final LoggerContext context, final String name, final MessageFactory messageFactory) {
  71.         super(name, messageFactory);
  72.         this.context = context;
  73.         privateConfig = new PrivateConfig(context.getConfiguration(), this);
  74.     }
  75.  
  76.     protected Object writeReplace() throws ObjectStreamException {
  77.         return new LoggerProxy(getName(), getMessageFactory());
  78.     }
  79.  
  80.     /**
  81.      * This method is only used for 1.x compatibility. Returns the parent of this Logger. If it doesn't already exist
  82.      * return a temporary Logger.
  83.      *
  84.      * @return The parent Logger.
  85.      */
  86.     public Logger getParent() {
  87.         final LoggerConfig lc = privateConfig.loggerConfig.getName().equals(getName()) ? privateConfig.loggerConfig
  88.                 .getParent() : privateConfig.loggerConfig;
  89.         if (lc == null) {
  90.             return null;
  91.         }
  92.         final String lcName = lc.getName();
  93.         final MessageFactory messageFactory = getMessageFactory();
  94.         if (context.hasLogger(lcName, messageFactory)) {
  95.             return context.getLogger(lcName, messageFactory);
  96.         }
  97.         return new Logger(context, lcName, messageFactory);
  98.     }
  99.  
  100.     /**
  101.      * Returns the LoggerContext this Logger is associated with.
  102.      *
  103.      * @return the LoggerContext.
  104.      */
  105.     public LoggerContext getContext() {
  106.         return context;
  107.     }
  108.  
  109.     /**
  110.      * This method is not exposed through the public API and is provided primarily for unit testing.
  111.      * <p>
  112.      * If the new level is null, this logger inherits the level from its parent.
  113.      * </p>
  114.      *
  115.      * @param level The Level to use on this Logger, may be null.
  116.      */
  117.     public synchronized void setLevel(final Level level) {
  118.         if (level == getLevel()) {
  119.             return;
  120.         }
  121.         Level actualLevel;
  122.         if (level != null) {
  123.             actualLevel = level;
  124.         } else {
  125.             final Logger parent = getParent();
  126.             actualLevel = parent != null ? parent.getLevel() : privateConfig.loggerConfigLevel;
  127.         }
  128.         privateConfig = new PrivateConfig(privateConfig, actualLevel);
  129.     }
  130.  
  131.     /*
  132.      * (non-Javadoc)
  133.      *
  134.      * @see org.apache.logging.log4j.util.Supplier#get()
  135.      */
  136.     @Override
  137.     public LoggerConfig get() {
  138.         return privateConfig.loggerConfig;
  139.     }
  140.  
  141.     @Override
  142.     public void logMessage(final String fqcn, final Level level, final Marker marker, final Message message,
  143.             final Throwable t) {
  144.         final Message msg = message == null ? new SimpleMessage(Strings.EMPTY) : message;
  145.  
  146.         final ReliabilityStrategy strategy = privateConfig.loggerConfig.getReliabilityStrategy();
  147.         strategy.log(this, getName(), fqcn, marker, level, msg, t);
  148.     }
  149.  
  150.     @Override
  151.     public boolean isEnabled(final Level level, final Marker marker, final String message, final Throwable t) {
  152.         return privateConfig.filter(level, marker, message, t);
  153.     }
  154.  
  155.     @Override
  156.     public boolean isEnabled(final Level level, final Marker marker, final String message) {
  157.         return privateConfig.filter(level, marker, message);
  158.     }
  159.  
  160.     @Override
  161.     public boolean isEnabled(final Level level, final Marker marker, final String message, final Object... params) {
  162.         return privateConfig.filter(level, marker, message, params);
  163.     }
  164.  
  165.     @Override
  166.     public boolean isEnabled(final Level level, final Marker marker, final Object message, final Throwable t) {
  167.         return privateConfig.filter(level, marker, message, t);
  168.     }
  169.  
  170.     @Override
  171.     public boolean isEnabled(final Level level, final Marker marker, final Message message, final Throwable t) {
  172.         return privateConfig.filter(level, marker, message, t);
  173.     }
  174.  
  175.     /**
  176.      * This method is not exposed through the public API and is used primarily for unit testing.
  177.      *
  178.      * @param appender The Appender to add to the Logger.
  179.      */
  180.     public void addAppender(final Appender appender) {
  181.         privateConfig.config.addLoggerAppender(this, appender);
  182.     }
  183.  
  184.     /**
  185.      * This method is not exposed through the public API and is used primarily for unit testing.
  186.      *
  187.      * @param appender The Appender to remove from the Logger.
  188.      */
  189.     public void removeAppender(final Appender appender) {
  190.         privateConfig.loggerConfig.removeAppender(appender.getName());
  191.     }
  192.  
  193.     /**
  194.      * This method is not exposed through the public API and is used primarily for unit testing.
  195.      *
  196.      * @return A Map containing the Appender's name as the key and the Appender as the value.
  197.      */
  198.     public Map<String, Appender> getAppenders() {
  199.         return privateConfig.loggerConfig.getAppenders();
  200.     }
  201.  
  202.     /**
  203.      * This method is not exposed through the public API and is used primarily for unit testing.
  204.      *
  205.      * @return An Iterator over all the Filters associated with the Logger.
  206.      */
  207.     // FIXME: this really ought to be an Iterable instead of an Iterator
  208.     public Iterator<Filter> getFilters() {
  209.         final Filter filter = privateConfig.loggerConfig.getFilter();
  210.         if (filter == null) {
  211.             return new ArrayList<Filter>().iterator();
  212.         } else if (filter instanceof CompositeFilter) {
  213.             return ((CompositeFilter) filter).iterator();
  214.         } else {
  215.             final List<Filter> filters = new ArrayList<>();
  216.             filters.add(filter);
  217.             return filters.iterator();
  218.         }
  219.     }
  220.  
  221.     /**
  222.      * Gets the Level associated with the Logger.
  223.      *
  224.      * @return the Level associate with the Logger.
  225.      */
  226.     @Override
  227.     public Level getLevel() {
  228.         return privateConfig.loggerConfigLevel;
  229.     }
  230.  
  231.     /**
  232.      * This method is not exposed through the public API and is used primarily for unit testing.
  233.      *
  234.      * @return The number of Filters associated with the Logger.
  235.      */
  236.     public int filterCount() {
  237.         final Filter filter = privateConfig.loggerConfig.getFilter();
  238.         if (filter == null) {
  239.             return 0;
  240.         } else if (filter instanceof CompositeFilter) {
  241.             return ((CompositeFilter) filter).size();
  242.         }
  243.         return 1;
  244.     }
  245.  
  246.     /**
  247.      * This method is not exposed through the public API and is used primarily for unit testing.
  248.      *
  249.      * @param filter The Filter to add.
  250.      */
  251.     public void addFilter(final Filter filter) {
  252.         privateConfig.config.addLoggerFilter(this, filter);
  253.     }
  254.  
  255.     /**
  256.      * This method is not exposed through the public API and is present only to support the Log4j 1.2 compatibility
  257.      * bridge.
  258.      *
  259.      * @return true if the associated LoggerConfig is additive, false otherwise.
  260.      */
  261.     public boolean isAdditive() {
  262.         return privateConfig.loggerConfig.isAdditive();
  263.     }
  264.  
  265.     /**
  266.      * This method is not exposed through the public API and is present only to support the Log4j 1.2 compatibility
  267.      * bridge.
  268.      *
  269.      * @param additive Boolean value to indicate whether the Logger is additive or not.
  270.      */
  271.     public void setAdditive(final boolean additive) {
  272.         privateConfig.config.setLoggerAdditive(this, additive);
  273.     }
  274.  
  275.     /**
  276.      * Associates this Logger with a new Configuration. This method is not
  277.      * exposed through the public API.
  278.      * <p>
  279.      * There are two ways this could be used to guarantee all threads are aware
  280.      * of changes to config.
  281.      * <ol>
  282.      * <li>Synchronize this method. Accessors don't need to be synchronized as
  283.      * Java will treat all variables within a synchronized block as volatile.
  284.      * </li>
  285.      * <li>Declare the variable volatile. Option 2 is used here as the
  286.      * performance cost is very low and it does a better job at documenting how
  287.      * it is used.</li>
  288.      *
  289.      * @param newConfig
  290.      *            The new Configuration.
  291.      */
  292.     protected void updateConfiguration(final Configuration newConfig) {
  293.         this.privateConfig = new PrivateConfig(newConfig, this);
  294.     }
  295.  
  296.     /**
  297.      * The binding between a Logger and its configuration.
  298.      */
  299.     protected class PrivateConfig {
  300.         // config fields are public to make them visible to Logger subclasses
  301.         /** LoggerConfig to delegate the actual logging to. */
  302.         public final LoggerConfig loggerConfig; // SUPPRESS CHECKSTYLE
  303.         /** The current Configuration associated with the LoggerConfig. */
  304.         public final Configuration config; // SUPPRESS CHECKSTYLE
  305.         private final Level loggerConfigLevel;
  306.         private final int intLevel;
  307.         private final Logger logger;
  308.  
  309.         public PrivateConfig(final Configuration config, final Logger logger) {
  310.             this.config = config;
  311.             this.loggerConfig = config.getLoggerConfig(getName());
  312.             this.loggerConfigLevel = this.loggerConfig.getLevel();
  313.             this.intLevel = this.loggerConfigLevel.intLevel();
  314.             this.logger = logger;
  315.         }
  316.  
  317.         public PrivateConfig(final PrivateConfig pc, final Level level) {
  318.             this.config = pc.config;
  319.             this.loggerConfig = pc.loggerConfig;
  320.             this.loggerConfigLevel = level;
  321.             this.intLevel = this.loggerConfigLevel.intLevel();
  322.             this.logger = pc.logger;
  323.         }
  324.  
  325.         public PrivateConfig(final PrivateConfig pc, final LoggerConfig lc) {
  326.             this.config = pc.config;
  327.             this.loggerConfig = lc;
  328.             this.loggerConfigLevel = lc.getLevel();
  329.             this.intLevel = this.loggerConfigLevel.intLevel();
  330.             this.logger = pc.logger;
  331.         }
  332.  
  333.         // LOG4J2-151: changed visibility to public
  334.         public void logEvent(final LogEvent event) {
  335.             loggerConfig.log(event);
  336.         }
  337.  
  338.         boolean filter(final Level level, final Marker marker, final String msg) {
  339.             final Filter filter = config.getFilter();
  340.             if (filter != null) {
  341.                 final Filter.Result r = filter.filter(logger, level, marker, msg);
  342.                 if (r != Filter.Result.NEUTRAL) {
  343.                     return r == Filter.Result.ACCEPT;
  344.                 }
  345.             }
  346.             return level != null && intLevel >= level.intLevel();
  347.         }
  348.  
  349.         boolean filter(final Level level, final Marker marker, final String msg, final Throwable t) {
  350.             final Filter filter = config.getFilter();
  351.             if (filter != null) {
  352.                 final Filter.Result r = filter.filter(logger, level, marker, msg, t);
  353.                 if (r != Filter.Result.NEUTRAL) {
  354.                     return r == Filter.Result.ACCEPT;
  355.                 }
  356.             }
  357.             return level != null && intLevel >= level.intLevel();
  358.         }
  359.  
  360.         boolean filter(final Level level, final Marker marker, final String msg, final Object... p1) {
  361.             final Filter filter = config.getFilter();
  362.             if (filter != null) {
  363.                 final Filter.Result r = filter.filter(logger, level, marker, msg, p1);
  364.                 if (r != Filter.Result.NEUTRAL) {
  365.                     return r == Filter.Result.ACCEPT;
  366.                 }
  367.             }
  368.             return level != null && intLevel >= level.intLevel();
  369.         }
  370.  
  371.         boolean filter(final Level level, final Marker marker, final Object msg, final Throwable t) {
  372.             final Filter filter = config.getFilter();
  373.             if (filter != null) {
  374.                 final Filter.Result r = filter.filter(logger, level, marker, msg, t);
  375.                 if (r != Filter.Result.NEUTRAL) {
  376.                     return r == Filter.Result.ACCEPT;
  377.                 }
  378.             }
  379.             return level != null && intLevel >= level.intLevel();
  380.         }
  381.  
  382.         boolean filter(final Level level, final Marker marker, final Message msg, final Throwable t) {
  383.             final Filter filter = config.getFilter();
  384.             if (filter != null) {
  385.                 final Filter.Result r = filter.filter(logger, level, marker, msg, t);
  386.                 if (r != Filter.Result.NEUTRAL) {
  387.                     return r == Filter.Result.ACCEPT;
  388.                 }
  389.             }
  390.             return level != null && intLevel >= level.intLevel();
  391.         }
  392.     }
  393.  
  394.     /**
  395.      * Serialization proxy class for Logger. Since the LoggerContext and config information can be reconstructed on the
  396.      * fly, the only information needed for a Logger are what's available in AbstractLogger.
  397.      *
  398.      * @since 2.5
  399.      */
  400.     protected static class LoggerProxy implements Serializable {
  401.         private static final long serialVersionUID = 1L;
  402.  
  403.         private final String name;
  404.         private final MessageFactory messageFactory;
  405.  
  406.         public LoggerProxy(String name, MessageFactory messageFactory) {
  407.             this.name = name;
  408.             this.messageFactory = messageFactory;
  409.         }
  410.  
  411.         protected Object readResolve() throws ObjectStreamException {
  412.             return new Logger(LoggerContext.getContext(), name, messageFactory);
  413.         }
  414.     }
  415.  
  416.     /**
  417.      * Returns a String representation of this instance in the form {@code "name:level[ in context_name]"}.
  418.      *
  419.      * @return A String describing this Logger instance.
  420.      */
  421.     @Override
  422.     public String toString() {
  423.         final String nameLevel = Strings.EMPTY + getName() + ':' + getLevel();
  424.         if (context == null) {
  425.             return nameLevel;
  426.         }
  427.         final String contextName = context.getName();
  428.         return contextName == null ? nameLevel : nameLevel + " in " + contextName;
  429.     }
  430.  
  431.     @Override
  432.     public boolean equals(final Object o) {
  433.         if (this == o) {
  434.             return true;
  435.         }
  436.         if (o == null || getClass() != o.getClass()) {
  437.             return false;
  438.         }
  439.         final Logger that = (Logger) o;
  440.         return getName().equals(that.getName());
  441.     }
  442.  
  443.     @Override
  444.     public int hashCode() {
  445.         return getName().hashCode();
  446.     }
  447. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement