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