LogManager.java revision 3296aadab8464fc555488c34c7ee63644b754387
/**
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
*
* Copyright (c) 2006 Sun Microsystems Inc. All Rights Reserved
*
* The contents of this file are subject to the terms
* of the Common Development and Distribution License
* (the License). You may not use this file except in
* compliance with the License.
*
* You can obtain a copy of the License at
* See the License for the specific language governing
* permission and limitations under the License.
*
* When distributing Covered Code, include this CDDL
* Header Notice in each file and include the License file
* at opensso/legal/CDDLv1.0.txt.
* If applicable, add the following below the CDDL Header,
* with the fields enclosed by brackets [] replaced by
* your own identifying information:
* "Portions Copyrighted [year] [name of copyright owner]"
*
* $Id: LogManager.java,v 1.14 2009/12/09 00:34:22 bigfatrat Exp $
*
* Portions Copyrighted 2011-2014 ForgeRock AS.
* Portions Copyrighted 2013 Cybernetica AS
*/
/**
* This class keeps track of all the logger objects and does all the
* bookkeeping work. It is extended from JDK's <code>LogManager</code> to add
* functionalities, such as adding our logger listening to DS changes, etc.
* @supported.all.api
*/
/**
* Is the Log Service running locally or remotely
*/
public static boolean isLocal = false;
/**
* The handler which will be added to each logger object
*/
/**
* The formatter which depends on the log settings
*/
public static boolean isMonitoringInit = false;
/*
* A list to maintain strong references to all loggers that are added,
* workaround for the file handle issue in OPENAM-184.
*/
private static Hashtable loggersTable;
/**
* Indicator for whether the first readConfiguration has happened
*/
private static boolean didFirstReadConfig;
private static String newLocation;
private static String newSecurityStatus;
private static String newBackend;
private final int OLDLOCATION = 0;
private final int NEWLOCATION = 1;
private final int OLDBACKEND = 2;
private final int NEWBACKEND = 3;
private final int OLDSECURITYSTATUS = 4;
private final int NEWSECURITYSTATUS = 5;
private final int OLDSTATUS = 6;
private final int NEWSTATUS = 7;
private final int OLDLEVEL = 8;
private final int NEWLEVEL = 9;
private static int loggerCount = 0;
/**
* Adds a logger to the Log Manager.
*
* @param logger Logger object to be added to the Log Manager.
* @return true if the logger is added.
*/
/* we have to pass root logger and global logger */
/* we have to take care of the resourcebundle logger may have */
}
// OPENAM-1110, loggersTable may not get initialized immediately, since we extend.
if (loggersTable == null) {
loggersTable = new Hashtable();
}
// Workaround for OPENAM-184, maintains strong reference to the loggers until this class is collected
// The Hashtable will never be used to retrieve loggers, only to keep then strongly referenced
if(addSuccess){
int lcnt = 0;
while (loggerNames.hasMoreElements()) {
/* avoid root logger */
{
lcnt++;
}
}
loggerCount = lcnt;
if (logServiceImplForMonitoring == null) {
}
if (logServiceImplForMonitoring != null) {
new Integer(loggerCount));
}
}
}
return addSuccess;
}
/* security status updated by readConfiguration */
private boolean securityStatus = false;
/* all fields read during read configuration */
private Set selectedFieldSet;
/**
* Return whether secure logging is specified.
*
* @return <code>securityStatus</code>
*/
public final boolean isSecure() {
return securityStatus;
}
/**
* Return the array of all LogRecord fields available for selection.
*
* @return <code>allFields</code>
*/
public synchronized final String[] getAllFields() {
return allFields;
}
/**
* Return the LogRecord fields selected to be included.
*
* @return <code>selectedFieldSet</code>
*/
public synchronized final Set getSelectedFieldSet() {
return selectedFieldSet;
}
private synchronized final void readAllFields() {
count = 0;
while (strToken.hasMoreElements()) {
}
}
private synchronized final void readSelectedFieldSet() {
while (stoken.hasMoreElements()) {
}
}
return;
}
/**
* This method overrides the <code>readConfiguration</code> method in
* JDK <code>LogManager</code> class.
* The base class method resets the loggers in memory. This method
* must add handlers to the loggers in memory according to the
* new configuration.
*
* @throws IOException if there are IO problems reading the configuration.
* @throws SecurityException if a security manager exists and if the caller
* does not have <code>LoggingPermission("control")</code>.
*/
public final void readConfiguration()
throws IOException, SecurityException {
try {
/*
* This writeLock ensures that no logging threads will execute
* a logger.log call after this point since they request for
* a readLock.
*/
/*
* This sync is for avoiding this thread snathing away
* time slice from a thread executing getLogger() method
* which is also sync on Logger.class
* which may lead to two handlers being added to the same logger.
*/
synchronized (Logger.class) {
}
try {
/*
* This change is done for deploying AM as a single
* war. In server mode we will always use our
* LogConfigReader. On the client side the
* the JVM property will define whether to use the
* LogConfigReader or the remote handlers. If no
* JVM property is set, the remote handlers will
* be used.
*/
if (SystemProperties.isServerMode()) {
new LogConfigReader();
} else {
super.readConfiguration();
}
didFirstReadConfig = true;
/* no debug since our debugging system is not up. */
} finally {
}
if (isLocal) {
securityStatus = false;
if (SystemProperties.isServerMode()) {
}
/*
* give all the pertinent values to decide why
* logging to the file was terminated. still
* have to check that one of the attributes
* that changed would cause a "real" termination
* location (as opposed to just a buffer timer change,
* for instance).
*/
} else if (getProperty(
{
securityStatus = true;
} else {
}
/*
* create new log directory if it has changed and
* the new directory does not exist.
*/
if (SystemProperties.isServerMode() &&
(newLocation != null) &&
(oldLocation != null) &&
"LogManager:readConfiguration:" +
"Unable to create the new log " +
"directory. Verify that the " +
"process has necessary permissions");
}
}
}
}
boolean loggingInactive =
try {
} catch (IllegalArgumentException iaex) {
"Log level '" + strLogLevel +
"' unknown; setting to Level.INFO.");
}
/*
* get the global logging level from the logging
* service config. however, if logging status is
* INACTIVE, the overriding level becomes OFF
*/
if (loggingInactive) {
}
} else {
}
}
}
booleanValue();
/*
* modify existing loggers in memory according
* to the new configuration
*/
while (loggerNames.hasMoreElements()) {
/* avoid root logger */
if (Debug.messageEnabled()) {
"LogManager:readConfiguration:" +
"Processing Logger: " + curEl);
}
/*
* remove all handlers and add new handlers for
* this logger
*/
l.removeHandler(handlers[i]);
}
try {
} catch (Exception e) {
"LogManager.readConfiguration:could not load " +
handlerClass, e);
}
try {
} catch (Exception e) {
"LogManager.readConfiguration:could not" +
" instantiate" + handlerClass, e);
}
try {
} catch (Exception e) {
"LogManager.readConfiguration:could not" +
" instantiate" + handlerClass, e);
}
try {
newInstance();
} catch (Exception e) {
"LogManager.readConfiguration:could not" +
" instantiate Formatter " +
formatterClass, e);
}
h.setFormatter(f);
l.addHandler(h);
/*
* get the "iplanet-am-logging.<logfilename>.level
* value for this file, if it's been added on the
* server's advanced config page.
*
* BUT: logging status set to Inactive means
* all logging is turned Level.OFF
*/
l.getName() + ".level";
try {
} catch (IllegalArgumentException iaex) {
// use value for all others
}
}
}
// update logging level
}
} /* end of avoid rootlogger */
} /* end of while(loggerNames.hasMoreElements) */
} /* end of synchronized(Logger.class) */
} finally {
}
//Update the new configuration info in Monitoring handle also
}
} /* end of readConfiguration() */
/**
* check the existing ("old") config and the new config for
* specific attribute changes that would mean logging has
* changed to a new location or has re-started. these are:
* 1. logging location
* 2. new Status == ACTIVE && old Level == OFF &&
* new Level != OFF
* 3. old Status == INACTIVE && new Status == ACTIVE &&
* new Level != OFF
* 4. old Backend != new Backend (File <-> DB)
* 5. old Security Status != new Security Status
*
* the String[] passed contains:
* [0] = old Location
* [1] = new Location
* [2] = old Backend
* [3] = new Backend
* [4] = old Security Status
* [5] = new Security Status
* [6] = old Status
* [7] = new Status
* [8] = old Level
* [9] = new Level
*/
boolean loggingIsActive = false;
boolean levelIsOff = true;
// if the values array or any of its elements is null, just return
return;
}
for (int i = 0; i <= NEWLEVEL; i++) {
return;
}
}
}
}
/*
* if current status == ACTIVE and Level != OFF,
* and individual log's Level != OFF,
* then write a start record to the log.
*
* note that status == INACTIVE overrides any Level setting
* for the logging service, or an individual log file.
*
*/
if (loggingIsActive) {
// see if there's a reason to write the log record
try {
} catch (IllegalArgumentException iaex) {
// just leave it at "INFO" as a default
}
while (loggerNames.hasMoreElements()) {
/* avoid root logger */
/*
* additional reason to check if start record
* should be written:
* general Level is now "OFF", but this
* individual file's level != OFF
* then log to the individual file
* and
* general Level != OFF, but this
* individual file's level == oFF
* then don't log to the individual file
* the individual file's level is set
* in the readConfiguration stuff, above.
*/
// get this log's level
if (levelIsOff) {
}
} else {
}
}
}
}
}
}
try {
"Logging");
} catch (IOException ioex) {
}
}
/**
* This method is called from two places, from readConfiguration() and from
* Logger.getLoggers().
*/
public void updateMonitConfigForLogService() {
/*
* if haven't gotten the logging service monitoring handle
* yet, see if it's setup now
*/
if (logServiceImplForMonitoring == null) {
}
if (logServiceImplForMonitoring == null) {
return;
}
new Integer(loggerCount));
longValue());
longValue());
longValue());
(long)0);
isMonitoringInit = true;
}
}
public boolean getLoggingStatusIsActive() {
}
protected String getBackend() {
return (newBackend);
}
protected boolean isDBLogging() {
}
public boolean getDidFirstReadConfig() {
return didFirstReadConfig;
}
/*
* only meant to be called from s1is.LogConfigReader when
* logging status goes from ACTIVE to INACTIVE
*/
public synchronized void logStopLogs() {
// only care about status going from ACTIVE to INACTIVE
while (loggerNames.hasMoreElements()) {
/* avoid root logger */
{
/*
* additional reason to check if end record
* should be written:
* this individual file's level == oFF
* then don't log to the individual file
*/
// get this log's level
}
}
}
}
}