001/** 002 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. 003 * 004 * Copyright (c) 2006 Sun Microsystems Inc. All Rights Reserved 005 * 006 * The contents of this file are subject to the terms 007 * of the Common Development and Distribution License 008 * (the License). You may not use this file except in 009 * compliance with the License. 010 * 011 * You can obtain a copy of the License at 012 * https://opensso.dev.java.net/public/CDDLv1.0.html or 013 * opensso/legal/CDDLv1.0.txt 014 * See the License for the specific language governing 015 * permission and limitations under the License. 016 * 017 * When distributing Covered Code, include this CDDL 018 * Header Notice in each file and include the License file 019 * at opensso/legal/CDDLv1.0.txt. 020 * If applicable, add the following below the CDDL Header, 021 * with the fields enclosed by brackets [] replaced by 022 * your own identifying information: 023 * "Portions Copyrighted [year] [name of copyright owner]" 024 * 025 * $Id: LogManager.java,v 1.14 2009/12/09 00:34:22 bigfatrat Exp $ 026 * 027 */ 028/* 029 * Portions Copyrighted 2011 ForgeRock AS 030 */ 031package com.sun.identity.log; 032 033import java.io.IOException; 034import java.io.File; 035import java.lang.reflect.Constructor; 036import java.util.Hashtable; 037import java.util.Set; 038import java.util.logging.Level; 039import java.util.Enumeration; 040import java.util.StringTokenizer; 041import java.util.logging.Handler; 042import java.util.HashSet; 043import java.util.logging.Formatter; 044 045import com.iplanet.am.util.SystemProperties; 046import com.iplanet.sso.SSOToken; 047import com.sun.identity.log.messageid.LogMessageProviderBase; 048import com.sun.identity.log.messageid.MessageProviderFactory; 049import com.sun.identity.log.spi.Debug; 050import com.sun.identity.log.s1is.LogConfigReader; 051import com.sun.identity.monitoring.Agent; 052import com.sun.identity.monitoring.MonitoringUtil; 053import com.sun.identity.monitoring.SsoServerLoggingSvcImpl; 054 055/** 056 * This class keeps track of all the logger objects and does all the 057 * bookkeeping work. It is extended from JDK's <code>LogManager</code> to add 058 * functionalities, such as adding our logger listening to DS changes, etc. 059 * @supported.all.api 060 */ 061public class LogManager extends java.util.logging.LogManager { 062 063 /** 064 * Is the Log Service running locally or remotely 065 */ 066 public static boolean isLocal = false; 067 /** 068 * The handler which will be added to each logger object 069 */ 070 public static String HANDLER = "Handler"; 071 /** 072 * The formatter which depends on the log settings 073 */ 074 public static String FORMATTER = "Formatter"; 075 076 public static boolean isMonitoringInit = false; 077 078 /* 079 * A list to maintain strong references to all loggers that are added, 080 * workaround for the file handle issue in OPENAM-184. 081 */ 082 private static Hashtable loggersTable; 083 084 085 /** 086 * Indicator for whether the first readConfiguration has happened 087 */ 088 private static boolean didFirstReadConfig; 089 private static final String strDEFAULT = "DEFAULT"; 090 private static String oldLocation = strDEFAULT; 091 private static String oldLevel = strDEFAULT; 092 private static String oldSecurityStatus = strDEFAULT; 093 private static String oldBackend = strDEFAULT; 094 private static String oldStatus = strDEFAULT; 095 private static String newLocation; 096 private static String newLevel; 097 private static String newSecurityStatus; 098 private static String newBackend; 099 private static String newStatus; 100 private final int OLDLOCATION = 0; 101 private final int NEWLOCATION = 1; 102 private final int OLDBACKEND = 2; 103 private final int NEWBACKEND = 3; 104 private final int OLDSECURITYSTATUS = 4; 105 private final int NEWSECURITYSTATUS = 5; 106 private final int OLDSTATUS = 6; 107 private final int NEWSTATUS = 7; 108 private final int OLDLEVEL = 8; 109 private final int NEWLEVEL = 9; 110 private static SsoServerLoggingSvcImpl logServiceImplForMonitoring = null; 111 private static int loggerCount = 0; 112 private String inactive = "INACTIVE"; 113 114 /** 115 * Adds a logger to the Log Manager. 116 * 117 * @param logger Logger object to be added to the Log Manager. 118 * @return true if the logger is added. 119 */ 120 public boolean addLogger(java.util.logging.Logger logger) { 121 String name = logger.getName(); 122 /* we have to pass root logger and global logger */ 123 if (name != null && name.length() != 0 && !name.equals("global")) { 124 /* we have to take care of the resourcebundle logger may have */ 125 String rbName = logger.getResourceBundleName(); 126 logger = new Logger(name, rbName); 127 } 128 boolean addSuccess = super.addLogger(logger); 129 130 // OPENAM-1110, loggersTable may not get initialized immediately, since we extend. 131 if (loggersTable == null) { 132 loggersTable = new Hashtable(); 133 } 134 // Workaround for OPENAM-184, maintains strong reference to the loggers until this class is collected 135 // The Hashtable will never be used to retrieve loggers, only to keep then strongly referenced 136 loggersTable.put(name, logger); 137 138 if(addSuccess){ 139 Enumeration loggerNames = getLoggerNames(); 140 int lcnt = 0; 141 while (loggerNames.hasMoreElements()) { 142 String curEl = (String) loggerNames.nextElement(); 143 /* avoid root logger */ 144 if (curEl.length() != 0 && curEl.length() != 0 && 145 !curEl.equals("global")) 146 { 147 lcnt++; 148 } 149 } 150 loggerCount = lcnt; 151 if (SystemProperties.isServerMode() && MonitoringUtil.isRunning()) { 152 if (logServiceImplForMonitoring == null) { 153 logServiceImplForMonitoring = 154 Agent.getLoggingSvcMBean(); 155 } 156 if (logServiceImplForMonitoring != null) { 157 logServiceImplForMonitoring.setSsoServerLoggingLoggers( 158 new Integer(loggerCount)); 159 } 160 } 161 } 162 return addSuccess; 163 } 164 165 /* security status updated by readConfiguration */ 166 private boolean securityStatus = false; 167 168 /* all fields read during read configuration */ 169 private String[] allFields; 170 private Set selectedFieldSet; 171 protected Level loggingLevel = null; 172 173 /** 174 * Return whether secure logging is specified. 175 * 176 * @return <code>securityStatus</code> 177 */ 178 public final boolean isSecure() { 179 return securityStatus; 180 } 181 182 /** 183 * Return the array of all LogRecord fields available for selection. 184 * 185 * @return <code>allFields</code> 186 */ 187 public synchronized final String[] getAllFields() { 188 return allFields; 189 } 190 191 /** 192 * Return the LogRecord fields selected to be included. 193 * 194 * @return <code>selectedFieldSet</code> 195 */ 196 public synchronized final Set getSelectedFieldSet() { 197 return selectedFieldSet; 198 } 199 200 private synchronized final void readAllFields() { 201 String strAllFields = getProperty(LogConstants.ALL_FIELDS); 202 StringTokenizer strToken = new StringTokenizer(strAllFields, ", "); 203 int count = strToken.countTokens(); 204 String localAllFields[] = new String[count]; 205 count = 0; 206 while (strToken.hasMoreElements()) { 207 localAllFields[count++] = strToken.nextToken().trim(); 208 } 209 allFields = localAllFields; 210 } 211 212 private synchronized final void readSelectedFieldSet() { 213 HashSet fieldSet = new HashSet(); 214 215 String strSelectedFields = getProperty(LogConstants.LOG_FIELDS); 216 217 if ((strSelectedFields != null) && (strSelectedFields.length() != 0)) { 218 StringTokenizer stoken = 219 new StringTokenizer(strSelectedFields, ", "); 220 221 while (stoken.hasMoreElements()) { 222 fieldSet.add(stoken.nextToken()); 223 } 224 } 225 selectedFieldSet = fieldSet; 226 return; 227 } 228 229 /** 230 * This method overrides the <code>readConfiguration</code> method in 231 * JDK <code>LogManager</code> class. 232 * The base class method resets the loggers in memory. This method 233 * must add handlers to the loggers in memory according to the 234 * new configuration. 235 * 236 * @throws IOException if there are IO problems reading the configuration. 237 * @throws SecurityException if a security manager exists and if the caller 238 * does not have <code>LoggingPermission("control")</code>. 239 */ 240 public final void readConfiguration() 241 throws IOException, SecurityException { 242 String[] xlogData = null; 243 try { 244 /* 245 * This writeLock ensures that no logging threads will execute 246 * a logger.log call after this point since they request for 247 * a readLock. 248 */ 249 Logger.rwLock.writeRequest(); 250 251 /* 252 * This sync is for avoiding this thread snathing away 253 * time slice from a thread executing getLogger() method 254 * which is also sync on Logger.class 255 * which may lead to two handlers being added to the same logger. 256 */ 257 synchronized (Logger.class) { 258 Enumeration loggerNames = getLoggerNames(); 259 LogManagerUtil.setupEnv(); 260 261 if (didFirstReadConfig && SystemProperties.isServerMode()) { 262 oldLocation = getProperty(LogConstants.LOG_LOCATION); 263 oldLevel = getProperty(LogConstants.LOGGING_LEVEL); 264 oldSecurityStatus = 265 getProperty(LogConstants.SECURITY_STATUS); 266 oldBackend = getProperty(LogConstants.BACKEND); 267 oldStatus = getProperty(LogConstants.LOG_STATUS_ATTR); 268 } 269 270 try { 271 /* 272 * This change is done for deploying AM as a single 273 * war. In server mode we will always use our 274 * LogConfigReader. On the client side the 275 * the JVM property will define whether to use the 276 * LogConfigReader or the remote handlers. If no 277 * JVM property is set, the remote handlers will 278 * be used. 279 */ 280 if (SystemProperties.isServerMode()) { 281 LogConfigReader logConfigReader = 282 new LogConfigReader(); 283 } else { 284 super.readConfiguration(); 285 } 286 didFirstReadConfig = true; 287 } catch (Exception ex) { 288 /* no debug since our debugging system is not up. */ 289 } finally { 290 LogManagerUtil.resetEnv(); 291 } 292 293 if (isLocal) { 294 securityStatus = false; 295 readAllFields(); 296 readSelectedFieldSet(); 297 298 if (SystemProperties.isServerMode()) { 299 newLocation = getProperty(LogConstants.LOG_LOCATION); 300 newLevel = getProperty(LogConstants.LOGGING_LEVEL); 301 newSecurityStatus = 302 getProperty(LogConstants.SECURITY_STATUS); 303 newBackend = getProperty(LogConstants.BACKEND); 304 newStatus = getProperty(LogConstants.LOG_STATUS_ATTR); 305 } 306 307 /* 308 * give all the pertinent values to decide why 309 * logging to the file was terminated. still 310 * have to check that one of the attributes 311 * that changed would cause a "real" termination 312 * of logging to the files/tables in the current 313 * location (as opposed to just a buffer timer change, 314 * for instance). 315 */ 316 317 String[] logData = {oldLocation, newLocation, 318 oldBackend, newBackend, 319 oldSecurityStatus, newSecurityStatus, 320 oldStatus, newStatus, 321 oldLevel, newLevel}; 322 323 if (getProperty(LogConstants.BACKEND).equals("DB")) { 324 HANDLER = getProperty(LogConstants.DB_HANDLER); 325 FORMATTER = getProperty(LogConstants.DB_FORMATTER); 326 String driver = getProperty(LogConstants.DB_DRIVER); 327 } else if (getProperty( 328 LogConstants.SECURITY_STATUS).equalsIgnoreCase("ON")) 329 { 330 securityStatus = true; 331 HANDLER = getProperty(LogConstants.SECURE_FILE_HANDLER); 332 FORMATTER = 333 getProperty(LogConstants.SECURE_ELF_FORMATTER); 334 } else { 335 HANDLER = getProperty(LogConstants.FILE_HANDLER); 336 FORMATTER = getProperty(LogConstants.ELF_FORMATTER); 337 } 338 339 if (getProperty(LogConstants.BACKEND).equals("File")) { 340 /* 341 * create new log directory if it has changed and 342 * the new directory does not exist. 343 */ 344 345 if (SystemProperties.isServerMode() && 346 (newLocation != null) && 347 (oldLocation != null) && 348 !oldLocation.equals(newLocation)) { 349 File dir = new File(newLocation); 350 if (!dir.exists()) { 351 if (!dir.mkdirs()) { 352 Debug.error( 353 "LogManager:readConfiguration:" + 354 "Unable to create the new log " + 355 "directory. Verify that the " + 356 "process has necessary permissions"); 357 } 358 } 359 } 360 } 361 362 boolean loggingInactive = 363 (getProperty(LogConstants.LOG_STATUS_ATTR). 364 equals(inactive)); 365 366 String strLogLevel = 367 getProperty(LogConstants.LOGGING_LEVEL); 368 try { 369 loggingLevel = Level.parse(strLogLevel); 370 } catch (IllegalArgumentException iaex) { 371 loggingLevel = Level.INFO; // default 372 Debug.error("LogManager:readConfiguration:" + 373 "Log level '" + strLogLevel + 374 "' unknown; setting to Level.INFO."); 375 } 376 377 /* 378 * get the global logging level from the logging 379 * service config. however, if logging status is 380 * INACTIVE, the overriding level becomes OFF 381 */ 382 383 if (loggingInactive) { 384 loggingLevel = Level.OFF; 385 } 386 xlogData = logData; 387 } else { 388 HANDLER = getProperty(LogConstants.REMOTE_HANDLER); 389 if (HANDLER == null) { 390 HANDLER = LogConstants.DEFAULT_REMOTE_HANDER; 391 } 392 FORMATTER = getProperty(LogConstants.REMOTE_FORMATTER); 393 if (FORMATTER == null) { 394 FORMATTER = LogConstants.DEFAULT_REMOTE_FORMATTER; 395 } 396 } 397 398 Logger.resolveHostName = Boolean.valueOf( 399 getProperty(LogConstants.LOG_RESOLVE_HOSTNAME_ATTR)). 400 booleanValue(); 401 402 /* 403 * modify existing loggers in memory according 404 * to the new configuration 405 */ 406 loggerNames = getLoggerNames(); 407 408 while (loggerNames.hasMoreElements()) { 409 String curEl = (String) loggerNames.nextElement(); 410 /* avoid root logger */ 411 if (curEl.length() != 0 && curEl.length() != 0 && 412 !curEl.equals("global")) { 413 if (Debug.messageEnabled()) { 414 Debug.message( 415 "LogManager:readConfiguration:" + 416 "Processing Logger: " + curEl); 417 } 418 419 /* 420 * remove all handlers and add new handlers for 421 * this logger 422 */ 423 Logger l = (Logger) Logger.getLogger(curEl); 424 Handler[] handlers = l.getHandlers(); 425 for (int i = 0; i < handlers.length; i++) { 426 handlers[i].close(); 427 l.removeHandler(handlers[i]); 428 } 429 430 String handlerClass = LogManager.HANDLER; 431 Class clz = null; 432 Class[] parameters = {String.class}; 433 Object[] parameterObjects = {l.getName()}; 434 Constructor cons = null; 435 Handler h = null; 436 try { 437 clz = Class.forName(handlerClass); 438 } catch (Exception e) { 439 Debug.error( 440 "LogManager.readConfiguration:could not load " + 441 handlerClass, e); 442 } 443 try { 444 cons = clz.getDeclaredConstructor(parameters); 445 } catch (Exception e) { 446 Debug.error( 447 "LogManager.readConfiguration:could not" + 448 " instantiate" + handlerClass, e); 449 } 450 try { 451 h = (Handler) cons.newInstance(parameterObjects); 452 } catch (Exception e) { 453 Debug.error( 454 "LogManager.readConfiguration:could not" + 455 " instantiate" + handlerClass, e); 456 } 457 String formatterClass = LogManager.FORMATTER; 458 Formatter f = null; 459 try { 460 f = (Formatter) Class.forName(formatterClass). 461 newInstance(); 462 } catch (Exception e) { 463 Debug.error( 464 "LogManager.readConfiguration:could not" + 465 " instantiate Formatter " + 466 formatterClass, e); 467 } 468 h.setFormatter(f); 469 l.addHandler(h); 470 471 /* 472 * get the "iplanet-am-logging.<logfilename>.level 473 * value for this file, if it's been added on the 474 * server's advanced config page. 475 * 476 * BUT: logging status set to Inactive means 477 * all logging is turned Level.OFF 478 */ 479 Level tlevel = loggingLevel; 480 if (loggingLevel != Level.OFF) { 481 String levelProp = 482 LogConstants.LOG_PROP_PREFIX + "." + 483 l.getName() + ".level"; 484 String lvlStr = SystemProperties.get(levelProp); 485 486 if ((lvlStr != null) && (lvlStr.length() > 0)) { 487 try { 488 tlevel = Level.parse(lvlStr); 489 } catch (IllegalArgumentException iaex) { 490 // use value for all others 491 } 492 } 493 } 494 if (loggingLevel != null) { // only if isLocal 495 // update logging level 496 l.setLevel(tlevel); 497 } 498 } /* end of avoid rootlogger */ 499 } /* end of while(loggerNames.hasMoreElements) */ 500 } /* end of synchronized(Logger.class) */ 501 } finally { 502 Logger.rwLock.writeDone(); 503 } 504 505 if (SystemProperties.isServerMode() && isLocal) { 506 checkStartLogs(xlogData); 507 //Update the new configuration info in Monitoring handle also 508 updateMonitConfigForLogService(); 509 } 510 } /* end of readConfiguration() */ 511 512 513 /** 514 * check the existing ("old") config and the new config for 515 * specific attribute changes that would mean logging has 516 * changed to a new location or has re-started. these are: 517 * 1. logging location 518 * 2. new Status == ACTIVE && old Level == OFF && 519 * new Level != OFF 520 * 3. old Status == INACTIVE && new Status == ACTIVE && 521 * new Level != OFF 522 * 4. old Backend != new Backend (File <-> DB) 523 * 5. old Security Status != new Security Status 524 * 525 * the String[] passed contains: 526 * [0] = old Location 527 * [1] = new Location 528 * [2] = old Backend 529 * [3] = new Backend 530 * [4] = old Security Status 531 * [5] = new Security Status 532 * [6] = old Status 533 * [7] = new Status 534 * [8] = old Level 535 * [9] = new Level 536 */ 537 private void checkStartLogs(String[] vals) { 538 Enumeration loggerNames = getLoggerNames(); 539 boolean loggingIsActive = false; 540 boolean levelIsOff = true; 541 542 // if the values array or any of its elements is null, just return 543 if (vals == null) { 544 return; 545 } 546 for (int i = 0; i <= NEWLEVEL; i++) { 547 if ((vals[i] == null) || (vals[i].length() == 0)) { 548 return; 549 } 550 } 551 552 if (vals[NEWSTATUS] != null) { 553 loggingIsActive = vals[NEWSTATUS].equals("ACTIVE"); 554 } 555 if (vals[NEWLEVEL] != null) { 556 levelIsOff = vals[NEWLEVEL].equals("OFF"); 557 } 558 559 /* 560 * if current status == ACTIVE and Level != OFF, 561 * and individual log's Level != OFF, 562 * then write a start record to the log. 563 * 564 * note that status == INACTIVE overrides any Level setting 565 * for the logging service, or an individual log file. 566 * 567 */ 568 if (loggingIsActive) { 569 // see if there's a reason to write the log record 570 if (!vals[OLDBACKEND].equals(vals[NEWBACKEND]) || 571 !vals[OLDLOCATION].equals(vals[NEWLOCATION]) || 572 !vals[OLDSECURITYSTATUS].equals(vals[NEWSECURITYSTATUS]) || 573 !vals[OLDSTATUS].equals(vals[NEWSTATUS]) || 574 !vals[OLDLEVEL].equals(vals[NEWLEVEL])) { 575 loggerNames = getLoggerNames(); 576 String saveLevel = vals[NEWLEVEL]; 577 Level level = Level.INFO; 578 try { 579 level = Level.parse(vals[NEWLEVEL]); 580 } catch (IllegalArgumentException iaex) { 581 // just leave it at "INFO" as a default 582 } 583 584 while (loggerNames.hasMoreElements()) { 585 vals[NEWLEVEL] = saveLevel; 586 String curEl = (String) loggerNames.nextElement(); 587 /* avoid root logger */ 588 if (curEl.length() != 0 && curEl.length() != 0 && 589 !curEl.equals("global")) { 590 Logger l = (Logger) Logger.getLogger(curEl); 591 592 /* 593 * additional reason to check if start record 594 * should be written: 595 * general Level is now "OFF", but this 596 * individual file's level != OFF 597 * then log to the individual file 598 * and 599 * general Level != OFF, but this 600 * individual file's level == oFF 601 * then don't log to the individual file 602 * the individual file's level is set 603 * in the readConfiguration stuff, above. 604 */ 605 606 // get this log's level 607 Level tlevel = l.getLevel(); 608 609 if (levelIsOff) { 610 if (tlevel != Level.OFF) { 611 vals[NEWLEVEL] = tlevel.toString(); 612 logIt(l, vals, 613 LogConstants.START_LOG_CONFIG_NAME); 614 } 615 } else { 616 logIt(l, vals, LogConstants.START_LOG_CONFIG_NAME); 617 } 618 } 619 } 620 } 621 } 622 } 623 624 private void logIt(Logger logger, String[] msg, String msgName) { 625 try { 626 LogMessageProviderBase provider = 627 (LogMessageProviderBase) MessageProviderFactory.getProvider( 628 "Logging"); 629 SSOToken ssot = LogManagerUtil.getLoggingSSOToken(); 630 com.sun.identity.log.LogRecord lr = 631 provider.createLogRecord(msgName, msg, ssot); 632 logger.log(lr, ssot); 633 logger.flush(); 634 } catch (IOException ioex) { 635 Debug.error("LogManager.logIt:could not log to " + 636 logger.getName() + ": " + ioex.getMessage()); 637 } 638 } 639 640 /** 641 * This method is called from two places, from readConfiguration() and from 642 * Logger.getLoggers(). 643 */ 644 public void updateMonitConfigForLogService() { 645 /* 646 * if haven't gotten the logging service monitoring handle 647 * yet, see if it's setup now 648 */ 649 if (SystemProperties.isServerMode() && MonitoringUtil.isRunning()) { 650 if (logServiceImplForMonitoring == null) { 651 logServiceImplForMonitoring = 652 Agent.getLoggingSvcMBean(); 653 } 654 if (logServiceImplForMonitoring == null) { 655 return; 656 } 657 658 logServiceImplForMonitoring.setSsoServerLoggingLoggers( 659 new Integer(loggerCount)); 660 logServiceImplForMonitoring.setSsoServerLoggingSecure( 661 newSecurityStatus); 662 logServiceImplForMonitoring.setSsoServerLoggingTimeBuffering( 663 getProperty(LogConstants.TIME_BUFFERING_STATUS)); 664 logServiceImplForMonitoring.setSsoServerLoggingBufferSize( 665 Long.valueOf(getProperty(LogConstants.BUFFER_SIZE)). 666 longValue()); 667 logServiceImplForMonitoring.setSsoServerLoggingBufferTime( 668 Long.valueOf(getProperty(LogConstants.BUFFER_TIME)). 669 longValue()); 670 logServiceImplForMonitoring.setSsoServerLoggingMaxLogSize( 671 Long.valueOf(getProperty( 672 LogConstants.MAX_FILE_SIZE)).longValue()); 673 logServiceImplForMonitoring. 674 setSsoServerLoggingNumberHistoryFiles(Long.valueOf( 675 getProperty(LogConstants.NUM_HISTORY_FILES)). 676 longValue()); 677 logServiceImplForMonitoring.setSsoServerLoggingLocation( 678 getProperty(LogConstants.LOG_LOCATION)); 679 logServiceImplForMonitoring.setSsoServerLoggingType( 680 getProperty(LogConstants.BACKEND)); 681 logServiceImplForMonitoring.setSsoServerLoggingRecsRejected( 682 (long)0); 683 684 isMonitoringInit = true; 685 } 686 } 687 688 public boolean getLoggingStatusIsActive() { 689 String oStatus = getProperty(LogConstants.LOG_STATUS_ATTR); 690 return (oStatus.equalsIgnoreCase("ACTIVE")); 691 } 692 693 protected String getBackend() { 694 return (newBackend); 695 } 696 697 protected boolean isDBLogging() { 698 return (newBackend.equals("DB")); 699 } 700 701 public boolean getDidFirstReadConfig() { 702 return didFirstReadConfig; 703 } 704 705 /* 706 * only meant to be called from s1is.LogConfigReader when 707 * logging status goes from ACTIVE to INACTIVE 708 */ 709 public synchronized void logStopLogs() { 710 String location = getProperty(LogConstants.LOG_LOCATION); 711 String level = getProperty(LogConstants.LOGGING_LEVEL); 712 String securityStatus = getProperty(LogConstants.SECURITY_STATUS); 713 String backend = getProperty(LogConstants.BACKEND); 714 String status = getProperty(LogConstants.LOG_STATUS_ATTR); 715 // only care about status going from ACTIVE to INACTIVE 716 String[] vals = {location, location, 717 backend, backend, 718 securityStatus, securityStatus, 719 status, inactive, 720 level, level}; 721 722 Enumeration loggerNames = getLoggerNames(); 723 while (loggerNames.hasMoreElements()) { 724 String curEl = (String) loggerNames.nextElement(); 725 /* avoid root logger */ 726 if (curEl.length() != 0 && curEl.length() != 0 && 727 !curEl.equals("global")) 728 { 729 Logger l = (Logger) Logger.getLogger(curEl); 730 731 /* 732 * additional reason to check if end record 733 * should be written: 734 * this individual file's level == oFF 735 * then don't log to the individual file 736 */ 737 738 // get this log's level 739 Level tlevel = l.getLevel(); 740 741 if (tlevel != Level.OFF) { 742 logIt(l, vals, LogConstants.END_LOG_CONFIG_NAME); 743 } 744 } 745 } 746 } 747} 748