1 22 package org.jboss.logging; 23 24 import java.io.IOException ; 25 import java.io.PrintStream ; 26 import java.net.MalformedURLException ; 27 import java.net.URL ; 28 import java.net.URLConnection ; 29 import java.util.StringTokenizer ; 30 import java.util.Timer ; 31 import java.util.TimerTask ; 32 33 import javax.management.MBeanServer ; 34 import javax.management.MalformedObjectNameException ; 35 import javax.management.Notification ; 36 import javax.management.ObjectName ; 37 38 import org.apache.log4j.Level; 39 import org.apache.log4j.PropertyConfigurator; 40 import org.apache.log4j.helpers.LogLog; 41 import org.apache.log4j.xml.DOMConfigurator; 42 import org.jboss.logging.util.LoggerStream; 43 import org.jboss.logging.util.OnlyOnceErrorHandler; 44 import org.jboss.system.ServiceMBeanSupport; 45 import org.jboss.util.Strings; 46 import org.jboss.util.ThrowableHandler; 47 import org.jboss.util.ThrowableListener; 48 import org.jboss.util.stream.Streams; 49 50 70 public class Log4jService 71 extends ServiceMBeanSupport 72 implements Log4jServiceMBean 73 { 74 79 public static final String DEFAULT_URL = 80 System.getProperty(Log4jService.class.getName() + ".configURL", "resource:log4j.xml"); 81 82 87 public static final boolean CATCH_SYSTEM_OUT = 88 getBoolean(Log4jService.class.getName() + ".catchSystemOut", true); 89 90 95 public static final boolean CATCH_SYSTEM_ERR = 96 getBoolean(Log4jService.class.getName() + ".catchSystemErr", true); 97 98 99 private static boolean getBoolean(String name, boolean defaultValue) 100 { 101 String value = System.getProperty(name, null); 102 if (value == null) 103 return defaultValue; 104 return new Boolean (value).booleanValue(); 105 } 106 107 108 private URL configURL; 109 110 111 private int refreshPeriod; 112 113 private ThrowableListenerLoggingAdapter throwableAdapter; 114 115 116 private PrintStream out; 117 118 119 private PrintStream err; 120 121 125 private boolean catchSystemOut = CATCH_SYSTEM_OUT; 126 127 131 private boolean catchSystemErr = CATCH_SYSTEM_ERR; 132 133 134 private boolean log4jQuietMode = true; 135 136 137 private Timer timer; 138 139 140 private URLWatchTimerTask timerTask; 141 142 146 private boolean initialized; 147 148 156 public Log4jService() throws MalformedURLException 157 { 158 this(DEFAULT_URL, 60); 159 } 160 161 166 public Log4jService(final URL url) 167 { 168 this(url, 60); 169 } 170 171 176 public Log4jService(final String url) throws MalformedURLException 177 { 178 this(Strings.toURL(url), 60); 179 } 180 181 187 public Log4jService(final String url, final int refreshPeriod) 188 throws MalformedURLException 189 { 190 this(Strings.toURL(url), refreshPeriod); 191 } 192 193 199 public Log4jService(final URL url, final int refreshPeriod) 200 { 201 this.configURL = url; 202 this.refreshPeriod = refreshPeriod; 203 } 204 205 212 public void setCatchSystemOut(final boolean flag) 213 { 214 this.catchSystemOut = flag; 215 } 216 217 224 public boolean getCatchSystemOut() 225 { 226 return catchSystemOut; 227 } 228 229 236 public void setCatchSystemErr(final boolean flag) 237 { 238 this.catchSystemErr = flag; 239 } 240 241 248 public boolean getCatchSystemErr() 249 { 250 return catchSystemErr; 251 } 252 253 260 public boolean getLog4jQuietMode() 261 { 262 return log4jQuietMode; 263 } 264 271 public void setLog4jQuietMode(boolean flag) 272 { 273 this.log4jQuietMode = flag; 274 } 275 276 281 public int getRefreshPeriod() 282 { 283 return refreshPeriod; 284 } 285 286 291 public void setRefreshPeriod(final int refreshPeriod) 292 { 293 this.refreshPeriod = refreshPeriod; 294 } 295 296 301 public URL getConfigurationURL() 302 { 303 return configURL; 304 } 305 306 311 public void setConfigurationURL(final URL url) 312 { 313 this.configURL = url; 314 } 315 316 326 public void setLoggerLevel(final String name, final String levelName) 327 { 328 org.apache.log4j.Logger logger = org.apache.log4j.Logger.getLogger(name.trim()); 329 Level level = XLevel.toLevel(levelName.trim()); 330 331 logger.setLevel(level); 332 log.info("Level set to " + level + " for " + name); 333 } 334 335 346 public void setLoggerLevels(final String list, final String levelName) 347 { 348 StringTokenizer stok = new StringTokenizer (list, ","); 349 350 while (stok.hasMoreTokens()) { 351 String name = stok.nextToken(); 352 setLoggerLevel(name, levelName); 353 } 354 } 355 356 363 public String getLoggerLevel(final String name) 364 { 365 org.apache.log4j.Logger logger = org.apache.log4j.Logger.getLogger(name); 366 Level level = logger.getLevel(); 367 368 if (level != null) 369 return level.toString(); 370 371 return null; 372 } 373 374 379 public void reconfigure() throws IOException 380 { 381 if (timerTask == null) 382 throw new IllegalStateException ("Service stopped or not started"); 383 384 timerTask.reconfigure(); 385 } 386 387 395 public void reconfigure(final String url) throws IOException , MalformedURLException 396 { 397 setConfigurationURL(Strings.toURL(url)); 398 reconfigure(); 399 } 400 401 private void installSystemAdapters() 402 { 403 org.apache.log4j.Logger logger; 404 405 if (catchSystemOut) 407 { 408 logger = org.apache.log4j.Logger.getLogger("STDOUT"); 409 out = System.out; 410 System.setOut(new LoggerStream(logger, Level.INFO, out)); 411 log.debug("Installed System.out adapter"); 412 } 413 414 if (catchSystemErr) 415 { 416 logger = org.apache.log4j.Logger.getLogger("STDERR"); 417 err = System.err; 418 OnlyOnceErrorHandler.setOutput(err); 419 System.setErr(new LoggerStream(logger, Level.ERROR, err)); 420 log.debug("Installed System.err adapter"); 421 } 422 } 423 424 private void uninstallSystemAdapters() 425 { 426 if (out != null) 428 { 429 System.out.flush(); 430 System.setOut(out); 431 log.debug("Removed System.out adapter"); 432 out = null; 433 } 434 435 if (err != null) 436 { 437 System.err.flush(); 438 System.setErr(err); 439 log.debug("Removed System.err adapter"); 440 err = null; 441 } 442 } 443 444 445 449 protected ObjectName getObjectName(MBeanServer server, ObjectName name) 450 throws MalformedObjectNameException 451 { 452 return name == null ? OBJECT_NAME : name; 453 } 454 455 private void setup() throws Exception 456 { 457 if (initialized) return; 458 459 timerTask = new URLWatchTimerTask(); 460 timerTask.run(); 461 timer = new Timer ("Timer-" + getName(), true); 462 timer.schedule(timerTask, 1000 * refreshPeriod, 1000 * refreshPeriod); 463 464 org.apache.log4j.Logger.getRootLogger(); 466 467 throwableAdapter = new ThrowableListenerLoggingAdapter(); 469 ThrowableHandler.addThrowableListener(throwableAdapter); 470 log.debug("Added ThrowableListener: " + throwableAdapter); 471 472 initialized = true; 473 } 474 475 protected void createService() throws Exception 476 { 477 setup(); 478 } 479 480 protected void startService() throws Exception 481 { 482 setup(); 483 } 484 485 protected void stopService() throws Exception 486 { 487 timer.cancel(); 488 timer = null; 489 timerTask.cancel(); 490 timerTask = null; 491 492 ThrowableHandler.removeThrowableListener(throwableAdapter); 494 throwableAdapter = null; 495 496 uninstallSystemAdapters(); 497 498 initialized = false; 500 } 501 502 protected void emitReconfigureNotification() 503 { 504 Notification n = new Notification (RECONFIGURE_NOTIFICATION_TYPE, 506 this, getNextNotificationSequenceNumber(), "Log4j subsystem reconfigured"); 507 n.setUserData(configURL); 508 509 super.sendNotification(n); 510 } 511 512 516 520 private static class ThrowableListenerLoggingAdapter 521 implements ThrowableListener 522 { 523 private Logger log = Logger.getLogger(ThrowableListenerLoggingAdapter.class); 524 525 public void onThrowable(int type, Throwable t) 526 { 527 switch (type) 528 { 529 default: 530 532 case ThrowableHandler.Type.ERROR: 533 log.error("Unhandled Throwable", t); 534 break; 535 536 case ThrowableHandler.Type.WARNING: 537 log.warn("Unhandled Throwable", t); 538 break; 539 540 case ThrowableHandler.Type.UNKNOWN: 541 log.trace("Ynhandled Throwable; status is unknown", t); 543 break; 544 } 545 } 546 } 547 548 549 553 557 private class URLWatchTimerTask 558 extends TimerTask 559 { 560 private Logger log = Logger.getLogger(URLWatchTimerTask.class); 561 562 private long lastConfigured = -1; 563 564 public void run() 565 { 566 log.trace("Checking if configuration changed"); 567 568 boolean trace = log.isTraceEnabled(); 569 570 try 571 { 572 URLConnection conn = configURL.openConnection(); 573 if (trace) 574 log.trace("connection: " + conn); 575 576 long lastModified = conn.getLastModified(); 577 if (trace) 578 { 579 log.trace("last configured: " + lastConfigured); 580 log.trace("last modified: " + lastModified); 581 } 582 583 if (lastConfigured < lastModified) 584 { 585 reconfigure(conn); 586 } 587 } 588 catch (Exception e) 589 { 590 log.warn("Failed to check URL: " + configURL, e); 591 } 592 } 593 594 public void reconfigure() throws IOException 595 { 596 URLConnection conn = configURL.openConnection(); 597 reconfigure(conn); 598 } 599 600 private void reconfigure(final URLConnection conn) 601 { 602 log.debug("Configuring from URL: " + configURL); 603 604 boolean xml = false; 605 boolean trace = log.isTraceEnabled(); 606 607 String contentType = conn.getContentType(); 609 if (trace) 610 log.trace("content type: " + contentType); 611 612 if (contentType == null) 613 { 614 String filename = configURL.getFile().toLowerCase(); 615 if (trace) log.trace("filename: " + filename); 616 617 xml = filename.endsWith(".xml"); 618 } 619 else 620 { 621 xml = contentType.equalsIgnoreCase("text/xml"); 622 xml |= contentType.equalsIgnoreCase("application/xml"); 623 } 624 if (trace) 625 log.trace("reconfiguring; xml=" + xml); 626 627 if (trace) 629 { 630 try 631 { 632 java.io.InputStream is = conn.getInputStream(); 633 Streams.copy(is, System.out); 634 } 635 catch (Exception e) 636 { 637 log.error("Failed to dump config", e); 638 } 639 } 640 641 uninstallSystemAdapters(); 643 644 if (xml) 645 { 646 DOMConfigurator.configure(configURL); 647 } 648 else 649 { 650 PropertyConfigurator.configure(configURL); 651 } 652 653 656 LogLog.setQuietMode(log4jQuietMode); 657 658 installSystemAdapters(); 660 661 lastConfigured = System.currentTimeMillis(); 663 664 emitReconfigureNotification(); 666 } 667 } 668 } 669 | Popular Tags |