001 /** 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017 018 package org.apache.geronimo.system.logging.log4j; 019 020 import java.io.BufferedReader; 021 import java.io.File; 022 import java.io.FileInputStream; 023 import java.io.FileOutputStream; 024 import java.io.IOException; 025 import java.io.InputStreamReader; 026 import java.io.OutputStream; 027 import java.io.Reader; 028 import java.net.MalformedURLException; 029 import java.util.ArrayList; 030 import java.util.Enumeration; 031 import java.util.Iterator; 032 import java.util.LinkedList; 033 import java.util.List; 034 import java.util.Set; 035 import java.util.Timer; 036 import java.util.TimerTask; 037 import java.util.regex.Matcher; 038 import java.util.regex.Pattern; 039 import java.util.regex.PatternSyntaxException; 040 041 import org.apache.commons.logging.Log; 042 import org.apache.commons.logging.LogConfigurationException; 043 import org.apache.commons.logging.LogFactory; 044 import org.apache.geronimo.gbean.GBeanInfo; 045 import org.apache.geronimo.gbean.GBeanInfoBuilder; 046 import org.apache.geronimo.gbean.GBeanLifecycle; 047 import org.apache.geronimo.kernel.log.GeronimoLogFactory; 048 import org.apache.geronimo.kernel.log.GeronimoLogging; 049 import org.apache.geronimo.system.logging.SystemLog; 050 import org.apache.geronimo.system.properties.JvmVendor; 051 import org.apache.geronimo.system.serverinfo.DirectoryUtils; 052 import org.apache.geronimo.system.serverinfo.ServerInfo; 053 import org.apache.log4j.FileAppender; 054 import org.apache.log4j.Level; 055 import org.apache.log4j.LogManager; 056 import org.apache.log4j.Logger; 057 058 /** 059 * A Log4j logging service. 060 * 061 * @version $Rev: 706640 $ $Date: 2008-10-21 14:44:05 +0000 (Tue, 21 Oct 2008) $ 062 */ 063 public class Log4jService implements GBeanLifecycle, SystemLog { 064 // A substitution variable in the file path in the config file 065 private final static Pattern VARIABLE_PATTERN = Pattern.compile("\\$\\{.*?\\}"); 066 // Next 6 are patterns that identify log messages in our default format 067 private final static Pattern DEFAULT_ANY_START = Pattern.compile("^\\d\\d\\:\\d\\d\\:\\d\\d\\,\\d\\d\\d (TRACE|DEBUG|INFO|WARN|ERROR|FATAL) .*"); 068 private final static Pattern DEFAULT_FATAL_START = Pattern.compile("^\\d\\d\\:\\d\\d\\:\\d\\d\\,\\d\\d\\d FATAL .*"); 069 private final static Pattern DEFAULT_ERROR_START = Pattern.compile("^\\d\\d\\:\\d\\d\\:\\d\\d\\,\\d\\d\\d (ERROR|FATAL) .*"); 070 private final static Pattern DEFAULT_WARN_START = Pattern.compile("^\\d\\d\\:\\d\\d\\:\\d\\d\\,\\d\\d\\d (WARN|ERROR|FATAL) .*"); 071 private final static Pattern DEFAULT_INFO_START = Pattern.compile("^\\d\\d\\:\\d\\d\\:\\d\\d\\,\\d\\d\\d (INFO|WARN|ERROR|FATAL) .*"); 072 private final static Pattern DEFAULT_DEBUG_START = Pattern.compile("^\\d\\d\\:\\d\\d\\:\\d\\d\\,\\d\\d\\d (DEBUG|INFO|WARN|ERROR|FATAL) .*"); 073 // Next 6 are patterns that identify log messages if the user changed the format -- but we assume the log level is in there somewhere 074 private final static Pattern UNKNOWN_ANY_START = Pattern.compile("(TRACE|DEBUG|INFO|WARN|ERROR|FATAL)"); 075 private final static Pattern UNKNOWN_FATAL_START = Pattern.compile("FATAL"); 076 private final static Pattern UNKNOWN_ERROR_START = Pattern.compile("(ERROR|FATAL)"); 077 private final static Pattern UNKNOWN_WARN_START = Pattern.compile("(WARN|ERROR|FATAL)"); 078 private final static Pattern UNKNOWN_INFO_START = Pattern.compile("(INFO|WARN|ERROR|FATAL)"); 079 private final static Pattern UNKNOWN_DEBUG_START = Pattern.compile("(DEBUG|INFO|WARN|ERROR|FATAL)"); 080 081 private final static Log log = LogFactory.getLog(Log4jService.class); 082 083 private static final String LOG4JSERVICE_CONFIG_PROPERTY = "org.apache.geronimo.log4jservice.configuration"; 084 085 /** 086 * The URL to the configuration file. 087 */ 088 private String configurationFile; 089 090 /** 091 * The time (in seconds) between checking for new config. 092 */ 093 private int refreshPeriod; 094 095 /** 096 * The properties service 097 */ 098 private final ServerInfo serverInfo; 099 100 /** 101 * The URL watch timer (in daemon mode). 102 */ 103 private Timer timer = new Timer(true); 104 105 /** 106 * A monitor to check when the config URL changes. 107 */ 108 private TimerTask monitor; 109 110 /** 111 * Last time the file was changed. 112 */ 113 private long lastChanged = -1; 114 115 /** 116 * Is this service running? 117 */ 118 private boolean running = false; 119 120 /** 121 * Construct a <code>Log4jService</code>. 122 * 123 * @param configurationFile The log4j configuration file. 124 * @param refreshPeriod The refresh refreshPeriod (in seconds). 125 */ 126 public Log4jService(final String configurationFile, final int refreshPeriod, ServerInfo serverInfo) { 127 this.refreshPeriod = refreshPeriod; 128 this.configurationFile = configurationFile; 129 this.serverInfo = serverInfo; 130 Logger.getLogger(this.getClass().getName()).setLevel(Level.INFO); 131 } 132 133 /** 134 * Gets the level of the root logger. 135 */ 136 public synchronized String getRootLoggerLevel() { 137 Level level = LogManager.getRootLogger().getLevel(); 138 139 if (level != null) { 140 return level.toString(); 141 } 142 143 return null; 144 } 145 146 /** 147 * Sets the level of the root logger. 148 * 149 * @param level The level to change the logger to. 150 */ 151 public synchronized void setRootLoggerLevel(final String level) { 152 153 String currentLevel = this.getRootLoggerLevel(); 154 155 // ensure that the level has really been changed 156 if (!currentLevel.equals(level)) { 157 LogManager.getRootLogger().setLevel(XLevel.toLevel(level)); 158 } 159 } 160 161 /** 162 * Gets the level of the logger of the give name. 163 * 164 * @param logger The logger to inspect. 165 */ 166 public String getLoggerEffectiveLevel(final String logger) { 167 if (logger == null) { 168 throw new IllegalArgumentException("logger is null"); 169 } 170 171 Level level = LogManager.getLogger(logger).getEffectiveLevel(); 172 173 if (level != null) { 174 return level.toString(); 175 } 176 177 return null; 178 } 179 180 /** 181 * Gets the level of the logger of the give name. 182 * 183 * @param logger The logger to inspect. 184 */ 185 public String getLoggerLevel(final String logger) { 186 if (logger == null) { 187 throw new IllegalArgumentException("logger is null"); 188 } 189 190 Level level = LogManager.getLogger(logger).getLevel(); 191 192 if (level != null) { 193 return level.toString(); 194 } 195 196 return null; 197 } 198 199 /** 200 * Sets the level for a logger of the give name. 201 * 202 * @param logger The logger to change level 203 * @param level The level to change the logger to. 204 */ 205 public void setLoggerLevel(final String logger, final String level) { 206 if (logger == null) { 207 throw new IllegalArgumentException("logger is null"); 208 } 209 if (level == null) { 210 throw new IllegalArgumentException("level is null"); 211 } 212 213 log.info("Setting logger level: logger=" + logger + ", level=" + level); 214 Logger.getLogger(logger).setLevel(XLevel.toLevel(level)); 215 } 216 217 /** 218 * Get the refresh period. 219 * 220 * @return the refresh period (in seconds) 221 */ 222 public synchronized int getRefreshPeriodSeconds() { 223 return refreshPeriod; 224 } 225 226 /** 227 * Set the refresh period. 228 * 229 * @param period the refresh period (in seconds) 230 * @throws IllegalArgumentException if refresh period is < 5 231 */ 232 public synchronized void setRefreshPeriodSeconds(final int period) { 233 if (period < 5) { 234 throw new IllegalArgumentException("Refresh period must be at least 5 seconds"); 235 } 236 237 if (this.refreshPeriod != period) { 238 this.refreshPeriod = period; 239 schedule(); 240 } 241 } 242 243 /** 244 * Get the logging configuration URL. 245 * 246 * @return the logging configuration URL 247 */ 248 public synchronized String getConfigFileName() { 249 return configurationFile; 250 } 251 252 /** 253 * Set the logging configuration URL. 254 * 255 * @param configurationFile the logging configuration file 256 */ 257 public synchronized void setConfigFileName(final String configurationFile) { 258 if (log.isDebugEnabled()) { 259 log.debug("setConfigFileName() called with configurationFile=" + configurationFile); 260 } 261 262 if (configurationFile == null) { 263 throw new IllegalArgumentException("configurationFile is null"); 264 } 265 266 // ensure that the file name has really been updated 267 if (!this.configurationFile.equals(configurationFile)) { 268 this.configurationFile = configurationFile; 269 lastChanged = -1; 270 reconfigure(); 271 } 272 } 273 274 /** 275 * Get the content of logging configuration file. 276 * 277 * @return the content of logging configuration file 278 */ 279 public synchronized String getConfiguration() { 280 File file = resolveConfigurationFile(); 281 if (file == null || !file.canRead()) { 282 return null; 283 } 284 Reader in = null; 285 try { 286 StringBuffer configuration = new StringBuffer(); 287 in = new InputStreamReader(new FileInputStream(file)); 288 char[] buffer = new char[4096]; 289 for (int size = in.read(buffer); size >= 0; size = in.read(buffer)) { 290 configuration.append(buffer, 0, size); 291 } 292 return configuration.toString(); 293 } catch (IOException e) { 294 e.printStackTrace(); 295 } finally { 296 if (in != null) { 297 try { 298 in.close(); 299 } catch (IOException e1) { 300 e1.printStackTrace(); 301 } 302 } 303 } 304 return null; 305 } 306 307 /** 308 * Overwrites the content of logging configuration file. 309 * 310 * @param configuration the new content of logging configuration file 311 */ 312 public synchronized void setConfiguration(final String configuration) throws IOException { 313 if (configuration == null || configuration.length() == 0) { 314 throw new IllegalArgumentException("configuration is null or an empty string"); 315 } 316 317 File file = resolveConfigurationFile(); 318 if (file == null) { 319 throw new IllegalStateException("Configuration file is null"); 320 } 321 322 // make parent directory if necessary 323 if (!file.getParentFile().exists()) { 324 if (!file.getParentFile().mkdirs()) { 325 throw new IllegalStateException("Could not create parent directory of log configuration file: " + file.getParent()); 326 } 327 } 328 329 // verify that the file is writable or does not exist 330 if (file.exists() && !file.canWrite()) { 331 throw new IllegalStateException("Configuration file is not writable: " + file.getAbsolutePath()); 332 } 333 334 OutputStream out = null; 335 try { 336 out = new FileOutputStream(file); 337 out.write(configuration.getBytes()); 338 log.info("Updated configuration file=" + file.toString()); 339 } finally { 340 if (out != null) { 341 try { 342 out.close(); 343 } catch (IOException e) { 344 e.printStackTrace(); 345 } 346 } 347 } 348 } 349 350 public synchronized String[] getLogFileNames() { 351 List list = new ArrayList(); 352 for (Enumeration e = Logger.getRootLogger().getAllAppenders(); e.hasMoreElements();) { 353 Object appender = e.nextElement(); 354 if (appender instanceof FileAppender) { 355 list.add(((FileAppender) appender).getFile()); 356 } 357 } 358 return (String[]) list.toArray(new String[list.size()]); 359 } 360 361 private static SearchResults searchFile(File file, String targetLevel, Pattern textSearch, Integer start, Integer stop, int max, boolean stacks) { 362 List list = new LinkedList(); 363 boolean capped = false; 364 int lineCount = 0; 365 FileInputStream logInputStream = null; 366 try { 367 logInputStream = new FileInputStream(file); 368 BufferedReader reader = new BufferedReader(new InputStreamReader(logInputStream, System.getProperty("file.encoding"))); 369 Matcher target = null; 370 Matcher any = null; 371 Matcher text = textSearch == null ? null : textSearch.matcher(""); 372 boolean hit = false; 373 max = Math.min(max, MAX_SEARCH_RESULTS); 374 String line; 375 while ((line = reader.readLine()) != null) { 376 ++lineCount; 377 if(target == null) { 378 if(DEFAULT_ANY_START.matcher(line).find()) { 379 target = getDefaultPatternForLevel(targetLevel).matcher(""); 380 any = DEFAULT_ANY_START.matcher(""); 381 } else { 382 target = getUnknownPatternForLevel(targetLevel).matcher(""); 383 any = UNKNOWN_ANY_START.matcher(""); 384 } 385 } 386 if(start != null && start.intValue() > lineCount) { 387 continue; 388 } 389 if(stop != null && stop.intValue() < lineCount) { 390 continue; 391 } 392 target.reset(line); 393 if(target.find()) { 394 if(text != null) { 395 text.reset(line); 396 if(!text.find()) { 397 hit = false; 398 continue; 399 } 400 } 401 list.add(new LogMessage(lineCount,line.toString())); 402 if(list.size() > max) { 403 list.remove(0); 404 capped = true; 405 } 406 hit = true; 407 } else if(stacks && hit) { 408 any.reset(line); 409 if(!any.find()) { 410 list.add(new LogMessage(lineCount,line.toString())); 411 if(list.size() > max) { 412 list.remove(0); 413 capped = true; 414 } 415 } else { 416 hit = false; 417 } 418 } 419 } 420 } catch (Exception e) { 421 // TODO: improve exception handling 422 } finally { 423 if (logInputStream != null) { 424 try { 425 logInputStream.close(); 426 } catch (IOException e) { 427 // ignore 428 } 429 } 430 } 431 return new SearchResults(lineCount, (LogMessage[]) list.toArray(new LogMessage[list.size()]), capped); 432 } 433 434 private static String substituteSystemProps(String source) { 435 StringBuffer buf = new StringBuffer(); 436 int last = 0; 437 Matcher m = VARIABLE_PATTERN.matcher(source); 438 while(m.find()) { 439 buf.append(source.substring(last, m.start())); 440 String prop = source.substring(m.start()+2, m.end()-1); 441 buf.append(System.getProperty(prop)); 442 last = m.end(); 443 } 444 buf.append(source.substring(last)); 445 return buf.toString(); 446 } 447 448 private static Pattern getDefaultPatternForLevel(String targetLevel) { 449 if(targetLevel.equals("FATAL")) { 450 return DEFAULT_FATAL_START; 451 } else if(targetLevel.equals("ERROR")) { 452 return DEFAULT_ERROR_START; 453 } else if(targetLevel.equals("WARN")) { 454 return DEFAULT_WARN_START; 455 } else if(targetLevel.equals("INFO")) { 456 return DEFAULT_INFO_START; 457 } else if(targetLevel.equals("DEBUG")) { 458 return DEFAULT_DEBUG_START; 459 } else { 460 return DEFAULT_ANY_START; 461 } 462 } 463 464 private static Pattern getUnknownPatternForLevel(String targetLevel) { 465 if(targetLevel.equals("FATAL")) { 466 return UNKNOWN_FATAL_START; 467 } else if(targetLevel.equals("ERROR")) { 468 return UNKNOWN_ERROR_START; 469 } else if(targetLevel.equals("WARN")) { 470 return UNKNOWN_WARN_START; 471 } else if(targetLevel.equals("INFO")) { 472 return UNKNOWN_INFO_START; 473 } else if(targetLevel.equals("DEBUG")) { 474 return UNKNOWN_DEBUG_START; 475 } else { 476 return UNKNOWN_ANY_START; 477 } 478 } 479 480 public SearchResults getMatchingItems(String logFile, Integer firstLine, Integer lastLine, String minLevel, String text, int maxResults, boolean includeStackTraces) { 481 // Ensure the file argument is really a log file! 482 if(logFile == null) { 483 throw new IllegalArgumentException("Must specify a log file"); 484 } 485 String[] files = getLogFileNames(); 486 boolean found = false; 487 for (int i = 0; i < files.length; i++) { 488 if(files[i].equals(logFile)) { 489 found = true; 490 break; 491 } 492 } 493 if(!found) { 494 throw new IllegalArgumentException("Not a log file!"); 495 } 496 // Check for valid log level 497 if(minLevel == null) { 498 minLevel = "TRACE"; 499 } else if(!minLevel.equals("FATAL") && !minLevel.equals("ERROR") && !minLevel.equals("WARN") && 500 !minLevel.equals("INFO") && !minLevel.equals("DEBUG") && !minLevel.equals("TRACE")) { 501 throw new IllegalArgumentException("Not a valid log level"); 502 } 503 // Check that the text pattern is valid 504 Pattern textPattern = null; 505 try { 506 textPattern = text == null || text.equals("") ? null : Pattern.compile(text); 507 } catch (PatternSyntaxException e) { 508 throw new IllegalArgumentException("Bad regular expression '"+text+"'", e); 509 } 510 // Make sure we can find the log file 511 File log = new File(substituteSystemProps(logFile)); 512 if(!log.exists()) { 513 throw new IllegalArgumentException("Log file "+log.getAbsolutePath()+" does not exist"); 514 } 515 // Run the search 516 return searchFile(log, minLevel, textPattern, firstLine, lastLine, maxResults, includeStackTraces); 517 } 518 519 /** 520 * Force the logging system to reconfigure. 521 */ 522 public void reconfigure() { 523 File file = resolveConfigurationFile(); 524 if (file == null || !file.exists()) { 525 return; 526 } else { 527 if (log.isDebugEnabled()) { 528 log.debug("reconfigure() using configurationFile=" + configurationFile); 529 } 530 lastChanged = file.lastModified(); 531 } 532 533 // Record the default console log level 534 System.setProperty("org.apache.geronimo.log.ConsoleLogLevel", GeronimoLogging.getConsoleLogLevel().toString()); 535 536 try { 537 URLConfigurator.configure(file.toURL()); 538 } catch (MalformedURLException e) { 539 e.printStackTrace(); 540 } 541 542 // refresh the level info for every log 543 GeronimoLogFactory logFactory = (GeronimoLogFactory) LogFactory.getFactory(); 544 Set instances = logFactory.getInstances(); 545 for (Iterator iterator = instances.iterator(); iterator.hasNext();) { 546 Object log = iterator.next(); 547 if (log instanceof CachingLog4jLog) { 548 ((CachingLog4jLog)log).updateLevelInfo(); 549 } 550 } 551 } 552 553 private synchronized void schedule() { 554 if (timer != null) { 555 // kill the old monitor 556 if (monitor != null) { 557 monitor.cancel(); 558 } 559 560 // start the new one 561 monitor = new URLMonitorTask(); 562 TimerTask task = monitor; 563 timer.schedule(monitor, 1000 * refreshPeriod, 1000 * refreshPeriod); 564 task.run(); 565 } 566 } 567 568 public void doStart() { 569 LogFactory logFactory = LogFactory.getFactory(); 570 if (logFactory instanceof GeronimoLogFactory) { 571 // Make sure the root Logger has loaded 572 Logger logger = LogManager.getRootLogger(); 573 574 // Change all of the loggers over to use log4j 575 GeronimoLogFactory geronimoLogFactory = (GeronimoLogFactory) logFactory; 576 synchronized (geronimoLogFactory) { 577 if (!(geronimoLogFactory.getLogFactory() instanceof CachingLog4jLogFactory)) { 578 geronimoLogFactory.setLogFactory(new CachingLog4jLogFactory()); 579 } 580 } 581 582 // Allow users to override the configurationFile which is hardcoded 583 // in config.ser and cannot be updated by config.xml, as the 584 // AttrbiuteManager comes up after this GBean 585 String cfgFile = System.getProperty(LOG4JSERVICE_CONFIG_PROPERTY); 586 if ((cfgFile != null) && (!cfgFile.equals(""))) { 587 this.configurationFile = cfgFile; 588 } 589 590 synchronized (this) { 591 reconfigure(); 592 593 timer = new Timer(true); 594 595 // Periodically check the configuration file 596 schedule(); 597 } 598 599 logEnvInfo(); 600 } 601 602 synchronized (this) { 603 running = true; 604 } 605 } 606 607 public synchronized void doStop() { 608 running = false; 609 if (monitor != null) { 610 monitor.cancel(); 611 monitor = null; 612 } 613 if (timer != null) { 614 timer.cancel(); 615 timer = null; 616 } 617 } 618 619 public void doFail() { 620 doStop(); 621 } 622 623 private synchronized File resolveConfigurationFile() { 624 try { 625 return serverInfo.resolveServer(configurationFile); 626 } catch (Exception e) { 627 return null; 628 } 629 } 630 631 private void logEnvInfo() { 632 try { 633 Log log = LogFactory.getLog(Log4jService.class); 634 log.info("----------------------------------------------"); 635 log.info("Started Logging Service"); 636 if (log.isDebugEnabled()) { 637 log.debug("Log4jService created with configFileName=" + this.configurationFile + ", refreshPeriodSeconds=" + this.refreshPeriod); 638 } 639 log.info("Runtime Information:"); 640 log.info(" Install Directory = " + DirectoryUtils.getGeronimoInstallDirectory().toString()); 641 log.info(" JVM in use = " + JvmVendor.getJvmInfo()); 642 log.info("Java Information:"); 643 log.info(" System property [java.runtime.name] = " + System.getProperty("java.runtime.name")); 644 log.info(" System property [java.runtime.version] = " + System.getProperty("java.runtime.version")); 645 log.info(" System property [os.name] = " + System.getProperty("os.name")); 646 log.info(" System property [os.version] = " + System.getProperty("os.version")); 647 log.info(" System property [sun.os.patch.level] = " + System.getProperty("sun.os.patch.level")); 648 log.info(" System property [os.arch] = " + System.getProperty("os.arch")); 649 log.info(" System property [java.class.version] = " + System.getProperty("java.class.version")); 650 log.info(" System property [locale] = " + System.getProperty("user.language") + "_" + System.getProperty("user.country")); 651 log.info(" System property [unicode.encoding] = " + System.getProperty("sun.io.unicode.encoding")); 652 log.info(" System property [file.encoding] = " + System.getProperty("file.encoding")); 653 log.info(" System property [java.vm.name] = " + System.getProperty("java.vm.name")); 654 log.info(" System property [java.vm.vendor] = " + System.getProperty("java.vm.vendor")); 655 log.info(" System property [java.vm.version] = " + System.getProperty("java.vm.version")); 656 log.info(" System property [java.vm.info] = " + System.getProperty("java.vm.info")); 657 log.info(" System property [java.home] = " + System.getProperty("java.home")); 658 log.info(" System property [java.classpath] = " + System.getProperty("java.classpath")); 659 log.info(" System property [java.library.path] = " + System.getProperty("java.library.path")); 660 log.info(" System property [java.endorsed.dirs] = " + System.getProperty("java.endorsed.dirs")); 661 log.info(" System property [java.ext.dirs] = " + System.getProperty("java.ext.dirs")); 662 log.info(" System property [sun.boot.class.path] = " + System.getProperty("sun.boot.class.path")); 663 log.info("----------------------------------------------"); 664 } catch (Exception e) { 665 System.err.println("Exception caught during logging of Runtime Information. Exception=" + e.toString()); 666 } 667 } 668 669 670 private class URLMonitorTask extends TimerTask { 671 public void run() { 672 try { 673 long lastModified; 674 synchronized (this) { 675 if (running == false) { 676 return; 677 } 678 679 File file = resolveConfigurationFile(); 680 if (file == null) { 681 return; 682 } 683 684 lastModified = file.lastModified(); 685 } 686 687 if (lastChanged < lastModified) { 688 lastChanged = lastModified; 689 reconfigure(); 690 } 691 } catch (Exception e) { 692 } 693 } 694 } 695 696 private static class CachingLog4jLogFactory extends LogFactory { 697 public Log getInstance(Class clazz) throws LogConfigurationException { 698 return getInstance(clazz.getName()); 699 } 700 701 public Log getInstance(String name) throws LogConfigurationException { 702 return new CachingLog4jLog(name); 703 } 704 705 public Object getAttribute(String name) { 706 return null; 707 } 708 709 public String[] getAttributeNames() { 710 return new String[0]; 711 } 712 713 public void release() { 714 } 715 716 public void removeAttribute(String name) { 717 } 718 719 public void setAttribute(String name, Object value) { 720 } 721 } 722 723 public static final GBeanInfo GBEAN_INFO; 724 725 static { 726 GBeanInfoBuilder infoFactory = GBeanInfoBuilder.createStatic(Log4jService.class, "SystemLog"); 727 728 infoFactory.addAttribute("configFileName", String.class, true); 729 infoFactory.addAttribute("refreshPeriodSeconds", int.class, true); 730 infoFactory.addAttribute("configuration", String.class, false); 731 infoFactory.addAttribute("rootLoggerLevel", String.class, false); 732 733 infoFactory.addReference("ServerInfo", ServerInfo.class, "GBean"); 734 735 infoFactory.addOperation("reconfigure"); 736 infoFactory.addOperation("setLoggerLevel", new Class[]{String.class, String.class}); 737 infoFactory.addOperation("getLoggerLevel", new Class[]{String.class}); 738 infoFactory.addOperation("getLoggerEffectiveLevel", new Class[]{String.class}); 739 infoFactory.addInterface(SystemLog.class); 740 741 infoFactory.setConstructor(new String[]{"configFileName", "refreshPeriodSeconds", "ServerInfo"}); 742 743 GBEAN_INFO = infoFactory.getBeanInfo(); 744 } 745 746 public static GBeanInfo getGBeanInfo() { 747 return GBEAN_INFO; 748 } 749 }