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 // Deprecated form: 68 Category cat = Category.getInstance("foo.bar") 69 70 // Preferred form for retrieving loggers: 71 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ülcü 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 != null && 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> 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 }