/*
* 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: Debug.java,v 1.5 2008/06/25 05:47:47 qcheng Exp $
*
* Portions Copyrighted 2015-2016 ForgeRock AS.
*/
// (actually all variables except double and long), the design consciously
// avoids synchronized methods, particularly for message(). This is done to
// reduce the performance overhead of synchronized message() when debugging
// is disabled. This does not have serious side-effects other than an occasional
// invocation of message() missing concurrent update of 'debugLevel'.
/*******************************************************************************
<p>Allows a uniform interface to file debug and exception information in a
filing debug information (in the ascending order): <code>OFF</code>,
<code>ERROR</code>, <code>WARNING</code>, <code>MESSAGE</code> and
state is <code>ERROR</code>, only errors will be filed. If the debug state is
<code>WARNING</code>, only errors and warnings will be filed. If the debug
state is <code>MESSAGE</code>, everything will be filed.
<code>MESSAGE</code> and <code>ON</code> are of the same levels;
the difference between them being <code>MESSAGE</code> writes to a file,
whereas <code>ON</code> writes to System.out.</p>
<p>
Debug service uses the property file, <code>DebugConfig.properties</code>, to
set the default debug level and the output directory where the debug files
will be placed. The properties file is located (using
{@link java.util.ResourceBundle} semantics) from one of the directories
in the CLASSPATH.
<p>
The following keys are used to configure the Debug service.
Possible values for the key 'level' are: off | error | warning | message
The key 'directory' specifies the output directory where the debug files will
be created.
<blockquote><pre>
com.iplanet.services.debug.level
com.iplanet.services.debug.directory
</pre></blockquote>
If there is an error reading or loading the properties,
debug service will redirect all debug information to <code>System.out</code>
If these properties are changed, the server must be restarted for the
changes to take effect.
<p><b>NOTE:</b> Debugging is an IO intensive operation and may hurt
application performance when abused. Particularly, note that Java evaluates
the arguments to <code>message()</code> and <code>warning()</code> even
when debugging is turned off.
It is recommended that the debug state be checked before invoking any
<code>message()</code> or <code>warning()</code> methods to avoid unnecessary
argument evaluation and to maximize application performance.</p>
******************************************************************************/
public class Debug {
/** flags the disabled debug state. */
/** flags the state where error debugging is enabled. When debugging is set
* to less than <code>ERROR</code>, error debugging is also disabled.
*/
/** flags the state where warning debugging is enabled, but message
* debugging is disabled. When debugging is set to less than
* <code>WARNING</code>, warning debugging is also disabled.
*/
/** This state enables debugging of messages, warnings and errors. */
/** flags the enabled debug state for warnings, errors and messages.
* Printing to a file is disabled. All printing is done on System.out.
*/
/** debugMap is a container of all active Debug objects. Log file name is
* the key and Debug is the value of this map.
*/
/** The default debug level for the entire service and the level that is
* used when a Debug object is first created and before its level is
* modified. Don't initialize the following two variables in a static
* initializer/block because other components may initialize Debug in their
* static initializers (as opposed to constructors or methods). The
* order of execution of static blocks is not guaranteed by JVM. So if we
* set the following two static variables to some default values here, then
* it will interfere with the execution of {@link #initService}.
*/
private int debugLevel;
private static boolean validInit() {
}
/** Initializes the Debug service so that Debug objects can be created. At
* startup (when the first Debug object is ever created in a JVM), this
* method reads <code>DebugConfig.properties</code> file (using
* {@link java.util.ResourceBundle} semantics) from one of the directories
* in the CLASSPATH, and loads the properties. It creates the debug
* directory. If all the directories in output dir don't have adequate
* permissions then the creation of the debug directory will fail and all
* the debug files will be located in the "current working directory" of
* the process running debug code
* If there is an error reading or loading the properties, it will set the
* debug service to redirect all debug information to
* <code>System.out</code>
*/
private static void initService() {
/* We will use the double-checked locking pattern. Rarely entered
* block. Push synchronization inside it. This is the first check.
*/
if (!validInit()) {
/* Only 1 thread at a time gets past the next point. Rarely
* executed synchronization statement and hence synchronization
* penalty is not paid every time this method is called.
*/
synchronized (Debug.class) {
/* If a second thread was waiting to get here, it will now
* find that the instance has already been initialized, and
* it will not re-initialize the instance variable. This is the
* (second) double-check.
*/
if (!validInit()) {
try {
if (debugDirectory != null ) {
{
}
}
} catch (MissingResourceException e) {
e.printStackTrace();
// If there is any error in getting the level or
// outputDirectory, defaultDebugLevel will be set to
// ON so that output will go to
// System.out
debugLevelStr = "on";
} catch (SecurityException se) {
}
}
}
}
}
/** This constructor takes as an argument the name of the debug file. The
* debug file is neither created nor opened until the first time
* <code>message()</code>, <code>warning()</code> or <code>error()</code>
* is invoked and the debug state is neither <code>OFF</code> nor
* <code>ON</code>.
* <p><b>NOTE:</b>The recommended and preferred method to create Debug
* objects is <code>getInstance(String)</code>. This constructor may be
* deprecated in future.</p>
*
* @param debugName name of the debug file to create or use
* @deprecated Use {@link #getInstance}
*/
// Initialize the debug service the first time a Debug object is
// created.
initService();
// Now initialize this instance itself
synchronized (debugMap) {
// explicitly ignore any duplicate instances.
}
}
/**
* Returns an existing instance of Debug for the specified debug file or a
* new one if no such instance already exists. If a Debug object has to be
* created, its level is set to the level defined in the
* <code>DebugConfig.properties</code> file. The level can be changed later
* by using {@link #setDebug(int)} or {@link #setDebug(String)}
*
* @param debugName name of debug instance.
* @return an instance of <code>Debug</code>.
*/
(debugDirectory != null &&
}
return debugObj;
}
/** Checks if message debugging is enabled.
*
* <p><b>NOTE:</b> It is recommended that <code>messageEnabled()</code>
* be used instead of <code>debugEnabled()</code> as the former is more
* intuitive.</>
*
* @return <code>true</code> if message debugging is enabled
* <code>false</code> if message debugging is disabled
*
* @deprecated Use {@link #messageEnabled}
*/
public boolean debugEnabled() {
}
/** Checks if message debugging is enabled.
*
* <p><b>NOTE:</b> Debugging is an IO intensive operation and may hurt
* application performance when abused. Particularly, note that Java
* evaluates arguments to <code>message()</code> even when
* debugging is turned off. It is recommended that
* <code>messageEnabled()</code> be called to check the debug state
* before invoking any <code>message()</code> methods to avoid
* unnecessary argument evaluation and maximize application performance.</p>
*
* @return <code>true</code> if message debugging is enabled
* <code>false</code> if message debugging is disabled
*/
public boolean messageEnabled() {
}
/** Checks if warning debugging is enabled.
*
* <p><b>NOTE:</b> Debugging is an IO intensive operation and may hurt
* application performance when abused. Particularly, note that Java
* evaluates arguments to <code>warning()</code> even when
* warning debugging is turned off. It is recommended that
* <code>warningEnabled()</code> be called to check the debug state
* before invoking any <code>warning()</code> methods to avoid
* unnecessary argument evaluation and maximize application performance.</p>
*
* @return <code>true</code> if warning debugging is enabled
* <code>false</code> if warning debugging is disabled
*/
public boolean warningEnabled() {
}
/**
* Returns one of the five possible values:
* <ul>
* <li><code>Debug.OFF</code>
* <li><code>Debug.ERROR</code>
* <li><code>Debug.WARNING</code>
* <li><code>Debug.MESSAGE</code>
* <pli<code>Debug.ON</code>
* </ul>
*
* @return debug state.
*/
public int getState() {
return debugLevel;
}
/** Prints messages only when the debug state is either
* DEBUG.MESSAGE or Debug.ON.
*
* <p><b>NOTE:</b> Debugging is an IO intensive operation and may hurt
* application performance when abused. Particularly, note that Java
* evaluates arguments to <code>message()</code> even when
* debugging is turned off. So when the argument to this method involves
* the String concatenation operator '+' or any other method invocation,
* <code>messageEnabled</code> <b>MUST</b> be used. It is recommended that
* the debug state be checked by invoking <code>messageEnabled()</code>
* before invoking any <code>message()</code> methods to avoid
* unnecessary argument evaluation and maximize application performance.</p>
*
* @param msg message to be printed. A newline will be appended to the
* message before printing either to <code>System.out</code>
* or to the debug file. If <code>msg</code> is null, it is
* ignored.
* @see Debug#message(String msg, Throwable t)
*/
}
}
/** <p> Prints debug and exception messages only when the debug
* state is either DEBUG.MESSAGE or Debug.ON. If the debug file is not
* accessible and debugging is enabled, the message along with a time stamp
* and thread info will be printed on <code>System.out</code>.</p>
*
* <p>This method creates the debug file if does not exist; otherwise it
* starts appending to the existing debug file. When invoked for the first
* time on this object, the method writes a line delimiter of '*'s.</p>
*
* <p>Note that the debug file will remain open until <code>destroy()</code>
* is invoked. To conserve file resources, you should invoke
* <code>destroy()</code> explicitly rather than wait for the garbage
* collector to clean up.</p>
*
* <p><b>NOTE:</b> Debugging is an IO intensive operation and may hurt
* application performance when abused. Particularly, note that
* Java evaluates arguments to <code>message()</code> even when
* debugging is turned off. It is recommended that the debug state be
* checked by invoking <code>messageEnabled()</code> before invoking any
* <code>message()</code> methods to avoid unnecessary argument evaluation
* and to maximize application performance.</p>
*
* @param msg message to be printed. A newline will be appended to the
* message before printing either to <code>System.out</code>
* or to the debug file. If <code>msg</code> is null, it is
* ignored.
* @param t <code>Throwable</code>, on which <code>printStackTrace</code>
* will be invoked to print the stack trace. If <code>t</code> is
* null, it is ignored.
* @see Debug#error(String msg, Throwable t)
*/
}
}
/** Prints warning messages only when debug level is greater than
* DEBUG.ERROR.
*
* <p><b>NOTE:</b> Debugging is an IO intensive operation and may hurt
* application performance when abused. Particularly, note that
* Java evaluates arguments to <code>warning()</code> even when
* debugging is turned off. So when the argument to this method involves
* the String concatenation operator '+' or any other method invocation,
* <code>warningEnabled</code> <b>MUST</b> be used. It is recommended that
* the debug state be checked by invoking <code>warningEnabled()</code>
* before invoking any <code>warning()</code> methods to avoid
* unnecessary argument evaluation and to maximize application
* performance.</p>
*
* @param msg message to be printed. A newline will be appended to the
* message before printing either to <code>System.out</code>
* or to the debug file. If <code>msg</code> is null, it is
* ignored.
* @see Debug#warning(String msg, Throwable t)
*/
}
}
/** Prints warning messages only when debug level is greater than
* DEBUG.ERROR.
*
* <p><b>NOTE:</b> Debugging is an IO intensive operation and may hurt
* application performance when abused. Particularly, note that
* Java evaluates arguments to <code>warning()</code> even when
* debugging is turned off. It is recommended that the debug state be
* checked by invoking <code>warningEnabled()</code> before invoking any
* <code>warning()</code> methods to avoid unnecessary argument evaluation
* and to maximize application performance.</p>
*
* <p>If the debug file is not accessible and debugging is enabled, the
* message along with a time stamp and thread info will be printed on
* <code>System.out</code>.</p>
*
* <p>This method creates the debug file if does not exist; otherwise it
* starts appending to the existing debug file. When invoked for the first
* time on this object, the method writes a line delimiter of '*'s.</p>
*
* <p>Note that the debug file will remain open until <code>destroy()</code>
* is invoked. To conserve file resources, you should invoke
* <code>destroy()</code> explicitly rather than wait for the garbage
* collector to clean up.</p>
*
* @param msg message to be printed. A newline will be appended to the
* message before printing either to <code>System.out</code>
* or to the debug file. If <code>msg</code> is null, it is
* ignored.
* @param t <code>Throwable</code>, on which
* <code>printStackTrace()</code> will be invoked to print the
* stack trace. If <code>t</code> is null, it is ignored.
*/
}
}
/**
* Prints error messages only when debug level is greater than DEBUG.OFF.
*
* @param msg message to be printed. A newline will be appended to the
* message before printing either to <code>System.out</code>
* or to the debug file. If <code>msg</code> is null, it is
* ignored.
* @see Debug#error(String msg, Throwable t)
*/
}
}
/** Prints error messages only if debug state is greater than
* Debug.OFF. If the debug file is not accessible and debugging is enabled,
* the message along with a time stamp and thread info will be printed on
* <code>System.out</code>.</p>
*
* <p>This method creates the debug file if does not exist; otherwise it
* starts appending to the existing debug file. When invoked for the first
* time on this object, the method writes a line delimiter of '*'s.</p>
*
* <p>Note that the debug file will remain open until <code>destroy()</code>
* is invoked. To conserve file resources, you should invoke
* <code>destroy()</code> explicitly rather than wait for the garbage
* collector to clean up.</p>
*
* @param msg message to be printed. A newline will be appended to the
* message before printing either to <code>System.out</code>
* or to the debug file. If <code>msg</code> is null, it is
* ignored.
* @param t <code>Throwable</code>, on which <code>printStackTrace()</code>
* will be invoked to print the stack trace. If <code>t</code> is
* null, it is ignored.
*/
}
}
} else {
}
}
if (t != null) {
}
return;
}
// The default capacity of StringBuffer in StringWriter is 16, but we
// know for sure that the minimum header size is about 35. Hence, to
// avoid reallocation allocate at least 160 chars.
synchronized (dateFormat) {
}
}
}
if (t != null) {
t.printStackTrace(buf);
}
}
/** Actually writes to the debug file. If it cannot write to the debug
* file, it turn off debugging. The first time this method is invoked on
* directory specified by the
* <code>property com.iplanet.services.debug.directory</code> in the
* properties file, <code>DebugConfig.properties</code>.
*/
try {
// debugging is enabled.
// First, see if the debugFile is already open. If not, open it now.
(debugDirectory != null &&
initService();
// open file in append mode
debugFile = new PrintWriter(
true); // autoflush enabled
"******************************************************");
}
} catch (IOException e) {
// turn off debugging because debugFile is not accessible
}
}
/**
* Sets the debug capabilities based on the values of the
* <code>debugType</code> argument.
*
* @param debugType is any one of five possible values:
* <ul>
* <li><code>Debug.OFF</code>
* <li><code>Debug.ERROR</code>
* <li><code>Debug.WARNING</code>
* <li><code>Debug.MESSAGE</code>
* <li><code>Debug.ON</code>
* <ul>
*/
switch (debugType) {
break;
default:
// ignore invalid debugType values
break;
}
}
/**
* Enables or disables debugging based on the value of debug attribute,
* <code>com.iplanet.services.debug.level</code>, in the
* <code>DebugConfig.properties</code> file.
* <code>DebugConfig.properties<code>
* file should be accessible from CLASSPATH.
* If the property is not defined, debug level is set to <code>error</code>.
*
* @deprecated Use {@link #getInstance}. {@link #getInstance} will
* automatically set the debug level based on the information in
* <code>DebugConfig.properties</code> file.
*/
public void setDebug() {
// The following initService is temporary. setDebug() is anyways
// deprecated and will be removed in future.
initService();
}
/**
* Sets the debug capabilities based on the values of the
* <code>debugType</code> argument.
*
* @param debugType is any one of the following possible values:
* <ul>
* <li>off - debugging is disabled
* <li>on - all debugging is enabled and written to <code>System.out</code>
* <li>message - message debugging is enabled and written to the debug file
* <li>warning - warning debugging is enabled and written to the debug file
* <li>error - error debugging is enabled and written to the debug file
* </ul>
*/
return;
} else {
}
}
}
}
/** Destroys the debug object, closes the debug file and releases any system
* resources. Note that the debug file will remain open until
* <code>destroy()</code> is invoked. To conserve file resources, you should
* invoke <code>destroy()</code> explicitly rather than wait for the garbage
* collector to clean up.
*
* <p> If this object is accessed after <code>destroy()</code> has been
* invoked, the results are undefined.</p>
*/
public void destroy() {
finalize();
}
/** Flushes and then closes the debug file. */
protected void finalize() {
synchronized (debugMap) {
}
synchronized (this) {
return;
}
}
}
}