View Javadoc

    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
    18  // Contibutors: Alex Blewitt <Alex.Blewitt@ioshq.com>
    19  //              Markus Oestreicher <oes@zurich.ibm.com>
    20  //              Frank Hoering <fhr@zurich.ibm.com>
    21  //              Nelson Minar <nelson@media.mit.edu>
    22  //              Jim Cakalic <jim_cakalic@na.biomerieux.com>
    23  //              Avy Sharell <asharell@club-internet.fr>
    24  //              Ciaran Treanor <ciaran@xelector.com>
    25  //              Jeff Turner <jeff@socialchange.net.au>
    26  //              Michael Horwitz <MHorwitz@siemens.co.za>
    27  //              Calvin Chan <calvin.chan@hic.gov.au>
    28  //              Aaron Greenhouse <aarong@cs.cmu.edu>
    29  //              Beat Meier <bmeier@infovia.com.ar>
    30  //              Colin Sampaleanu <colinml1@exis.com>
    31
    32  package org.apache.log4j;
    33
    34  import org.apache.log4j.spi.AppenderAttachable;
    35  import org.apache.log4j.spi.LoggingEvent;
    36  import org.apache.log4j.spi.LoggerRepository;
    37  import org.apache.log4j.spi.HierarchyEventListener;
    38  import org.apache.log4j.helpers.NullEnumeration;
    39  import org.apache.log4j.helpers.AppenderAttachableImpl;
    40
    41  import java.util.Enumeration;
    42  import java.util.MissingResourceException;
    43  import java.util.ResourceBundle;
    44  import java.util.Vector;
    45
    46
    47  /***
    48    * <font color="#AA2222"><b>This class has been deprecated and
    49    * replaced by the {@link Logger} <em>subclass</em></b></font>. It
    50    * will be kept around to preserve backward compatibility until mid
    51    * 2003.
    52    *
    53    * <p><code>Logger</code> is a subclass of Category, i.e. it extends
    54    * Category. In other words, a logger <em>is</em> a category. Thus,
    55    * all operations that can be performed on a category can be
    56    * performed on a logger. Internally, whenever log4j is asked to
    57    * produce a Category object, it will instead produce a Logger
    58    * object. Log4j 1.2 will <em>never</em> produce Category objects but
    59    * only <code>Logger</code> instances. In order to preserve backward
    60    * compatibility, methods that previously accepted category objects
    61    * still continue to accept category objects.
    62    *
    63    * <p>For example, the following are all legal and will work as
    64    * expected.
    65    *
    66     <pre>
    67      &nbsp;&nbsp;&nbsp;// Deprecated form:
    68      &nbsp;&nbsp;&nbsp;Category cat = Category.getInstance("foo.bar")
    69
    70      &nbsp;&nbsp;&nbsp;// Preferred form for retrieving loggers:
    71      &nbsp;&nbsp;&nbsp;Logger logger = Logger.getLogger("foo.bar")
    72     </pre>
    73
    74    *  <p>The first form is deprecated and should be avoided.
    75    *
    76    *  <p><b>There is absolutely no need for new client code to use or
    77    *  refer to the <code>Category</code> class.</b> Whenever possible,
    78    *  please avoid referring to it or using it.
    79    *
    80    * <p>See the <a href="../../../../manual.html">short manual</a> for an
    81    * introduction on this class.
    82    * <p>
    83    * See the document entitled <a href="http://www.qos.ch/logging/preparingFor13.html">preparing
    84    *  for log4j 1.3</a> for a more detailed discussion.
    85    *
    86    * @author Ceki G&uuml;lc&uuml;
    87    * @author Anders Kristensen
    88    */
    89  public class Category implements AppenderAttachable {
    90
    91    /***
    92       The hierarchy where categories are attached to by default.
    93    */
    94    //static
    95    //public
    96    //final Hierarchy defaultHierarchy = new Hierarchy(new
    97    //					   RootCategory(Level.DEBUG));
    98
    99    /***
    100      The name of this category.
    101   */
    102   protected String   name;
    103
    104   /***
    105      The assigned level of this category.  The
    106      <code>level</code> variable need not be assigned a value in
    107      which case it is inherited form the hierarchy.  */
    108   volatile protected Level level;
    109
    110   /***
    111      The parent of this category. All categories have at least one
    112      ancestor which is the root category. */
    113   volatile protected Category parent;
    114
    115   /***
    116      The fully qualified name of the Category class. See also the
    117      getFQCN method. */
    118   private static final String FQCN = Category.class.getName();
    119
    120   protected ResourceBundle resourceBundle;
    121
    122   // Categories need to know what Hierarchy they are in
    123   protected LoggerRepository repository;
    124
    125
    126   AppenderAttachableImpl aai;
    127
    128   /*** Additivity is set to true by default, that is children inherit
    129       the appenders of their ancestors by default. If this variable is
    130       set to <code>false</code> then the appenders found in the
    131       ancestors of this category are not used. However, the children
    132       of this category will inherit its appenders, unless the children
    133       have their additivity flag set to <code>false</code> too. See
    134       the user manual for more details. */
    135   protected boolean additive = true;
    136
    137   /***
    138      This constructor created a new <code>Category</code> instance and
    139      sets its name.
    140
    141      <p>It is intended to be used by sub-classes only. You should not
    142      create categories directly.
    143
    144      @param name The name of the category.
    145   */
    146   protected
    147   Category(String name) {
    148     this.name = name;
    149   }
    150
    151   /***
    152      Add <code>newAppender</code> to the list of appenders of this
    153      Category instance.
    154
    155      <p>If <code>newAppender</code> is already in the list of
    156      appenders, then it won't be added again.
    157   */
    158   synchronized
    159   public
    160   void addAppender(Appender newAppender) {
    161     if(aai == null) {
    162       aai = new AppenderAttachableImpl();
    163     }
    164     aai.addAppender(newAppender);
    165     repository.fireAddAppenderEvent(this, newAppender);
    166   }
    167
    168   /***
    169      If <code>assertion</code> parameter is <code>false</code>, then
    170      logs <code>msg</code> as an {@link #error(Object) error} statement.
    171
    172      <p>The <code>assert</code> method has been renamed to
    173      <code>assertLog</code> because <code>assert</code> is a language
    174      reserved word in JDK 1.4.
    175
    176      @param assertion
    177      @param msg The message to print if <code>assertion</code> is
    178      false.
    179
    180      @since 1.2 */
    181   public
    182   void assertLog(boolean assertion, String msg) {
    183     if(!assertion)
    184       this.error(msg);
    185   }
    186
    187
    188   /***
    189      Call the appenders in the hierrachy starting at
    190      <code>this</code>.  If no appenders could be found, emit a
    191      warning.
    192
    193      <p>This method calls all the appenders inherited from the
    194      hierarchy circumventing any evaluation of whether to log or not
    195      to log the particular log request.
    196
    197      @param event the event to log.  */
    198   public
    199   void callAppenders(LoggingEvent event) {
    200     int writes = 0;
    201
    202     for(Category c = this; c != null; c=c.parent) {
    203       // Protected against simultaneous call to addAppender, removeAppender,...
    204       synchronized(c) {
    205 	if(c.aai != null) {
    206 	  writes += c.aai.appendLoopOnAppenders(event);
    207 	}
    208 	if(!c.additive) {
    209 	  break;
    210 	}
    211       }
    212     }
    213
    214     if(writes == 0) {
    215       repository.emitNoAppenderWarning(this);
    216     }
    217   }
    218
    219   /***
    220      Close all attached appenders implementing the AppenderAttachable
    221      interface.
    222      @since 1.0
    223   */
    224   synchronized
    225   void closeNestedAppenders() {
    226     Enumeration enumeration = this.getAllAppenders();
    227     if(enumeration != null) {
    228       while(enumeration.hasMoreElements()) {
    229 	Appender a = (Appender) enumeration.nextElement();
    230 	if(a instanceof AppenderAttachable) {
    231 	  a.close();
    232 	}
    233       }
    234     }
    235   }
    236
    237   /***
    238     Log a message object with the {@link Level#DEBUG DEBUG} level.
    239
    240     <p>This method first checks if this category is <code>DEBUG</code>
    241     enabled by comparing the level of this category with the {@link
    242     Level#DEBUG DEBUG} level. If this category is
    243     <code>DEBUG</code> enabled, then it converts the message object
    244     (passed as parameter) to a string by invoking the appropriate
    245     {@link org.apache.log4j.or.ObjectRenderer}. It then proceeds to call all the
    246     registered appenders in this category and also higher in the
    247     hierarchy depending on the value of the additivity flag.
    248
    249     <p><b>WARNING</b> Note that passing a {@link Throwable} to this
    250     method will print the name of the <code>Throwable</code> but no
    251     stack trace. To print a stack trace use the {@link #debug(Object,
    252     Throwable)} form instead.
    253
    254     @param message the message object to log. */
    255   public
    256   void debug(Object message) {
    257     if(repository.isDisabled(Level.DEBUG_INT))
    258       return;
    259     if(Level.DEBUG.isGreaterOrEqual(this.getEffectiveLevel())) {
    260       forcedLog(FQCN, Level.DEBUG, message, null);
    261     }
    262   }
    263
    264
    265   /***
    266    Log a message object with the <code>DEBUG</code> level including
    267    the stack trace of the {@link Throwable} <code>t</code> passed as
    268    parameter.
    269
    270    <p>See {@link #debug(Object)} form for more detailed information.
    271
    272    @param message the message object to log.
    273    @param t the exception to log, including its stack trace.  */
    274   public
    275   void debug(Object message, Throwable t) {
    276     if(repository.isDisabled(Level.DEBUG_INT))
    277       return;
    278     if(Level.DEBUG.isGreaterOrEqual(this.getEffectiveLevel()))
    279       forcedLog(FQCN, Level.DEBUG, message, t);
    280   }
    281
    282   /***
    283     Log a message object with the {@link Level#ERROR ERROR} Level.
    284
    285     <p>This method first checks if this category is <code>ERROR</code>
    286     enabled by comparing the level of this category with {@link
    287     Level#ERROR ERROR} Level. If this category is <code>ERROR</code>
    288     enabled, then it converts the message object passed as parameter
    289     to a string by invoking the appropriate {@link
    290     org.apache.log4j.or.ObjectRenderer}. It proceeds to call all the
    291     registered appenders in this category and also higher in the
    292     hierarchy depending on the value of the additivity flag.
    293
    294     <p><b>WARNING</b> Note that passing a {@link Throwable} to this
    295     method will print the name of the <code>Throwable</code> but no
    296     stack trace. To print a stack trace use the {@link #error(Object,
    297     Throwable)} form instead.
    298
    299     @param message the message object to log */
    300   public
    301   void error(Object message) {
    302     if(repository.isDisabled(Level.ERROR_INT))
    303       return;
    304     if(Level.ERROR.isGreaterOrEqual(this.getEffectiveLevel()))
    305       forcedLog(FQCN, Level.ERROR, message, null);
    306   }
    307
    308   /***
    309    Log a message object with the <code>ERROR</code> level including
    310    the stack trace of the {@link Throwable} <code>t</code> passed as
    311    parameter.
    312
    313    <p>See {@link #error(Object)} form for more detailed information.
    314
    315    @param message the message object to log.
    316    @param t the exception to log, including its stack trace.  */
    317   public
    318   void error(Object message, Throwable t) {
    319     if(repository.isDisabled(Level.ERROR_INT))
    320       return;
    321     if(Level.ERROR.isGreaterOrEqual(this.getEffectiveLevel()))
    322       forcedLog(FQCN, Level.ERROR, message, t);
    323
    324   }
    325
    326
    327   /***
    328      If the named category exists (in the default hierarchy) then it
    329      returns a reference to the category, otherwise it returns
    330      <code>null</code>.
    331
    332      @deprecated Please use {@link LogManager#exists} instead.
    333
    334      @since 0.8.5 */
    335   public
    336   static
    337   Logger exists(String name) {
    338     return LogManager.exists(name);
    339   }
    340
    341   /***
    342     Log a message object with the {@link Level#FATAL FATAL} Level.
    343
    344     <p>This method first checks if this category is <code>FATAL</code>
    345     enabled by comparing the level of this category with {@link
    346     Level#FATAL FATAL} Level. If the category is <code>FATAL</code>
    347     enabled, then it converts the message object passed as parameter
    348     to a string by invoking the appropriate
    349     {@link org.apache.log4j.or.ObjectRenderer}. It
    350     proceeds to call all the registered appenders in this category and
    351     also higher in the hierarchy depending on the value of the
    352     additivity flag.
    353
    354     <p><b>WARNING</b> Note that passing a {@link Throwable} to this
    355     method will print the name of the Throwable but no stack trace. To
    356     print a stack trace use the {@link #fatal(Object, Throwable)} form
    357     instead.
    358
    359     @param message the message object to log */
    360   public
    361   void fatal(Object message) {
    362     if(repository.isDisabled(Level.FATAL_INT))
    363       return;
    364     if(Level.FATAL.isGreaterOrEqual(this.getEffectiveLevel()))
    365       forcedLog(FQCN, Level.FATAL, message, null);
    366   }
    367
    368   /***
    369    Log a message object with the <code>FATAL</code> level including
    370    the stack trace of the {@link Throwable} <code>t</code> passed as
    371    parameter.
    372
    373    <p>See {@link #fatal(Object)} for more detailed information.
    374
    375    @param message the message object to log.
    376    @param t the exception to log, including its stack trace.  */
    377   public
    378   void fatal(Object message, Throwable t) {
    379     if(repository.isDisabled(Level.FATAL_INT))
    380       return;
    381     if(Level.FATAL.isGreaterOrEqual(this.getEffectiveLevel()))
    382       forcedLog(FQCN, Level.FATAL, message, t);
    383   }
    384
    385
    386   /***
    387      This method creates a new logging event and logs the event
    388      without further checks.  */
    389   protected
    390   void forcedLog(String fqcn, Priority level, Object message, Throwable t) {
    391     callAppenders(new LoggingEvent(fqcn, this, level, message, t));
    392   }
    393
    394
    395   /***
    396      Get the additivity flag for this Category instance.
    397   */
    398   public
    399   boolean getAdditivity() {
    400     return additive;
    401   }
    402
    403   /***
    404      Get the appenders contained in this category as an {@link
    405      Enumeration}. If no appenders can be found, then a {@link NullEnumeration}
    406      is returned.
    407
    408      @return Enumeration An enumeration of the appenders in this category.  */
    409   synchronized
    410   public
    411   Enumeration getAllAppenders() {
    412     if(aai == null)
    413       return NullEnumeration.getInstance();
    414     else
    415       return aai.getAllAppenders();
    416   }
    417
    418   /***
    419      Look for the appender named as <code>name</code>.
    420
    421      <p>Return the appender with that name if in the list. Return
    422      <code>null</code> otherwise.  */
    423   synchronized
    424   public
    425   Appender getAppender(String name) {
    426      if(aai == null || name == null)
    427       return null;
    428
    429      return aai.getAppender(name);
    430   }
    431
    432   /***
    433      Starting from this category, search the category hierarchy for a
    434      non-null level and return it. Otherwise, return the level of the
    435      root category.
    436
    437      <p>The Category class is designed so that this method executes as
    438      quickly as possible.
    439    */
    440   public
    441   Level getEffectiveLevel() {
    442     for(Category c = this; c != null; c=c.parent) {
    443       if(c.level != null)
    444 	return c.level;
    445     }
    446     return null; // If reached will cause an NullPointerException.
    447   }
    448
    449   /***
    450     *
    451     * @deprecated Please use the the {@link #getEffectiveLevel} method
    452     * instead.
    453     * */
    454   public
    455   Priority getChainedPriority() {
    456     for(Category c = this; c != null; c=c.parent) {
    457       if(c.level != null)
    458 	return c.level;
    459     }
    460     return null; // If reached will cause an NullPointerException.
    461   }
    462
    463
    464   /***
    465      Returns all the currently defined categories in the default
    466      hierarchy as an {@link java.util.Enumeration Enumeration}.
    467
    468      <p>The root category is <em>not</em> included in the returned
    469      {@link Enumeration}.
    470
    471      @deprecated Please use {@link LogManager#getCurrentLoggers()} instead.
    472   */
    473   public
    474   static
    475   Enumeration getCurrentCategories() {
    476     return LogManager.getCurrentLoggers();
    477   }
    478
    479
    480   /***
    481      Return the default Hierarchy instance.
    482
    483      @deprecated Please use {@link LogManager#getLoggerRepository()} instead.
    484
    485      @since 1.0
    486    */
    487   public
    488   static
    489   LoggerRepository getDefaultHierarchy() {
    490     return LogManager.getLoggerRepository();
    491   }
    492
    493   /***
    494      Return the the {@link Hierarchy} where this <code>Category</code>
    495      instance is attached.
    496
    497      @deprecated Please use {@link #getLoggerRepository} instead.
    498
    499      @since 1.1 */
    500   public
    501   LoggerRepository  getHierarchy() {
    502     return repository;
    503   }
    504
    505   /***
    506      Return the the {@link LoggerRepository} where this
    507      <code>Category</code> is attached.
    508
    509      @since 1.2 */
    510   public
    511   LoggerRepository  getLoggerRepository() {
    512     return repository;
    513   }
    514
    515
    516  /***
    517   * @deprecated Make sure to use {@link Logger#getLogger(String)} instead.
    518   */
    519   public
    520   static
    521   Category getInstance(String name) {
    522     return LogManager.getLogger(name);
    523   }
    524
    525  /***
    526   * @deprecated Please make sure to use {@link Logger#getLogger(Class)} instead.
    527   */
    528   public
    529   static
    530   Category getInstance(Class clazz) {
    531     return LogManager.getLogger(clazz);
    532   }
    533
    534
    535   /***
    536      Return the category name.  */
    537   public
    538   final
    539   String getName() {
    540     return name;
    541   }
    542
    543
    544   /***
    545      Returns the parent of this category. Note that the parent of a
    546      given category may change during the lifetime of the category.
    547
    548      <p>The root category will return <code>null</code>.
    549
    550      @since 1.2
    551   */
    552   final
    553   public
    554   Category getParent() {
    555     return this.parent;
    556   }
    557
    558
    559   /***
    560      Returns the assigned {@link Level}, if any, for this Category.
    561
    562      @return Level - the assigned Level, can be <code>null</code>.
    563   */
    564   final
    565   public
    566   Level getLevel() {
    567     return this.level;
    568   }
    569
    570   /***
    571      @deprecated Please use {@link #getLevel} instead.
    572   */
    573   final
    574   public
    575   Level getPriority() {
    576     return this.level;
    577   }
    578
    579
    580   /***
    581    *  @deprecated Please use {@link Logger#getRootLogger()} instead.
    582    */
    583   final
    584   public
    585   static
    586   Category getRoot() {
    587     return LogManager.getRootLogger();
    588   }
    589
    590   /***
    591      Return the <em>inherited</em> {@link ResourceBundle} for this
    592      category.
    593
    594      <p>This method walks the hierarchy to find the appropriate
    595      resource bundle. It will return the resource bundle attached to
    596      the closest ancestor of this category, much like the way
    597      priorities are searched. In case there is no bundle in the
    598      hierarchy then <code>null</code> is returned.
    599
    600      @since 0.9.0 */
    601   public
    602   ResourceBundle getResourceBundle() {
    603     for(Category c = this; c != null; c=c.parent) {
    604       if(c.resourceBundle != null)
    605 	return c.resourceBundle;
    606     }
    607     // It might be the case that there is no resource bundle
    608     return null;
    609   }
    610
    611   /***
    612      Returns the string resource coresponding to <code>key</code> in
    613      this category's inherited resource bundle. See also {@link
    614      #getResourceBundle}.
    615
    616      <p>If the resource cannot be found, then an {@link #error error}
    617      message will be logged complaining about the missing resource.
    618   */
    619   protected
    620   String getResourceBundleString(String key) {
    621     ResourceBundle rb = getResourceBundle();
    622     // This is one of the rare cases where we can use logging in order
    623     // to report errors from within log4j.
    624     if(rb == null) {
    625       //if(!hierarchy.emittedNoResourceBundleWarning) {
    626       //error("No resource bundle has been set for category "+name);
    627       //hierarchy.emittedNoResourceBundleWarning = true;
    628       //}
    629       return null;
    630     }
    631     else {
    632       try {
    633 	return rb.getString(key);
    634       }
    635       catch(MissingResourceException mre) {
    636 	error("No resource is associated with key \""+key+"\".");
    637 	return null;
    638       }
    639     }
    640   }
    641
    642   /***
    643     Log a message object with the {@link Level#INFO INFO} Level.
    644
    645     <p>This method first checks if this category is <code>INFO</code>
    646     enabled by comparing the level of this category with {@link
    647     Level#INFO INFO} Level. If the category is <code>INFO</code>
    648     enabled, then it converts the message object passed as parameter
    649     to a string by invoking the appropriate
    650     {@link org.apache.log4j.or.ObjectRenderer}. It
    651     proceeds to call all the registered appenders in this category and
    652     also higher in the hierarchy depending on the value of the
    653     additivity flag.
    654
    655     <p><b>WARNING</b> Note that passing a {@link Throwable} to this
    656     method will print the name of the Throwable but no stack trace. To
    657     print a stack trace use the {@link #info(Object, Throwable)} form
    658     instead.
    659
    660     @param message the message object to log */
    661   public
    662   void info(Object message) {
    663     if(repository.isDisabled(Level.INFO_INT))
    664       return;
    665     if(Level.INFO.isGreaterOrEqual(this.getEffectiveLevel()))
    666       forcedLog(FQCN, Level.INFO, message, null);
    667   }
    668
    669   /***
    670    Log a message object with the <code>INFO</code> level including
    671    the stack trace of the {@link Throwable} <code>t</code> passed as
    672    parameter.
    673
    674    <p>See {@link #info(Object)} for more detailed information.
    675
    676    @param message the message object to log.
    677    @param t the exception to log, including its stack trace.  */
    678   public
    679   void info(Object message, Throwable t) {
    680     if(repository.isDisabled(Level.INFO_INT))
    681       return;
    682     if(Level.INFO.isGreaterOrEqual(this.getEffectiveLevel()))
    683       forcedLog(FQCN, Level.INFO, message, t);
    684   }
    685
    686   /***
    687      Is the appender passed as parameter attached to this category?
    688    */
    689   public
    690   boolean isAttached(Appender appender) {
    691     if(appender == null || aai == null)
    692       return false;
    693     else {
    694       return aai.isAttached(appender);
    695     }
    696   }
    697
    698   /***
    699     *  Check whether this category is enabled for the <code>DEBUG</code>
    700     *  Level.
    701     *
    702     *  <p> This function is intended to lessen the computational cost of
    703     *  disabled log debug statements.
    704     *
    705     *  <p> For some <code>cat</code> Category object, when you write,
    706     *  <pre>
    707     *      cat.debug("This is entry number: " + i );
    708     *  </pre>
    709     *
    710     *  <p>You incur the cost constructing the message, concatenatiion in
    711     *  this case, regardless of whether the message is logged or not.
    712     *
    713     *  <p>If you are worried about speed, then you should write
    714     *  <pre>
    715     * 	 if(cat.isDebugEnabled()) {
    716     * 	   cat.debug("This is entry number: " + i );
    717     * 	 }
    718     *  </pre>
    719     *
    720     *  <p>This way you will not incur the cost of parameter
    721     *  construction if debugging is disabled for <code>cat</code>. On
    722     *  the other hand, if the <code>cat</code> is debug enabled, you
    723     *  will incur the cost of evaluating whether the category is debug
    724     *  enabled twice. Once in <code>isDebugEnabled</code> and once in
    725     *  the <code>debug</code>.  This is an insignificant overhead
    726     *  since evaluating a category takes about 1%% of the time it
    727     *  takes to actually log.
    728     *
    729     *  @return boolean - <code>true</code> if this category is debug
    730     *  enabled, <code>false</code> otherwise.
    731     *   */
    732   public
    733   boolean isDebugEnabled() {
    734     if(repository.isDisabled( Level.DEBUG_INT))
    735       return false;
    736     return Level.DEBUG.isGreaterOrEqual(this.getEffectiveLevel());
    737   }
    738
    739   /***
    740      Check whether this category is enabled for a given {@link
    741      Level} passed as parameter.
    742
    743      See also {@link #isDebugEnabled}.
    744
    745      @return boolean True if this category is enabled for <code>level</code>.
    746   */
    747   public
    748   boolean isEnabledFor(Priority level) {
    749     if(repository.isDisabled(level.level))
    750       return false;
    751     return level.isGreaterOrEqual(this.getEffectiveLevel());
    752   }
    753
    754   /***
    755     Check whether this category is enabled for the info Level.
    756     See also {@link #isDebugEnabled}.
    757
    758     @return boolean - <code>true</code> if this category is enabled
    759     for level info, <code>false</code> otherwise.
    760   */
    761   public
    762   boolean isInfoEnabled() {
    763     if(repository.isDisabled(Level.INFO_INT))
    764       return false;
    765     return Level.INFO.isGreaterOrEqual(this.getEffectiveLevel());
    766   }
    767
    768
    769   /***
    770      Log a localized message. The user supplied parameter
    771      <code>key</code> is replaced by its localized version from the
    772      resource bundle.
    773
    774      @see #setResourceBundle
    775
    776      @since 0.8.4 */
    777   public
    778   void l7dlog(Priority priority, String key, Throwable t) {
    779     if(repository.isDisabled(priority.level)) {
    780       return;
    781     }
    782     if(priority.isGreaterOrEqual(this.getEffectiveLevel())) {
    783       String msg = getResourceBundleString(key);
    784       // if message corresponding to 'key' could not be found in the
    785       // resource bundle, then default to 'key'.
    786       if(msg == null) {
    787 	msg = key;
    788       }
    789       forcedLog(FQCN, priority, msg, t);
    790     }
    791   }
    792   /***
    793      Log a localized and parameterized message. First, the user
    794      supplied <code>key</code> is searched in the resource
    795      bundle. Next, the resulting pattern is formatted using
    796      {@link java.text.MessageFormat#format(String,Object[])} method with the
    797      user supplied object array <code>params</code>.
    798
    799      @since 0.8.4
    800   */
    801   public
    802   void l7dlog(Priority priority, String key,  Object[] params, Throwable t) {
    803     if(repository.isDisabled(priority.level)) {
    804       return;
    805     }
    806     if(priority.isGreaterOrEqual(this.getEffectiveLevel())) {
    807       String pattern = getResourceBundleString(key);
    808       String msg;
    809       if(pattern == null)
    810 	msg = key;
    811       else
    812 	msg = java.text.MessageFormat.format(pattern, params);
    813       forcedLog(FQCN, priority, msg, t);
    814     }
    815   }
    816
    817   /***
    818      This generic form is intended to be used by wrappers.
    819    */
    820   public
    821   void log(Priority priority, Object message, Throwable t) {
    822     if(repository.isDisabled(priority.level)) {
    823       return;
    824     }
    825     if(priority.isGreaterOrEqual(this.getEffectiveLevel()))
    826       forcedLog(FQCN, priority, message, t);
    827   }
    828
    829  /***
    830     This generic form is intended to be used by wrappers.
    831  */
    832   public
    833   void log(Priority priority, Object message) {
    834     if(repository.isDisabled(priority.level)) {
    835       return;
    836     }
    837     if(priority.isGreaterOrEqual(this.getEffectiveLevel()))
    838       forcedLog(FQCN, priority, message, null);
    839   }
    840
    841   /***
    842
    843      This is the most generic printing method. It is intended to be
    844      invoked by <b>wrapper</b> classes.
    845
    846      @param callerFQCN The wrapper class' fully qualified class name.
    847      @param level The level of the logging request.
    848      @param message The message of the logging request.
    849      @param t The throwable of the logging request, may be null.  */
    850   public
    851   void log(String callerFQCN, Priority level, Object message, Throwable t) {
    852     if(repository.isDisabled(level.level)) {
    853       return;
    854     }
    855     if(level.isGreaterOrEqual(this.getEffectiveLevel())) {
    856       forcedLog(callerFQCN, level, message, t);
    857     }
    858   }
    859
    860     /***
    861       *  LoggerRepository forgot the fireRemoveAppenderEvent method,
    862       *     if using the stock Hierarchy implementation, then call its fireRemove.
    863       *     Custom repositories can implement HierarchyEventListener if they
    864       *     want remove notifications.
    865      * @param appender appender, may be null.
    866      */
    867    private void fireRemoveAppenderEvent(final Appender appender) {
    868        if (appender != null) {
    869          if (repository instanceof Hierarchy) {
    870            ((Hierarchy) repository).fireRemoveAppenderEvent(this, appender);
    871          } else if (repository instanceof HierarchyEventListener) {
    872              ((HierarchyEventListener) repository).removeAppenderEvent(this, appender);
    873          }
    874        }
    875    }
    876
    877   /***
    878      Remove all previously added appenders from this Category
    879      instance.
    880
    881      <p>This is useful when re-reading configuration information.
    882   */
    883   synchronized
    884   public
    885   void removeAllAppenders() {
    886     if(aai != null) {
    887       Vector appenders = new Vector();
    888       for (Enumeration iter = aai.getAllAppenders(); iter.hasMoreElements();) {
    889           appenders.add(iter.nextElement());
    890       }
    891       aai.removeAllAppenders();
    892       for(Enumeration iter = appenders.elements(); iter.hasMoreElements();) {
    893           fireRemoveAppenderEvent((Appender) iter.nextElement());
    894       }
    895       aai = null;
    896     }
    897   }
    898
    899
    900   /***
    901      Remove the appender passed as parameter form the list of appenders.
    902
    903      @since 0.8.2
    904   */
    905   synchronized
    906   public
    907   void removeAppender(Appender appender) {
    908     if(appender == null || aai == null)
    909       return;
    910     boolean wasAttached = aai.isAttached(appender);
    911     aai.removeAppender(appender);
    912     if (wasAttached) {
    913         fireRemoveAppenderEvent(appender);
    914     }
    915   }
    916
    917   /***
    918      Remove the appender with the name passed as parameter form the
    919      list of appenders.
    920
    921      @since 0.8.2 */
    922   synchronized
    923   public
    924   void removeAppender(String name) {
    925     if(name == null || aai == null) return;
    926     Appender appender = aai.getAppender(name);
    927     aai.removeAppender(name);
    928     if (appender != null) {
    929         fireRemoveAppenderEvent(appender);
    930     }
    931   }
    932
    933   /***
    934      Set the additivity flag for this Category instance.
    935      @since 0.8.1
    936    */
    937   public
    938   void setAdditivity(boolean additive) {
    939     this.additive = additive;
    940   }
    941
    942   /***
    943      Only the Hiearchy class can set the hiearchy of a
    944      category. Default package access is MANDATORY here.  */
    945   final
    946   void setHierarchy(LoggerRepository repository) {
    947     this.repository = repository;
    948   }
    949
    950   /***
    951      Set the level of this Category. If you are passing any of
    952      <code>Level.DEBUG</code>, <code>Level.INFO</code>,
    953      <code>Level.WARN</code>, <code>Level.ERROR</code>,
    954      <code>Level.FATAL</code> as a parameter, you need to case them as
    955      Level.
    956
    957      <p>As in <pre> &nbsp;&nbsp;&nbsp;logger.setLevel((Level) Level.DEBUG); </pre>
    958
    959
    960      <p>Null values are admitted.  */
    961   public
    962   void setLevel(Level level) {
    963     this.level = level;
    964   }
    965
    966
    967   /***
    968      Set the level of this Category.
    969
    970      <p>Null values are admitted.
    971
    972      @deprecated Please use {@link #setLevel} instead.
    973   */
    974   public
    975   void setPriority(Priority priority) {
    976     this.level = (Level) priority;
    977   }
    978
    979
    980   /***
    981      Set the resource bundle to be used with localized logging
    982      methods {@link #l7dlog(Priority,String,Throwable)} and {@link
    983      #l7dlog(Priority,String,Object[],Throwable)}.
    984
    985      @since 0.8.4
    986    */
    987   public
    988   void setResourceBundle(ResourceBundle bundle) {
    989     resourceBundle = bundle;
    990   }
    991
    992   /***
    993      Calling this method will <em>safely</em> close and remove all
    994      appenders in all the categories including root contained in the
    995      default hierachy.
    996
    997      <p>Some appenders such as {@link org.apache.log4j.net.SocketAppender}
    998      and {@link AsyncAppender} need to be closed before the
    999      application exists. Otherwise, pending logging events might be
    1000      lost.
    1001
    1002      <p>The <code>shutdown</code> method is careful to close nested
    1003      appenders before closing regular appenders. This is allows
    1004      configurations where a regular appender is attached to a category
    1005      and again to a nested appender.
    1006
    1007      @deprecated Please use {@link LogManager#shutdown()} instead.
    1008
    1009      @since 1.0
    1010   */
    1011   public
    1012   static
    1013   void shutdown() {
    1014     LogManager.shutdown();
    1015   }
    1016
    1017
    1018   /***
    1019     Log a message object with the {@link Level#WARN WARN} Level.
    1020
    1021     <p>This method first checks if this category is <code>WARN</code>
    1022     enabled by comparing the level of this category with {@link
    1023     Level#WARN WARN} Level. If the category is <code>WARN</code>
    1024     enabled, then it converts the message object passed as parameter
    1025     to a string by invoking the appropriate
    1026     {@link org.apache.log4j.or.ObjectRenderer}. It
    1027     proceeds to call all the registered appenders in this category and
    1028     also higher in the hieararchy depending on the value of the
    1029     additivity flag.
    1030
    1031     <p><b>WARNING</b> Note that passing a {@link Throwable} to this
    1032     method will print the name of the Throwable but no stack trace. To
    1033     print a stack trace use the {@link #warn(Object, Throwable)} form
    1034     instead.  <p>
    1035
    1036     @param message the message object to log.  */
    1037   public
    1038   void warn(Object message) {
    1039     if(repository.isDisabled( Level.WARN_INT))
    1040       return;
    1041
    1042     if(Level.WARN.isGreaterOrEqual(this.getEffectiveLevel()))
    1043       forcedLog(FQCN, Level.WARN, message, null);
    1044   }
    1045
    1046   /***
    1047    Log a message with the <code>WARN</code> level including the
    1048    stack trace of the {@link Throwable} <code>t</code> passed as
    1049    parameter.
    1050
    1051    <p>See {@link #warn(Object)} for more detailed information.
    1052
    1053    @param message the message object to log.
    1054    @param t the exception to log, including its stack trace.  */
    1055   public
    1056   void warn(Object message, Throwable t) {
    1057     if(repository.isDisabled(Level.WARN_INT))
    1058       return;
    1059     if(Level.WARN.isGreaterOrEqual(this.getEffectiveLevel()))
    1060       forcedLog(FQCN, Level.WARN, message, t);
    1061   }
    1062 }