mirror of
git://gcc.gnu.org/git/gcc.git
synced 2025-04-10 07:10:27 +08:00
LogRecord.java, [...]: New files from classpath.
2003-06-21 Michael Koch <konqueror@gmx.de> * java/util/logging/LogRecord.java, java/util/logging/Logger.java, java/util/logging/SocketHandler.java, java/util/logging/SimpleFormatter.java, java/util/logging/Formatter.java, java/util/logging/ErrorManager.java, java/util/logging/Handler.java, java/util/logging/FileHandler.java, java/util/logging/LogManager.java, java/util/logging/Level.java, java/util/logging/ConsoleHandler.java, java/util/logging/StreamHandler.java, java/util/logging/LoggingPermission.java, java/util/logging/Filter.java, java/util/logging/MemoryHandler.java, java/util/logging/XMLFormatter.java: New files from classpath. From-SVN: r68295
This commit is contained in:
parent
c18cd64247
commit
2d0c9050c3
@ -1,3 +1,23 @@
|
||||
2003-06-21 Michael Koch <konqueror@gmx.de>
|
||||
|
||||
* java/util/logging/LogRecord.java,
|
||||
java/util/logging/Logger.java,
|
||||
java/util/logging/SocketHandler.java,
|
||||
java/util/logging/SimpleFormatter.java,
|
||||
java/util/logging/Formatter.java,
|
||||
java/util/logging/ErrorManager.java,
|
||||
java/util/logging/Handler.java,
|
||||
java/util/logging/FileHandler.java,
|
||||
java/util/logging/LogManager.java,
|
||||
java/util/logging/Level.java,
|
||||
java/util/logging/ConsoleHandler.java,
|
||||
java/util/logging/StreamHandler.java,
|
||||
java/util/logging/LoggingPermission.java,
|
||||
java/util/logging/Filter.java,
|
||||
java/util/logging/MemoryHandler.java,
|
||||
java/util/logging/XMLFormatter.java:
|
||||
New files from classpath.
|
||||
|
||||
2003-06-20 Michael Koch <konqueror@gmx.de>
|
||||
|
||||
* java/io/ObjectStreamField.java
|
||||
|
129
libjava/java/util/logging/ConsoleHandler.java
Normal file
129
libjava/java/util/logging/ConsoleHandler.java
Normal file
@ -0,0 +1,129 @@
|
||||
/* ConsoleHandler.java
|
||||
-- a class for publishing log messages to System.err
|
||||
|
||||
Copyright (C) 2002 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Classpath.
|
||||
|
||||
GNU Classpath is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
GNU Classpath is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GNU Classpath; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
02111-1307 USA.
|
||||
|
||||
Linking this library statically or dynamically with other modules is
|
||||
making a combined work based on this library. Thus, the terms and
|
||||
conditions of the GNU General Public License cover the whole
|
||||
combination.
|
||||
|
||||
As a special exception, the copyright holders of this library give you
|
||||
permission to link this library with independent modules to produce an
|
||||
executable, regardless of the license terms of these independent
|
||||
modules, and to copy and distribute the resulting executable under
|
||||
terms of your choice, provided that you also meet, for each linked
|
||||
independent module, the terms and conditions of the license of that
|
||||
module. An independent module is a module which is not derived from
|
||||
or based on this library. If you modify this library, you may extend
|
||||
this exception to your version of the library, but you are not
|
||||
obligated to do so. If you do not wish to do so, delete this
|
||||
exception statement from your version.
|
||||
|
||||
*/
|
||||
|
||||
|
||||
package java.util.logging;
|
||||
|
||||
/**
|
||||
* A <code>ConsoleHandler</code> publishes log records to
|
||||
* <code>System.err</code>.
|
||||
*
|
||||
* <p><strong>Configuration:</strong> Values of the subsequent
|
||||
* <code>LogManager</code> properties are taken into consideration
|
||||
* when a <code>ConsoleHandler</code> is initialized.
|
||||
* If a property is not defined, or if it has an invalid
|
||||
* value, a default is taken without an exception being thrown.
|
||||
*
|
||||
* <ul>
|
||||
*
|
||||
* <li><code>java.util.logging.ConsoleHandler.level</code> - specifies
|
||||
* the initial severity level threshold. Default value:
|
||||
* <code>Level.INFO</code>.</li>
|
||||
*
|
||||
* <li><code>java.util.logging.ConsoleHandler.filter</code> - specifies
|
||||
* the name of a Filter class. Default value: No Filter.</li>
|
||||
*
|
||||
* <li><code>java.util.logging.ConsoleHandler.formatter</code> - specifies
|
||||
* the name of a Formatter class. Default value:
|
||||
* <code>java.util.logging.SimpleFormatter</code>.</li>
|
||||
*
|
||||
* <li><code>java.util.logging.ConsoleHandler.encoding</code> - specifies
|
||||
* the name of the character encoding. Default value:
|
||||
* the default platform encoding.
|
||||
*
|
||||
* </ul>
|
||||
*
|
||||
* @author Sascha Brawer (brawer@acm.org)
|
||||
*/
|
||||
public class ConsoleHandler
|
||||
extends StreamHandler
|
||||
{
|
||||
/**
|
||||
* Constructs a <code>StreamHandler</code> that publishes
|
||||
* log records to <code>System.err</code>. The initial
|
||||
* configuration is determined by the <code>LogManager</code>
|
||||
* properties described above.
|
||||
*/
|
||||
public ConsoleHandler()
|
||||
{
|
||||
super(System.err, "java.util.logging.ConsoleHandler", Level.INFO,
|
||||
/* formatter */ null, SimpleFormatter.class);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Forces any data that may have been buffered to the underlying
|
||||
* output device, but does <i>not</i> close <code>System.err</code>.
|
||||
*
|
||||
* <p>In case of an I/O failure, the <code>ErrorManager</code>
|
||||
* of this <code>ConsoleHandler</code> will be informed, but the caller
|
||||
* of this method will not receive an exception.
|
||||
*/
|
||||
public void close()
|
||||
{
|
||||
flush();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Publishes a <code>LogRecord</code> to the console, provided the
|
||||
* record passes all tests for being loggable.
|
||||
*
|
||||
* <p>Most applications do not need to call this method directly.
|
||||
* Instead, they will use use a <code>Logger</code>, which will
|
||||
* create LogRecords and distribute them to registered handlers.
|
||||
*
|
||||
* <p>In case of an I/O failure, the <code>ErrorManager</code>
|
||||
* of this <code>SocketHandler</code> will be informed, but the caller
|
||||
* of this method will not receive an exception.
|
||||
*
|
||||
* <p>The GNU implementation of <code>ConsoleHandler.publish</code>
|
||||
* calls flush() for every request to publish a record, so
|
||||
* they appear immediately on the console.
|
||||
*
|
||||
* @param record the log event to be published.
|
||||
*/
|
||||
public void publish(LogRecord record)
|
||||
{
|
||||
super.publish(record);
|
||||
flush();
|
||||
}
|
||||
}
|
182
libjava/java/util/logging/ErrorManager.java
Normal file
182
libjava/java/util/logging/ErrorManager.java
Normal file
@ -0,0 +1,182 @@
|
||||
/* ErrorManager.java
|
||||
-- a class for dealing with errors that a Handler encounters
|
||||
during logging
|
||||
|
||||
Copyright (C) 2002 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Classpath.
|
||||
|
||||
GNU Classpath is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
GNU Classpath is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GNU Classpath; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
02111-1307 USA.
|
||||
|
||||
Linking this library statically or dynamically with other modules is
|
||||
making a combined work based on this library. Thus, the terms and
|
||||
conditions of the GNU General Public License cover the whole
|
||||
combination.
|
||||
|
||||
As a special exception, the copyright holders of this library give you
|
||||
permission to link this library with independent modules to produce an
|
||||
executable, regardless of the license terms of these independent
|
||||
modules, and to copy and distribute the resulting executable under
|
||||
terms of your choice, provided that you also meet, for each linked
|
||||
independent module, the terms and conditions of the license of that
|
||||
module. An independent module is a module which is not derived from
|
||||
or based on this library. If you modify this library, you may extend
|
||||
this exception to your version of the library, but you are not
|
||||
obligated to do so. If you do not wish to do so, delete this
|
||||
exception statement from your version.
|
||||
|
||||
*/
|
||||
|
||||
|
||||
package java.util.logging;
|
||||
|
||||
/**
|
||||
* An <code>ErrorManager</code> deals with errors that a <code>Handler</code>
|
||||
* encounters while logging.
|
||||
*
|
||||
* @see Handler#setErrorManager(ErrorManager)
|
||||
*
|
||||
* @author Sascha Brawer (brawer@acm.org)
|
||||
*/
|
||||
public class ErrorManager
|
||||
{
|
||||
/* The values have been taken from Sun's public J2SE 1.4 API
|
||||
* documentation.
|
||||
* See http://java.sun.com/j2se/1.4/docs/api/constant-values.html
|
||||
*/
|
||||
|
||||
/**
|
||||
* Indicates that there was a failure that does not readily
|
||||
* fall into any of the other categories.
|
||||
*/
|
||||
public static final int GENERIC_FAILURE = 0;
|
||||
|
||||
|
||||
/**
|
||||
* Indicates that there was a problem upon writing to
|
||||
* an output stream.
|
||||
*/
|
||||
public static final int WRITE_FAILURE = 1;
|
||||
|
||||
|
||||
/**
|
||||
* Indicates that there was a problem upon flushing
|
||||
* an output stream.
|
||||
*/
|
||||
public static final int FLUSH_FAILURE = 2;
|
||||
|
||||
|
||||
/**
|
||||
* Indicates that there was a problem upon closing
|
||||
* an output stream.
|
||||
*/
|
||||
public static final int CLOSE_FAILURE = 3;
|
||||
|
||||
|
||||
/**
|
||||
* Indicates that there was a problem upon opening
|
||||
* an output stream.
|
||||
*/
|
||||
public static final int OPEN_FAILURE = 4;
|
||||
|
||||
|
||||
/**
|
||||
* Indicates that there was a problem upon formatting
|
||||
* the message of a log record.
|
||||
*/
|
||||
public static final int FORMAT_FAILURE = 5;
|
||||
|
||||
|
||||
private boolean everUsed = false;
|
||||
|
||||
public ErrorManager()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Reports an error that occured upon logging. The default implementation
|
||||
* emits the very first error to System.err, ignoring subsequent errors.
|
||||
*
|
||||
* @param message a message describing the error, or <code>null</code> if
|
||||
* there is no suitable description.
|
||||
*
|
||||
* @param ex an exception, or <code>null</code> if the error is not
|
||||
* related to an exception.
|
||||
*
|
||||
* @param errorCode one of the defined error codes, for example
|
||||
* <code>ErrorManager.CLOSE_FAILURE</code>.
|
||||
*/
|
||||
public void error(String message, Exception ex, int errorCode)
|
||||
{
|
||||
if (everUsed)
|
||||
return;
|
||||
|
||||
synchronized (ErrorManager.class)
|
||||
{
|
||||
/* The double check is intentional. If the first check was
|
||||
* omitted, the monitor would have to be entered every time
|
||||
* error() method was called. If the second check was
|
||||
* omitted, the code below could be executed by multiple
|
||||
* threads simultaneously.
|
||||
*/
|
||||
if (everUsed)
|
||||
return;
|
||||
|
||||
everUsed = true;
|
||||
}
|
||||
|
||||
String codeMsg;
|
||||
switch (errorCode)
|
||||
{
|
||||
case GENERIC_FAILURE:
|
||||
codeMsg = "GENERIC_FAILURE";
|
||||
break;
|
||||
|
||||
case WRITE_FAILURE:
|
||||
codeMsg = "WRITE_FAILURE";
|
||||
break;
|
||||
|
||||
case FLUSH_FAILURE:
|
||||
codeMsg = "FLUSH_FAILURE";
|
||||
break;
|
||||
|
||||
case CLOSE_FAILURE:
|
||||
codeMsg = "CLOSE_FAILURE";
|
||||
break;
|
||||
|
||||
case OPEN_FAILURE:
|
||||
codeMsg = "OPEN_FAILURE";
|
||||
break;
|
||||
|
||||
case FORMAT_FAILURE:
|
||||
codeMsg = "FORMAT_FAILURE";
|
||||
break;
|
||||
|
||||
default:
|
||||
codeMsg = String.valueOf(errorCode);
|
||||
break;
|
||||
}
|
||||
|
||||
System.err.println("Error upon logging: " + codeMsg);
|
||||
if ((message != null) && (message.length() > 0))
|
||||
System.err.println(message);
|
||||
|
||||
if (ex != null)
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
509
libjava/java/util/logging/FileHandler.java
Normal file
509
libjava/java/util/logging/FileHandler.java
Normal file
@ -0,0 +1,509 @@
|
||||
/* FileHandler.java
|
||||
-- a class for publishing log messages to log files
|
||||
|
||||
Copyright (C) 2002, 2003 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Classpath.
|
||||
|
||||
GNU Classpath is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
GNU Classpath is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GNU Classpath; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
02111-1307 USA.
|
||||
|
||||
Linking this library statically or dynamically with other modules is
|
||||
making a combined work based on this library. Thus, the terms and
|
||||
conditions of the GNU General Public License cover the whole
|
||||
combination.
|
||||
|
||||
As a special exception, the copyright holders of this library give you
|
||||
permission to link this library with independent modules to produce an
|
||||
executable, regardless of the license terms of these independent
|
||||
modules, and to copy and distribute the resulting executable under
|
||||
terms of your choice, provided that you also meet, for each linked
|
||||
independent module, the terms and conditions of the license of that
|
||||
module. An independent module is a module which is not derived from
|
||||
or based on this library. If you modify this library, you may extend
|
||||
this exception to your version of the library, but you are not
|
||||
obligated to do so. If you do not wish to do so, delete this
|
||||
exception statement from your version.
|
||||
|
||||
*/
|
||||
|
||||
package java.util.logging;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
|
||||
/**
|
||||
* A <code>FileHandler</code> publishes log records to a set of log
|
||||
* files. A maximum file size can be specified; as soon as a log file
|
||||
* reaches the size limit, it is closed and the next file in the set
|
||||
* is taken.
|
||||
*
|
||||
* <p><strong>Configuration:</strong> Values of the subsequent
|
||||
* <code>LogManager</code> properties are taken into consideration
|
||||
* when a <code>FileHandler</code> is initialized. If a property is
|
||||
* not defined, or if it has an invalid value, a default is taken
|
||||
* without an exception being thrown.
|
||||
*
|
||||
* <ul>
|
||||
*
|
||||
* <li><code>java.util.FileHandler.level</code> - specifies
|
||||
* the initial severity level threshold. Default value:
|
||||
* <code>Level.ALL</code>.</li>
|
||||
*
|
||||
* <li><code>java.util.FileHandler.filter</code> - specifies
|
||||
* the name of a Filter class. Default value: No Filter.</li>
|
||||
*
|
||||
* <li><code>java.util.FileHandler.formatter</code> - specifies
|
||||
* the name of a Formatter class. Default value:
|
||||
* <code>java.util.logging.XMLFormatter</code>.</li>
|
||||
*
|
||||
* <li><code>java.util.FileHandler.encoding</code> - specifies
|
||||
* the name of the character encoding. Default value:
|
||||
* the default platform encoding.</li>
|
||||
*
|
||||
* <li><code>java.util.FileHandler.limit</code> - specifies the number
|
||||
* of bytes a log file is approximately allowed to reach before it
|
||||
* is closed and the handler switches to the next file in the
|
||||
* rotating set. A value of zero means that files can grow
|
||||
* without limit. Default value: 0 (unlimited growth).</li>
|
||||
*
|
||||
* <li><code>java.util.FileHandler.count</code> - specifies the number
|
||||
* of log files through which this handler cycles. Default value:
|
||||
* 1.</li>
|
||||
*
|
||||
* <li><code>java.util.FileHandler.pattern</code> - specifies a
|
||||
* pattern for the location and name of the produced log files.
|
||||
* See the section on <a href="#filePatterns">file name
|
||||
* patterns</a> for details. Default value:
|
||||
* <code>"%h/java%u.log"</code>.</li>
|
||||
*
|
||||
* <li><code>java.util.FileHandler.append</code> - specifies
|
||||
* whether the handler will append log records to existing
|
||||
* files, or whether the handler will clear log files
|
||||
* upon switching to them. Default value: <code>false</code>,
|
||||
* indicating that files will be cleared.</li>
|
||||
*
|
||||
* </ul>
|
||||
*
|
||||
* <p><a name="filePatterns"><strong>File Name Patterns:</strong></a>
|
||||
* The name and location and log files are specified with pattern
|
||||
* strings. The handler will replace the following character sequences
|
||||
* when opening log files:
|
||||
*
|
||||
* <p><ul>
|
||||
* <li><code>/</code> - replaced by the platform-specific path name
|
||||
* separator. This value is taken from the system property
|
||||
* <code>file.separator</code>.</li>
|
||||
*
|
||||
* <li><code>%t</code> - replaced by the platform-specific location of
|
||||
* the directory intended for temporary files. This value is
|
||||
* taken from the system property <code>java.io.tmpdir</code>.</li>
|
||||
*
|
||||
* <li><code>%h</code> - replaced by the location of the home
|
||||
* directory of the current user. This value is taken from the
|
||||
* system property <code>file.separator</code>.</li>
|
||||
*
|
||||
* <li><code>%g</code> - replaced by a generation number for
|
||||
* distinguisthing the individual items in the rotating set
|
||||
* of log files. The generation number cycles through the
|
||||
* sequence 0, 1, ..., <code>count</code> - 1.</li>
|
||||
*
|
||||
* <li><code>%u</code> - replaced by a unique number for
|
||||
* distinguisthing the output files of several concurrently
|
||||
* running processes. The <code>FileHandler</code> starts
|
||||
* with 0 when it tries to open a log file. If the file
|
||||
* cannot be opened because it is currently in use,
|
||||
* the unique number is incremented by one and opening
|
||||
* is tried again. These steps are repeated until the
|
||||
* opening operation succeeds.
|
||||
*
|
||||
* <p>FIXME: Is the following correct? Please review. The unique
|
||||
* number is determined for each log file individually when it is
|
||||
* opened upon switching to the next file. Therefore, it is not
|
||||
* correct to assume that all log files in a rotating set bear the
|
||||
* same unique number.
|
||||
*
|
||||
* <p>FIXME: The Javadoc for the Sun reference implementation
|
||||
* says: "Note that the use of unique ids to avoid conflicts is
|
||||
* only guaranteed to work reliably when using a local disk file
|
||||
* system." Why? This needs to be mentioned as well, in case
|
||||
* the reviewers decide the statement is true. Otherwise,
|
||||
* file a bug report with Sun.</li>
|
||||
*
|
||||
* <li><code>%%</code> - replaced by a single percent sign.</li>
|
||||
* </ul>
|
||||
*
|
||||
* <p>If the pattern string does not contain <code>%g</code> and
|
||||
* <code>count</code> is greater than one, the handler will append
|
||||
* the string <code>.%g</code> to the specified pattern.
|
||||
*
|
||||
* <p>If the handler attempts to open a log file, this log file
|
||||
* is being used at the time of the attempt, and the pattern string
|
||||
* does not contain <code>%u</code>, the handler will append
|
||||
* the string <code>.%u</code> to the specified pattern. This
|
||||
* step is performed after any generation number has been
|
||||
* appended.
|
||||
*
|
||||
* <p><em>Examples for the GNU platform:</em>
|
||||
*
|
||||
* <p><ul>
|
||||
*
|
||||
* <li><code>%h/java%u.log</code> will lead to a single log file
|
||||
* <code>/home/janet/java0.log</code>, assuming <code>count</code>
|
||||
* equals 1, the user's home directory is
|
||||
* <code>/home/janet</code>, and the attempt to open the file
|
||||
* succeeds.</li>
|
||||
*
|
||||
* <li><code>%h/java%u.log</code> will lead to three log files
|
||||
* <code>/home/janet/java0.log.0</code>,
|
||||
* <code>/home/janet/java0.log.1</code>, and
|
||||
* <code>/home/janet/java0.log.2</code>,
|
||||
* assuming <code>count</code> equals 3, the user's home
|
||||
* directory is <code>/home/janet</code>, and all attempts
|
||||
* to open files succeed.</li>
|
||||
*
|
||||
* <li><code>%h/java%u.log</code> will lead to three log files
|
||||
* <code>/home/janet/java0.log.0</code>,
|
||||
* <code>/home/janet/java1.log.1</code>, and
|
||||
* <code>/home/janet/java0.log.2</code>,
|
||||
* assuming <code>count</code> equals 3, the user's home
|
||||
* directory is <code>/home/janet</code>, and the attempt
|
||||
* to open <code>/home/janet/java0.log.1</code> fails.</li>
|
||||
*
|
||||
* </ul>
|
||||
*
|
||||
* @author Sascha Brawer (brawer@acm.org)
|
||||
*/
|
||||
public class FileHandler
|
||||
extends StreamHandler
|
||||
{
|
||||
/**
|
||||
* The number of bytes a log file is approximately allowed to reach
|
||||
* before it is closed and the handler switches to the next file in
|
||||
* the rotating set. A value of zero means that files can grow
|
||||
* without limit.
|
||||
*/
|
||||
private final int limit;
|
||||
|
||||
|
||||
/**
|
||||
* The number of log files through which this handler cycles.
|
||||
*/
|
||||
private final int count;
|
||||
|
||||
|
||||
/**
|
||||
* The pattern for the location and name of the produced log files.
|
||||
* See the section on <a href="#filePatterns">file name patterns</a>
|
||||
* for details.
|
||||
*/
|
||||
private final String pattern;
|
||||
|
||||
|
||||
/**
|
||||
* Indicates whether the handler will append log records to existing
|
||||
* files (<code>true</code>), or whether the handler will clear log files
|
||||
* upon switching to them (<code>false</code>).
|
||||
*/
|
||||
private final boolean append;
|
||||
|
||||
|
||||
/**
|
||||
* Constructs a <code>FileHandler</code>, taking all property values
|
||||
* from the current {@link LogManager LogManager} configuration.
|
||||
*
|
||||
* @throws java.io.IOException FIXME: The Sun Javadoc says: "if
|
||||
* there are IO problems opening the files." This conflicts
|
||||
* with the general principle that configuration errors do
|
||||
* not prohibit construction. Needs review.
|
||||
*
|
||||
* @throws SecurityException if a security manager exists and
|
||||
* the caller is not granted the permission to control
|
||||
* the logging infrastructure.
|
||||
*/
|
||||
public FileHandler()
|
||||
throws IOException, SecurityException
|
||||
{
|
||||
this(/* pattern: use configiguration */ null,
|
||||
|
||||
LogManager.getIntProperty("java.util.logging.FileHandler.limit",
|
||||
/* default */ 0),
|
||||
|
||||
LogManager.getIntProperty("java.util.logging.FileHandler.count",
|
||||
/* default */ 1),
|
||||
|
||||
LogManager.getBooleanProperty("java.util.logging.FileHandler.append",
|
||||
/* default */ false));
|
||||
}
|
||||
|
||||
|
||||
/* FIXME: Javadoc missing. */
|
||||
public FileHandler(String pattern)
|
||||
throws IOException, SecurityException
|
||||
{
|
||||
this(pattern,
|
||||
/* limit */ 0,
|
||||
/* count */ 1,
|
||||
/* append */ false);
|
||||
}
|
||||
|
||||
|
||||
/* FIXME: Javadoc missing. */
|
||||
public FileHandler(String pattern, boolean append)
|
||||
throws IOException, SecurityException
|
||||
{
|
||||
this(pattern,
|
||||
/* limit */ 0,
|
||||
/* count */ 1,
|
||||
append);
|
||||
}
|
||||
|
||||
|
||||
/* FIXME: Javadoc missing. */
|
||||
public FileHandler(String pattern, int limit, int count)
|
||||
throws IOException, SecurityException
|
||||
{
|
||||
this(pattern, limit, count,
|
||||
LogManager.getBooleanProperty(
|
||||
"java.util.logging.FileHandler.append",
|
||||
/* default */ false));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Constructs a <code>FileHandler</code> given the pattern for the
|
||||
* location and name of the produced log files, the size limit, the
|
||||
* number of log files thorough which the handler will rotate, and
|
||||
* the <code>append</code> property. All other property values are
|
||||
* taken from the current {@link LogManager LogManager}
|
||||
* configuration.
|
||||
*
|
||||
* @param pattern The pattern for the location and name of the
|
||||
* produced log files. See the section on <a
|
||||
* href="#filePatterns">file name patterns</a> for details.
|
||||
* If <code>pattern</code> is <code>null</code>, the value is
|
||||
* taken from the {@link LogManager LogManager} configuration
|
||||
* property
|
||||
* <code>java.util.logging.FileHandler.pattern</code>.
|
||||
* However, this is a pecularity of the GNU implementation,
|
||||
* and Sun's API specification does not mention what behavior
|
||||
* is to be expected for <code>null</code>. Therefore,
|
||||
* applications should not rely on this feature.
|
||||
*
|
||||
* @param limit specifies the number of bytes a log file is
|
||||
* approximately allowed to reach before it is closed and the
|
||||
* handler switches to the next file in the rotating set. A
|
||||
* value of zero means that files can grow without limit.
|
||||
*
|
||||
* @param count specifies the number of log files through which this
|
||||
* handler cycles.
|
||||
*
|
||||
* @param append specifies whether the handler will append log
|
||||
* records to existing files (<code>true</code>), or whether the
|
||||
* handler will clear log files upon switching to them
|
||||
* (<code>false</code>).
|
||||
*
|
||||
* @throws java.io.IOException FIXME: The Sun Javadoc says: "if
|
||||
* there are IO problems opening the files." This conflicts
|
||||
* with the general principle that configuration errors do
|
||||
* not prohibit construction. Needs review.
|
||||
*
|
||||
* @throws SecurityException if a security manager exists and
|
||||
* the caller is not granted the permission to control
|
||||
* the logging infrastructure.
|
||||
* <p>FIXME: This seems in contrast to all other handler
|
||||
* constructors -- verify this by running tests against
|
||||
* the Sun reference implementation.
|
||||
*/
|
||||
public FileHandler(String pattern,
|
||||
int limit,
|
||||
int count,
|
||||
boolean append)
|
||||
throws IOException, SecurityException
|
||||
{
|
||||
super(createFileStream(pattern, limit, count, append,
|
||||
/* generation */ 0),
|
||||
"java.util.logging.FileHandler",
|
||||
/* default level */ Level.ALL,
|
||||
/* formatter */ null,
|
||||
/* default formatter */ XMLFormatter.class);
|
||||
|
||||
if ((limit <0) || (count < 1))
|
||||
throw new IllegalArgumentException();
|
||||
|
||||
this.pattern = pattern;
|
||||
this.limit = limit;
|
||||
this.count = count;
|
||||
this.append = append;
|
||||
}
|
||||
|
||||
|
||||
/* FIXME: Javadoc missing. */
|
||||
private static java.io.OutputStream createFileStream(String pattern,
|
||||
int limit,
|
||||
int count,
|
||||
boolean append,
|
||||
int generation)
|
||||
{
|
||||
String path;
|
||||
int unique = 0;
|
||||
|
||||
/* Throws a SecurityException if the caller does not have
|
||||
* LoggingPermission("control").
|
||||
*/
|
||||
LogManager.getLogManager().checkAccess();
|
||||
|
||||
/* Default value from the java.util.logging.FileHandler.pattern
|
||||
* LogManager configuration property.
|
||||
*/
|
||||
if (pattern == null)
|
||||
pattern = LogManager.getLogManager().getProperty(
|
||||
"java.util.logging.FileHandler.pattern");
|
||||
if (pattern == null)
|
||||
pattern = "%h/java%u.log";
|
||||
|
||||
do
|
||||
{
|
||||
path = replaceFileNameEscapes(pattern, generation, unique, count);
|
||||
|
||||
try
|
||||
{
|
||||
File file = new File(path);
|
||||
if (file.createNewFile())
|
||||
return new FileOutputStream(path, append);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
ex.printStackTrace();
|
||||
}
|
||||
|
||||
unique = unique + 1;
|
||||
if (pattern.indexOf("%u") < 0)
|
||||
pattern = pattern + ".%u";
|
||||
}
|
||||
while (true);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Replaces the substrings <code>"/"</code> by the value of the
|
||||
* system property <code>"file.separator"</code>, <code>"%t"</code>
|
||||
* by the value of the system property
|
||||
* <code>"java.io.tmpdir"</code>, <code>"%h"</code> by the value of
|
||||
* the system property <code>"user.home"</code>, <code>"%g"</code>
|
||||
* by the value of <code>generation</code>, <code>"%u"</code> by the
|
||||
* value of <code>uniqueNumber</code>, and <code>"%%"</code> by a
|
||||
* single percent character. If <code>pattern<code> does
|
||||
* <em>not</em> contain the sequence <code>"%g"</code>,
|
||||
* the value of <code>generation</code> will be appended to
|
||||
* the result.
|
||||
*
|
||||
* @throws NullPointerException if one of the system properties
|
||||
* <code>"file.separator"</code>,
|
||||
* <code>"java.io.tmpdir"</code>, or
|
||||
* <code>"user.home"</code> has no value and the
|
||||
* corresponding escape sequence appears in
|
||||
* <code>pattern</code>.
|
||||
*/
|
||||
private static String replaceFileNameEscapes(String pattern,
|
||||
int generation,
|
||||
int uniqueNumber,
|
||||
int count)
|
||||
{
|
||||
StringBuffer buf = new StringBuffer(pattern);
|
||||
String replaceWith;
|
||||
boolean foundGeneration = false;
|
||||
|
||||
int pos = 0;
|
||||
do
|
||||
{
|
||||
// Uncomment the next line for finding bugs.
|
||||
// System.out.println(buf.substring(0,pos) + '|' + buf.substring(pos));
|
||||
|
||||
if (buf.charAt(pos) == '/')
|
||||
{
|
||||
/* The same value is also provided by java.io.File.separator. */
|
||||
replaceWith = System.getProperty("file.separator");
|
||||
buf.replace(pos, pos + 1, replaceWith);
|
||||
pos = pos + replaceWith.length() - 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (buf.charAt(pos) == '%')
|
||||
{
|
||||
switch (buf.charAt(pos + 1))
|
||||
{
|
||||
case 't':
|
||||
replaceWith = System.getProperty("java.io.tmpdir");
|
||||
break;
|
||||
|
||||
case 'h':
|
||||
replaceWith = System.getProperty("user.home");
|
||||
break;
|
||||
|
||||
case 'g':
|
||||
replaceWith = Integer.toString(generation);
|
||||
foundGeneration = true;
|
||||
break;
|
||||
|
||||
case 'u':
|
||||
replaceWith = Integer.toString(uniqueNumber);
|
||||
break;
|
||||
|
||||
case '%':
|
||||
replaceWith = "%";
|
||||
break;
|
||||
|
||||
default:
|
||||
replaceWith = "??";
|
||||
break; // FIXME: Throw exception?
|
||||
}
|
||||
|
||||
buf.replace(pos, pos + 2, replaceWith);
|
||||
pos = pos + replaceWith.length() - 1;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
while (++pos < buf.length() - 1);
|
||||
|
||||
if (!foundGeneration && (count > 1))
|
||||
{
|
||||
buf.append('.');
|
||||
buf.append(generation);
|
||||
}
|
||||
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
|
||||
/* FIXME: Javadoc missing, implementation incomplete. */
|
||||
public void publish(LogRecord record)
|
||||
{
|
||||
super.publish(record);
|
||||
|
||||
/* FIXME: Decide when to switch over. How do we get to
|
||||
* the number of bytes published so far? Two possibilities:
|
||||
* 1. File.length, 2. have metering wrapper around
|
||||
* output stream counting the number of written bytes.
|
||||
*/
|
||||
|
||||
/* FIXME: Switch over if needed! This implementation always
|
||||
* writes into a single file, i.e. behaves as if limit
|
||||
* always was zero. So, the implementation is somewhat
|
||||
* functional but incomplete.
|
||||
*/
|
||||
}
|
||||
}
|
68
libjava/java/util/logging/Filter.java
Normal file
68
libjava/java/util/logging/Filter.java
Normal file
@ -0,0 +1,68 @@
|
||||
/* Filter.java
|
||||
-- an interface for filters that decide whether a LogRecord should
|
||||
be published or discarded
|
||||
|
||||
Copyright (C) 2002 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Classpath.
|
||||
|
||||
GNU Classpath is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
GNU Classpath is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GNU Classpath; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
02111-1307 USA.
|
||||
|
||||
Linking this library statically or dynamically with other modules is
|
||||
making a combined work based on this library. Thus, the terms and
|
||||
conditions of the GNU General Public License cover the whole
|
||||
combination.
|
||||
|
||||
As a special exception, the copyright holders of this library give you
|
||||
permission to link this library with independent modules to produce an
|
||||
executable, regardless of the license terms of these independent
|
||||
modules, and to copy and distribute the resulting executable under
|
||||
terms of your choice, provided that you also meet, for each linked
|
||||
independent module, the terms and conditions of the license of that
|
||||
module. An independent module is a module which is not derived from
|
||||
or based on this library. If you modify this library, you may extend
|
||||
this exception to your version of the library, but you are not
|
||||
obligated to do so. If you do not wish to do so, delete this
|
||||
exception statement from your version.
|
||||
|
||||
*/
|
||||
|
||||
|
||||
package java.util.logging;
|
||||
|
||||
/**
|
||||
* By implementing the <code>Filter</code> interface, applications
|
||||
* can control what is being logged based on arbitrary properties,
|
||||
* not just the severity level. Both <code>Handler</code> and
|
||||
* <code>Logger</code> allow to register Filters whose
|
||||
* <code>isLoggable</code> method will be called when a
|
||||
* <code>LogRecord</code> has passed the test based on the
|
||||
* severity level.
|
||||
*
|
||||
* @author Sascha Brawer (brawer@acm.org)
|
||||
*/
|
||||
public interface Filter
|
||||
{
|
||||
/**
|
||||
* Determines whether a LogRecord should be published or discarded.
|
||||
*
|
||||
* @param record the <code>LogRecord</code> to be inspected.
|
||||
*
|
||||
* @return <code>true</code> if the record should be published,
|
||||
* <code>false</code> if it should be discarded.
|
||||
*/
|
||||
public boolean isLoggable(LogRecord record);
|
||||
}
|
174
libjava/java/util/logging/Formatter.java
Normal file
174
libjava/java/util/logging/Formatter.java
Normal file
@ -0,0 +1,174 @@
|
||||
/* Formatter.java
|
||||
-- a class for formatting log messages by localizing message texts
|
||||
and performing substitution of parameters
|
||||
|
||||
Copyright (C) 2002 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Classpath.
|
||||
|
||||
GNU Classpath is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
GNU Classpath is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GNU Classpath; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
02111-1307 USA.
|
||||
|
||||
Linking this library statically or dynamically with other modules is
|
||||
making a combined work based on this library. Thus, the terms and
|
||||
conditions of the GNU General Public License cover the whole
|
||||
combination.
|
||||
|
||||
As a special exception, the copyright holders of this library give you
|
||||
permission to link this library with independent modules to produce an
|
||||
executable, regardless of the license terms of these independent
|
||||
modules, and to copy and distribute the resulting executable under
|
||||
terms of your choice, provided that you also meet, for each linked
|
||||
independent module, the terms and conditions of the license of that
|
||||
module. An independent module is a module which is not derived from
|
||||
or based on this library. If you modify this library, you may extend
|
||||
this exception to your version of the library, but you are not
|
||||
obligated to do so. If you do not wish to do so, delete this
|
||||
exception statement from your version.
|
||||
|
||||
*/
|
||||
|
||||
|
||||
package java.util.logging;
|
||||
|
||||
import java.util.ResourceBundle;
|
||||
import java.text.MessageFormat;
|
||||
|
||||
/**
|
||||
* A <code>Formatter</code> supports handlers by localizing
|
||||
* message texts and by subsituting parameter values for their
|
||||
* placeholders.
|
||||
*
|
||||
* @author Sascha Brawer (brawer@acm.org)
|
||||
*/
|
||||
public abstract class Formatter
|
||||
{
|
||||
/**
|
||||
* Constructs a new Formatter.
|
||||
*/
|
||||
protected Formatter()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Formats a LogRecord into a string. Usually called by handlers
|
||||
* which need a string for a log record, for example to append
|
||||
* a record to a log file or to transmit a record over the network.
|
||||
*
|
||||
* @param record the log record for which a string form is requested.
|
||||
*/
|
||||
public abstract String format(LogRecord record);
|
||||
|
||||
|
||||
/**
|
||||
* Returns a string that handlers are supposed to emit before
|
||||
* the first log record. The base implementation returns an
|
||||
* empty string, but subclasses such as {@link XMLFormatter}
|
||||
* override this method in order to provide a suitable header.
|
||||
*
|
||||
* @return a string for the header.
|
||||
*
|
||||
* @param handler the handler which will prepend the returned
|
||||
* string in front of the first log record. This method
|
||||
* may inspect certain properties of the handler, for
|
||||
* example its encoding, in order to construct the header.
|
||||
*/
|
||||
public String getHead(Handler handler)
|
||||
{
|
||||
return "";
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns a string that handlers are supposed to emit after
|
||||
* the last log record. The base implementation returns an
|
||||
* empty string, but subclasses such as {@link XMLFormatter}
|
||||
* override this method in order to provide a suitable tail.
|
||||
*
|
||||
* @return a string for the header.
|
||||
*
|
||||
* @param handler the handler which will append the returned
|
||||
* string after the last log record. This method
|
||||
* may inspect certain properties of the handler
|
||||
* in order to construct the tail.
|
||||
*/
|
||||
public String getTail(Handler handler)
|
||||
{
|
||||
return "";
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Formats the message part of a log record.
|
||||
*
|
||||
* <p>First, the Formatter localizes the record message to the
|
||||
* default locale by looking up the message in the record's
|
||||
* localization resource bundle. If this step fails because there
|
||||
* is no resource bundle associated with the record, or because the
|
||||
* record message is not a key in the bundle, the raw message is
|
||||
* used instead.
|
||||
*
|
||||
* <p>Second, the Formatter substitutes appropriate strings for
|
||||
* the message parameters. If the record returns a non-empty
|
||||
* array for <code>getParameters()</code> and the localized
|
||||
* message string contains the character sequence "{0", the
|
||||
* formatter uses <code>java.text.MessageFormat</code> to format
|
||||
* the message. Otherwise, no parameter substitution is performed.
|
||||
*
|
||||
* @param record the log record to be localized and formatted.
|
||||
*
|
||||
* @return the localized message text where parameters have been
|
||||
* substituted by suitable strings.
|
||||
*
|
||||
* @throws NullPointerException if <code>record</code>
|
||||
* is <code>null</code>.
|
||||
*/
|
||||
public String formatMessage(LogRecord record)
|
||||
{
|
||||
String msg;
|
||||
ResourceBundle bundle;
|
||||
Object[] params;
|
||||
|
||||
/* This will throw a NullPointerExceptionif record is null. */
|
||||
msg = record.getMessage();
|
||||
if (msg == null)
|
||||
msg = "";
|
||||
|
||||
/* Try to localize the message. */
|
||||
bundle = record.getResourceBundle();
|
||||
if (bundle != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
msg = bundle.getString(msg);
|
||||
}
|
||||
catch (java.util.MissingResourceException _)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
/* Format the message if there are parameters. */
|
||||
params = record.getParameters();
|
||||
if ((params != null)
|
||||
&& (params.length > 0)
|
||||
&& (msg.indexOf("{0") >= 0))
|
||||
{
|
||||
msg = MessageFormat.format(msg, params);
|
||||
}
|
||||
|
||||
return msg;
|
||||
}
|
||||
}
|
390
libjava/java/util/logging/Handler.java
Normal file
390
libjava/java/util/logging/Handler.java
Normal file
@ -0,0 +1,390 @@
|
||||
/* Handler.java
|
||||
-- a class for publishing log messages
|
||||
|
||||
Copyright (C) 2002 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Classpath.
|
||||
|
||||
GNU Classpath is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
GNU Classpath is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GNU Classpath; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
02111-1307 USA.
|
||||
|
||||
Linking this library statically or dynamically with other modules is
|
||||
making a combined work based on this library. Thus, the terms and
|
||||
conditions of the GNU General Public License cover the whole
|
||||
combination.
|
||||
|
||||
As a special exception, the copyright holders of this library give you
|
||||
permission to link this library with independent modules to produce an
|
||||
executable, regardless of the license terms of these independent
|
||||
modules, and to copy and distribute the resulting executable under
|
||||
terms of your choice, provided that you also meet, for each linked
|
||||
independent module, the terms and conditions of the license of that
|
||||
module. An independent module is a module which is not derived from
|
||||
or based on this library. If you modify this library, you may extend
|
||||
this exception to your version of the library, but you are not
|
||||
obligated to do so. If you do not wish to do so, delete this
|
||||
exception statement from your version.
|
||||
|
||||
*/
|
||||
|
||||
|
||||
package java.util.logging;
|
||||
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.security.AccessController;
|
||||
|
||||
/**
|
||||
* A <code>Handler</code> publishes <code>LogRecords</code> to
|
||||
* a sink, for example a file, the console or a network socket.
|
||||
* There are different subclasses of <code>Handler</code>
|
||||
* to deal with different kinds of sinks.
|
||||
*
|
||||
* <p>FIXME: Are handlers thread-safe, or is the assumption that only
|
||||
* loggers are, and a handler can belong only to one single logger? If
|
||||
* the latter, should we enforce it? (Spec not clear). In any
|
||||
* case, it needs documentation.
|
||||
*
|
||||
* @author Sascha Brawer (brawer@acm.org)
|
||||
*/
|
||||
public abstract class Handler
|
||||
{
|
||||
Formatter formatter;
|
||||
Filter filter;
|
||||
Level level;
|
||||
ErrorManager errorManager;
|
||||
String encoding;
|
||||
|
||||
/**
|
||||
* Constructs a Handler with a logging severity level of
|
||||
* <code>Level.ALL</code>, no formatter, no filter, and
|
||||
* an instance of <code>ErrorManager</code> managing errors.
|
||||
*
|
||||
* <p><strong>Specification Note:</strong> The specification of the
|
||||
* Java<sup>TM</sup> Logging API does not mention which character
|
||||
* encoding is to be used by freshly constructed Handlers. The GNU
|
||||
* implementation uses the default platform encoding, but other
|
||||
* Java implementations might behave differently.
|
||||
*
|
||||
* <p><strong>Specification Note:</strong> While a freshly constructed
|
||||
* Handler is required to have <em>no filter</em> according to the
|
||||
* specification, <code>null</code> is not a valid parameter for
|
||||
* <code>Handler.setFormatter</code>. Therefore, the following
|
||||
* code will throw a <code>java.lang.NullPointerException</code>:
|
||||
*
|
||||
* <p><pre>Handler h = new MyConcreteSubclassOfHandler();
|
||||
h.setFormatter(h.getFormatter());</pre>
|
||||
*
|
||||
* It seems strange that a freshly constructed Handler is not
|
||||
* supposed to provide a Formatter, but this is what the specification
|
||||
* says.
|
||||
*/
|
||||
{
|
||||
level = Level.ALL;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Publishes a <code>LogRecord</code> to an appropriate sink,
|
||||
* provided the record passes all tests for being loggable. The
|
||||
* <code>Handler</code> will localize the message of the log
|
||||
* record and substitute any message parameters.
|
||||
*
|
||||
* <p>Most applications do not need to call this method directly.
|
||||
* Instead, they will use use a {@link Logger}, which will
|
||||
* create LogRecords and distribute them to registered handlers.
|
||||
*
|
||||
* <p>In case of an I/O failure, the <code>ErrorManager</code>
|
||||
* of this <code>Handler</code> will be informed, but the caller
|
||||
* of this method will not receive an exception.
|
||||
*
|
||||
* @param record the log event to be published.
|
||||
*/
|
||||
public abstract void publish(LogRecord record);
|
||||
|
||||
|
||||
/**
|
||||
* Forces any data that may have been buffered to the underlying
|
||||
* output device.
|
||||
*
|
||||
* <p>In case of an I/O failure, the <code>ErrorManager</code>
|
||||
* of this <code>Handler</code> will be informed, but the caller
|
||||
* of this method will not receive an exception.
|
||||
*/
|
||||
public abstract void flush();
|
||||
|
||||
|
||||
/**
|
||||
* Closes this <code>Handler</code> after having flushed
|
||||
* the buffers. As soon as <code>close</code> has been called,
|
||||
* a <code>Handler</code> should not be used anymore. Attempts
|
||||
* to publish log records, to flush buffers, or to modify the
|
||||
* <code>Handler</code> in any other way may throw runtime
|
||||
* exceptions after calling <code>close</code>.
|
||||
*
|
||||
* <p>In case of an I/O failure, the <code>ErrorManager</code>
|
||||
* of this <code>Handler</code> will be informed, but the caller
|
||||
* of this method will not receive an exception.
|
||||
*
|
||||
* @throws SecurityException if a security manager exists and
|
||||
* the caller is not granted the permission to control
|
||||
* the logging infrastructure.
|
||||
*/
|
||||
public abstract void close()
|
||||
throws SecurityException;
|
||||
|
||||
|
||||
/**
|
||||
* Returns the <code>Formatter</code> which will be used to
|
||||
* localize the text of log messages and to substitute
|
||||
* message parameters. A <code>Handler</code> is encouraged,
|
||||
* but not required to actually use an assigned
|
||||
* <code>Formatter</code>.
|
||||
*
|
||||
* @return the <code>Formatter</code> being used, or
|
||||
* <code>null</code> if this <code>Handler</code>
|
||||
* does not use formatters and no formatter has
|
||||
* ever been set by calling <code>setFormatter</code>.
|
||||
*/
|
||||
public Formatter getFormatter()
|
||||
{
|
||||
return formatter;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Sets the <code>Formatter</code> which will be used to
|
||||
* localize the text of log messages and to substitute
|
||||
* message parameters. A <code>Handler</code> is encouraged,
|
||||
* but not required to actually use an assigned
|
||||
* <code>Formatter</code>.
|
||||
*
|
||||
* @param formatter the new <code>Formatter</code> to use.
|
||||
*
|
||||
* @throws SecurityException if a security manager exists and
|
||||
* the caller is not granted the permission to control
|
||||
* the logging infrastructure.
|
||||
*
|
||||
* @throws NullPointerException if <code>formatter</code> is
|
||||
* <code>null</code>.
|
||||
*/
|
||||
public void setFormatter(Formatter formatter)
|
||||
throws SecurityException
|
||||
{
|
||||
LogManager.getLogManager().checkAccess();
|
||||
|
||||
/* Throws a NullPointerException if formatter is null. */
|
||||
formatter.getClass();
|
||||
|
||||
this.formatter = formatter;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the character encoding which this handler uses for publishing
|
||||
* log records.
|
||||
*
|
||||
* @param encoding the name of a character encoding, or <code>null</code>
|
||||
* for the default platform encoding.
|
||||
*/
|
||||
public String getEncoding()
|
||||
{
|
||||
return encoding;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Sets the character encoding which this handler uses for publishing
|
||||
* log records. The encoding of a <code>Handler</code> must be
|
||||
* set before any log records have been published.
|
||||
*
|
||||
* @param encoding the name of a character encoding, or <code>null</code>
|
||||
* for the default encoding.
|
||||
*
|
||||
* @exception SecurityException if a security manager exists and
|
||||
* the caller is not granted the permission to control
|
||||
* the logging infrastructure.
|
||||
*
|
||||
*/
|
||||
public void setEncoding(String encoding)
|
||||
throws SecurityException, UnsupportedEncodingException
|
||||
{
|
||||
/* Should any developer ever change this implementation, they are
|
||||
* advised to have a look at StreamHandler.setEncoding(String),
|
||||
* which overrides this method without calling super.setEncoding.
|
||||
*/
|
||||
LogManager.getLogManager().checkAccess();
|
||||
|
||||
/* Simple check for supported encodings. This is more expensive
|
||||
* than it could be, but this method is overwritten by StreamHandler
|
||||
* anyway.
|
||||
*/
|
||||
if (encoding != null)
|
||||
new String(new byte[0], encoding);
|
||||
|
||||
this.encoding = encoding;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the <code>Filter</code> that currently controls which
|
||||
* log records are being published by this <code>Handler</code>.
|
||||
*
|
||||
* @return the currently active <code>Filter</code>, or
|
||||
* <code>null</code> if no filter has been associated.
|
||||
* In the latter case, log records are filtered purely
|
||||
* based on their severity level.
|
||||
*/
|
||||
public Filter getFilter()
|
||||
{
|
||||
return filter;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Sets the <code>Filter</code> for controlling which
|
||||
* log records will be published by this <code>Handler</code>.
|
||||
*
|
||||
* @return the <code>Filter</code> to use, or
|
||||
* <code>null</code> to filter log records purely based
|
||||
* on their severity level.
|
||||
*/
|
||||
public void setFilter(Filter filter)
|
||||
throws SecurityException
|
||||
{
|
||||
LogManager.getLogManager().checkAccess();
|
||||
this.filter = filter;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the <code>ErrorManager</code> that currently deals
|
||||
* with errors originating from this Handler.
|
||||
*
|
||||
* @exception SecurityException if a security manager exists and
|
||||
* the caller is not granted the permission to control
|
||||
* the logging infrastructure.
|
||||
*/
|
||||
public ErrorManager getErrorManager()
|
||||
{
|
||||
LogManager.getLogManager().checkAccess();
|
||||
|
||||
/* Developers wanting to change the subsequent code should
|
||||
* have a look at Handler.reportError -- it also can create
|
||||
* an ErrorManager, but does so without checking permissions
|
||||
* to control the logging infrastructure.
|
||||
*/
|
||||
if (errorManager == null)
|
||||
errorManager = new ErrorManager();
|
||||
|
||||
return errorManager;
|
||||
}
|
||||
|
||||
|
||||
public void setErrorManager(ErrorManager manager)
|
||||
{
|
||||
LogManager.getLogManager().checkAccess();
|
||||
|
||||
/* Make sure manager is not null. */
|
||||
manager.getClass();
|
||||
|
||||
this.errorManager = manager;
|
||||
}
|
||||
|
||||
|
||||
protected void reportError(String message, Exception ex, int code)
|
||||
{
|
||||
if (errorManager == null)
|
||||
errorManager = new ErrorManager();
|
||||
|
||||
errorManager.error(message, ex, code);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the severity level threshold for this <code>Handler</code>
|
||||
* All log records with a lower severity level will be discarded;
|
||||
* a log record of the same or a higher level will be published
|
||||
* unless an installed <code>Filter</code> decides to discard it.
|
||||
*
|
||||
* @return the severity level below which all log messages
|
||||
* will be discarded.
|
||||
*/
|
||||
public Level getLevel()
|
||||
{
|
||||
return level;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Sets the severity level threshold for this <code>Handler</code>.
|
||||
* All log records with a lower severity level will be discarded;
|
||||
* a log record of the same or a higher level will be published
|
||||
* unless an installed <code>Filter</code> decides to discard it.
|
||||
*
|
||||
* @param level the severity level below which all log messages
|
||||
* will be discarded.
|
||||
*
|
||||
* @exception SecurityException if a security manager exists and
|
||||
* the caller is not granted the permission to control
|
||||
* the logging infrastructure.
|
||||
*
|
||||
* @exception NullPointerException if <code>level</code> is
|
||||
* <code>null</code>.
|
||||
*/
|
||||
public void setLevel(Level level)
|
||||
{
|
||||
LogManager.getLogManager().checkAccess();
|
||||
|
||||
/* Throw NullPointerException if level is null. */
|
||||
level.getClass();
|
||||
this.level = level;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Checks whether a <code>LogRecord</code> would be logged
|
||||
* if it was passed to this <code>Handler</code> for publication.
|
||||
*
|
||||
* <p>The <code>Handler</code> implementation considers a record as
|
||||
* loggable if its level is greater than or equal to the severity
|
||||
* level threshold. In a second step, if a {@link Filter} has
|
||||
* been installed, its {@link Filter#isLoggable(LogRecord) isLoggable}
|
||||
* method is invoked. Subclasses of <code>Handler</code> can override
|
||||
* this method to impose their own constraints.
|
||||
*
|
||||
* @param record the <code>LogRecord</code> to be checked.
|
||||
*
|
||||
* @return <code>true</code> if <code>record</code> would
|
||||
* be published by {@link #publish(LogRecord) publish},
|
||||
* <code>false</code> if it would be discarded.
|
||||
*
|
||||
* @see #setLevel(Level)
|
||||
* @see #setFilter(Filter)
|
||||
* @see Filter#isLoggable(LogRecord)
|
||||
*
|
||||
* @throws NullPointerException if <code>record</code>
|
||||
* is <code>null</code>.
|
||||
*/
|
||||
public boolean isLoggable(LogRecord record)
|
||||
{
|
||||
if (record.getLevel().intValue() < level.intValue())
|
||||
return false;
|
||||
|
||||
if (filter != null)
|
||||
return filter.isLoggable(record);
|
||||
else
|
||||
return true;
|
||||
}
|
||||
}
|
417
libjava/java/util/logging/Level.java
Normal file
417
libjava/java/util/logging/Level.java
Normal file
@ -0,0 +1,417 @@
|
||||
/* Level.java -- a class for indicating logging levels
|
||||
Copyright (C) 2002 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Classpath.
|
||||
|
||||
GNU Classpath is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
GNU Classpath is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GNU Classpath; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
02111-1307 USA.
|
||||
|
||||
Linking this library statically or dynamically with other modules is
|
||||
making a combined work based on this library. Thus, the terms and
|
||||
conditions of the GNU General Public License cover the whole
|
||||
combination.
|
||||
|
||||
As a special exception, the copyright holders of this library give you
|
||||
permission to link this library with independent modules to produce an
|
||||
executable, regardless of the license terms of these independent
|
||||
modules, and to copy and distribute the resulting executable under
|
||||
terms of your choice, provided that you also meet, for each linked
|
||||
independent module, the terms and conditions of the license of that
|
||||
module. An independent module is a module which is not derived from
|
||||
or based on this library. If you modify this library, you may extend
|
||||
this exception to your version of the library, but you are not
|
||||
obligated to do so. If you do not wish to do so, delete this
|
||||
exception statement from your version.
|
||||
|
||||
*/
|
||||
|
||||
|
||||
package java.util.logging;
|
||||
|
||||
import java.util.ResourceBundle;
|
||||
|
||||
|
||||
/**
|
||||
* A class for indicating logging levels. A number of commonly used
|
||||
* levels is pre-defined (such as <code>java.util.logging.Level.INFO</code>),
|
||||
* and applications should utilize those whenever possible. For specialized
|
||||
* purposes, however, applications can sub-class Level in order to define
|
||||
* custom logging levels.
|
||||
*
|
||||
* @author Sascha Brawer <brawer@acm.org>
|
||||
*/
|
||||
public class Level
|
||||
implements java.io.Serializable
|
||||
{
|
||||
/* The integer values are the same as in the Sun J2SE 1.4.
|
||||
* They have been obtained with a test program. In J2SE 1.4.1,
|
||||
* Sun has amended the API documentation; these values are now
|
||||
* publicly documented.
|
||||
*/
|
||||
|
||||
/**
|
||||
* The <code>OFF</code> level is used as a threshold for filtering
|
||||
* log records, meaning that no message should be logged.
|
||||
*
|
||||
* @see Logger#setLevel(java.util.logging.Level)
|
||||
*/
|
||||
public static final Level OFF = new Level ("OFF", Integer.MAX_VALUE);
|
||||
|
||||
/**
|
||||
* Log records whose level is <code>SEVERE</code> indicate a serious
|
||||
* failure that prevents normal program execution. Messages at this
|
||||
* level should be understandable to an inexperienced, non-technical
|
||||
* end user. Ideally, they explain in simple words what actions the
|
||||
* user can take in order to resolve the problem.
|
||||
*/
|
||||
public static final Level SEVERE = new Level ("SEVERE", 1000);
|
||||
|
||||
|
||||
/**
|
||||
* Log records whose level is <code>WARNING</code> indicate a
|
||||
* potential problem that does not prevent normal program execution.
|
||||
* Messages at this level should be understandable to an
|
||||
* inexperienced, non-technical end user. Ideally, they explain in
|
||||
* simple words what actions the user can take in order to resolve
|
||||
* the problem.
|
||||
*/
|
||||
public static final Level WARNING = new Level ("WARNING", 900);
|
||||
|
||||
|
||||
/**
|
||||
* Log records whose level is <code>INFO</code> are used in purely
|
||||
* informational situations that do not constitute serious errors or
|
||||
* potential problems. In the default logging configuration, INFO
|
||||
* messages will be written to the system console. For this reason,
|
||||
* the INFO level should be used only for messages that are
|
||||
* important to end users and system administrators. Messages at
|
||||
* this level should be understandable to an inexperienced,
|
||||
* non-technical user.
|
||||
*/
|
||||
public static final Level INFO = new Level ("INFO", 800);
|
||||
|
||||
|
||||
/**
|
||||
* Log records whose level is <code>CONFIG</code> are used for
|
||||
* describing the static configuration, for example the windowing
|
||||
* environment, the operating system version, etc.
|
||||
*/
|
||||
public static final Level CONFIG = new Level ("CONFIG", 700);
|
||||
|
||||
|
||||
/**
|
||||
* Log records whose level is <code>FINE</code> are typically used
|
||||
* for messages that are relevant for developers using
|
||||
* the component generating log messages. Examples include minor,
|
||||
* recoverable failures, or possible inefficiencies.
|
||||
*/
|
||||
public static final Level FINE = new Level ("FINE", 500);
|
||||
|
||||
|
||||
/**
|
||||
* Log records whose level is <code>FINER</code> are intended for
|
||||
* rather detailed tracing, for example entering a method, returning
|
||||
* from a method, or throwing an exception.
|
||||
*/
|
||||
public static final Level FINER = new Level ("FINER", 400);
|
||||
|
||||
|
||||
/**
|
||||
* Log records whose level is <code>FINEST</code> are used for
|
||||
* highly detailed tracing, for example to indicate that a certain
|
||||
* point inside the body of a method has been reached.
|
||||
*/
|
||||
public static final Level FINEST = new Level ("FINEST", 300);
|
||||
|
||||
|
||||
/**
|
||||
* The <code>ALL</code> level is used as a threshold for filtering
|
||||
* log records, meaning that every message should be logged.
|
||||
*
|
||||
* @see Logger#setLevel(java.util.logging.Level)
|
||||
*/
|
||||
public static final Level ALL = new Level ("ALL", Integer.MIN_VALUE);
|
||||
|
||||
|
||||
private static final Level[] knownLevels = {
|
||||
ALL, FINEST, FINER, FINE, CONFIG, INFO, WARNING, SEVERE, OFF
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* The name of the Level without localizing it, for example
|
||||
* "WARNING".
|
||||
*/
|
||||
private String name;
|
||||
|
||||
|
||||
/**
|
||||
* The integer value of this <code>Level</code>.
|
||||
*/
|
||||
private int value;
|
||||
|
||||
|
||||
/**
|
||||
* The name of the resource bundle used for localizing the level
|
||||
* name, or <code>null</code> if the name does not undergo
|
||||
* localization.
|
||||
*/
|
||||
private String resourceBundleName;
|
||||
|
||||
|
||||
/**
|
||||
* Creates a logging level given a name and an integer value.
|
||||
* It rarely is necessary to create custom levels,
|
||||
* as most applications should be well served with one of the
|
||||
* standard levels such as <code>Level.CONFIG</code>,
|
||||
* <code>Level.INFO</code>, or <code>Level.FINE</code>.
|
||||
*
|
||||
* @param name the name of the level.
|
||||
*
|
||||
* @param value the integer value of the level. Please note
|
||||
* that the Java<small><sup>TM</sup></small>
|
||||
* Logging API does not specify integer
|
||||
* values for standard levels (such as
|
||||
* Level.FINE). Therefore, a custom
|
||||
* level should pass an integer value that
|
||||
* is calculated at run-time, e.g.
|
||||
* <code>(Level.FINE.intValue() + Level.CONFIG.intValue())
|
||||
* / 2</code> for a level between FINE and CONFIG.
|
||||
*/
|
||||
protected Level(String name, int value)
|
||||
{
|
||||
this(name, value, null);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Create a logging level given a name, an integer value and a name
|
||||
* of a resource bundle for localizing the level name. It rarely
|
||||
* is necessary to create custom levels, as most applications
|
||||
* should be well served with one of the standard levels such as
|
||||
* <code>Level.CONFIG</code>, <code>Level.INFO</code>, or
|
||||
* <code>Level.FINE</code>.
|
||||
*
|
||||
* @param name the name of the level.
|
||||
*
|
||||
* @param value the integer value of the level. Please note
|
||||
* that the Java<small><sup>TM</sup></small>
|
||||
* Logging API does not specify integer
|
||||
* values for standard levels (such as
|
||||
* Level.FINE). Therefore, a custom
|
||||
* level should pass an integer value that
|
||||
* is calculated at run-time, e.g.
|
||||
* <code>(Level.FINE.intValue() + Level.CONFIG.intValue())
|
||||
* / 2</code> for a level between FINE and CONFIG.
|
||||
*
|
||||
* @param resourceBundleName the name of a resource bundle
|
||||
* for localizing the level name, or <code>null</code>
|
||||
* if the name does not need to be localized.
|
||||
*/
|
||||
protected Level(String name, int value, String resourceBundleName)
|
||||
{
|
||||
this.name = name;
|
||||
this.value = value;
|
||||
this.resourceBundleName = resourceBundleName;
|
||||
}
|
||||
|
||||
|
||||
static final long serialVersionUID = -8176160795706313070L;
|
||||
|
||||
|
||||
/**
|
||||
* Checks whether the Level has the same intValue as one of the
|
||||
* pre-defined levels. If so, the pre-defined level object is
|
||||
* returned.
|
||||
*
|
||||
* <br/>Since the resource bundle name is not taken into
|
||||
* consideration, it is possible to resolve Level objects that have
|
||||
* been de-serialized by another implementation, even if the other
|
||||
* implementation uses a different resource bundle for localizing
|
||||
* the names of pre-defined levels.
|
||||
*/
|
||||
private Object readResolve()
|
||||
{
|
||||
for (int i = 0; i < knownLevels.length; i++)
|
||||
if (value == knownLevels[i].intValue())
|
||||
return knownLevels[i];
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the name of the resource bundle used for localizing the
|
||||
* level name.
|
||||
*
|
||||
* @return the name of the resource bundle used for localizing the
|
||||
* level name, or <code>null</code> if the name does not undergo
|
||||
* localization.
|
||||
*/
|
||||
public String getResourceBundleName()
|
||||
{
|
||||
return resourceBundleName;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the name of the Level without localizing it, for example
|
||||
* "WARNING".
|
||||
*/
|
||||
public String getName()
|
||||
{
|
||||
return name;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the name of the Level after localizing it, for example
|
||||
* "WARNUNG".
|
||||
*/
|
||||
public String getLocalizedName()
|
||||
{
|
||||
String localizedName = null;
|
||||
|
||||
if (resourceBundleName != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
ResourceBundle b = ResourceBundle.getBundle(resourceBundleName);
|
||||
localizedName = b.getString(name);
|
||||
}
|
||||
catch (Exception _)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
if (localizedName != null)
|
||||
return localizedName;
|
||||
else
|
||||
return name;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the name of the Level without localizing it, for example
|
||||
* "WARNING".
|
||||
*/
|
||||
public final String toString()
|
||||
{
|
||||
return getName();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the integer value of the Level.
|
||||
*/
|
||||
public final int intValue()
|
||||
{
|
||||
return value;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns one of the standard Levels given either its name or its
|
||||
* integer value. Custom subclasses of Level will not be returned
|
||||
* by this method.
|
||||
*
|
||||
* @throws IllegalArgumentException if <code>name</code> is neither
|
||||
* the name nor the integer value of one of the pre-defined standard
|
||||
* logging levels.
|
||||
*
|
||||
* @throws NullPointerException if <code>name</code> is null.
|
||||
*
|
||||
*/
|
||||
public static Level parse(String name)
|
||||
throws IllegalArgumentException
|
||||
{
|
||||
/* This will throw a NullPointerException if name is null,
|
||||
* as required by the API specification.
|
||||
*/
|
||||
name = name.intern();
|
||||
|
||||
for (int i = 0; i < knownLevels.length; i++)
|
||||
{
|
||||
if (name == knownLevels[i].name)
|
||||
return knownLevels[i];
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
int num = Integer.parseInt(name);
|
||||
for (int i = 0; i < knownLevels.length; i++)
|
||||
if (num == knownLevels[i].value)
|
||||
return knownLevels[i];
|
||||
}
|
||||
catch (NumberFormatException _)
|
||||
{
|
||||
}
|
||||
|
||||
String msg = "Not the name of a standard logging level: \"" + name + "\"";
|
||||
throw new IllegalArgumentException(msg);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Checks whether this Level's integer value is equal to that of
|
||||
* another object.
|
||||
*
|
||||
* @return <code>true</code> if <code>other</code> is an instance of
|
||||
* <code>java.util.logging.Level</code> and has the same integer
|
||||
* value, <code>false</code> otherwise.
|
||||
*/
|
||||
public boolean equals(Object other)
|
||||
{
|
||||
if (!(other instanceof Level))
|
||||
return false;
|
||||
|
||||
return value == ((Level) other).value;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns a hash code for this Level which is based on its numeric
|
||||
* value.
|
||||
*/
|
||||
public int hashCode()
|
||||
{
|
||||
return value;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Determines whether or not this Level is one of the standard
|
||||
* levels specified in the Logging API.
|
||||
*
|
||||
* <p>This method is package-private because it is not part
|
||||
* of the logging API specification. However, an XMLFormatter
|
||||
* is supposed to emit the numeric value for a custom log
|
||||
* level, but the name for a pre-defined level. It seems
|
||||
* cleaner to put this method to Level than to write some
|
||||
* procedural code for XMLFormatter.
|
||||
*
|
||||
* @return <code>true</code> if this Level is a standard level,
|
||||
* <code>false</code> otherwise.
|
||||
*/
|
||||
final boolean isStandardLevel()
|
||||
{
|
||||
for (int i = 0; i < knownLevels.length; i++)
|
||||
if (knownLevels[i] == this)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
821
libjava/java/util/logging/LogManager.java
Normal file
821
libjava/java/util/logging/LogManager.java
Normal file
@ -0,0 +1,821 @@
|
||||
/* LogManager.java
|
||||
-- a class for maintaining Loggers and managing configuration
|
||||
properties
|
||||
|
||||
Copyright (C) 2002 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Classpath.
|
||||
|
||||
GNU Classpath is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
GNU Classpath is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GNU Classpath; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
02111-1307 USA.
|
||||
|
||||
Linking this library statically or dynamically with other modules is
|
||||
making a combined work based on this library. Thus, the terms and
|
||||
conditions of the GNU General Public License cover the whole
|
||||
combination.
|
||||
|
||||
As a special exception, the copyright holders of this library give you
|
||||
permission to link this library with independent modules to produce an
|
||||
executable, regardless of the license terms of these independent
|
||||
modules, and to copy and distribute the resulting executable under
|
||||
terms of your choice, provided that you also meet, for each linked
|
||||
independent module, the terms and conditions of the license of that
|
||||
module. An independent module is a module which is not derived from
|
||||
or based on this library. If you modify this library, you may extend
|
||||
this exception to your version of the library, but you are not
|
||||
obligated to do so. If you do not wish to do so, delete this
|
||||
exception statement from your version.
|
||||
|
||||
*/
|
||||
|
||||
package java.util.logging;
|
||||
|
||||
import java.beans.PropertyChangeListener;
|
||||
import java.beans.PropertyChangeSupport;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.net.URL;
|
||||
import java.util.Collections;
|
||||
import java.util.Properties;
|
||||
import java.util.Enumeration;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import java.lang.ref.WeakReference;
|
||||
|
||||
/**
|
||||
* The <code>LogManager</code> maintains a hierarchical namespace
|
||||
* of Logger objects and manages properties for configuring the logging
|
||||
* framework. There exists only one single <code>LogManager</code>
|
||||
* per virtual machine. This instance can be retrieved using the
|
||||
* static method {@link #getLogManager()}.
|
||||
*
|
||||
* <p><strong>Configuration Process:</strong> The global LogManager
|
||||
* object is created and configured when the class
|
||||
* <code>java.util.logging.LogManager</code> is initialized.
|
||||
* The configuration process includes the subsequent steps:
|
||||
*
|
||||
* <ol>
|
||||
* <li>If the system property <code>java.util.logging.manager</code>
|
||||
* is set to the name of a subclass of
|
||||
* <code>java.util.logging.LogManager</code>, an instance of
|
||||
* that subclass is created and becomes the global LogManager.
|
||||
* Otherwise, a new instance of LogManager is created.</li>
|
||||
*
|
||||
* <li>The <code>LogManager</code> constructor tries to create
|
||||
* a new instance of the class specified by the system
|
||||
* property <code>java.util.logging.config.class</code>.
|
||||
* Typically, the constructor of this class will call
|
||||
* <code>LogManager.getLogManager().readConfiguration(java.io.InputStream)</code>
|
||||
* for configuring the logging framework.
|
||||
* The configuration process stops at this point if
|
||||
* the system property <code>java.util.logging.config.class</code>
|
||||
* is set (irrespective of whether the class constructor
|
||||
* could be called or an exception was thrown).</li>
|
||||
*
|
||||
* <li>If the system property <code>java.util.logging.config.class</code>
|
||||
* is <em>not</em> set, the configuration parameters are read in from
|
||||
* a file and passed to
|
||||
* {@link #readConfiguration(java.io.InputStream)}.
|
||||
* The name and location of this file are specified by the system
|
||||
* property <code>java.util.logging.config.file</code>.</li>
|
||||
*
|
||||
* <li>If the system property <code>java.util.logging.config.file</code>
|
||||
* is not set, however, the contents of the URL
|
||||
* "{gnu.classpath.home.url}/logging.properties" are passed to
|
||||
* {@link #readConfiguration(java.io.InputStream)}.
|
||||
* Here, "{gnu.classpath.home.url}" stands for the value of
|
||||
* the system property <code>gnu.classpath.home.url</code>.</li>
|
||||
* </ol>
|
||||
*
|
||||
* @author Sascha Brawer (brawer@acm.org)
|
||||
*/
|
||||
public class LogManager
|
||||
{
|
||||
/**
|
||||
* The singleton LogManager instance.
|
||||
*/
|
||||
private static LogManager logManager;
|
||||
|
||||
|
||||
/**
|
||||
* The registered named loggers; maps the name of a Logger to
|
||||
* a WeakReference to it.
|
||||
*/
|
||||
private Map loggers;
|
||||
|
||||
final Logger rootLogger;
|
||||
|
||||
|
||||
/**
|
||||
* The properties for the logging framework which have been
|
||||
* read in last.
|
||||
*/
|
||||
private Properties properties;
|
||||
|
||||
/**
|
||||
* A delegate object that provides support for handling
|
||||
* PropertyChangeEvents. The API specification does not
|
||||
* mention which bean should be the source in the distributed
|
||||
* PropertyChangeEvents, but Mauve test code has determined that
|
||||
* the Sun J2SE 1.4 reference implementation uses the LogManager
|
||||
* class object. This is somewhat strange, as the class object
|
||||
* is not the bean with which listeners have to register, but
|
||||
* there is no reason for the GNU Classpath implementation to
|
||||
* behave differently from the reference implementation in
|
||||
* this case.
|
||||
*/
|
||||
private final PropertyChangeSupport pcs
|
||||
= new PropertyChangeSupport(/* source bean */ LogManager.class);
|
||||
|
||||
protected LogManager()
|
||||
{
|
||||
if (logManager != null)
|
||||
throw new IllegalStateException(
|
||||
"there can be only one LogManager; use LogManager.getLogManager()");
|
||||
|
||||
logManager = this;
|
||||
loggers = new java.util.HashMap();
|
||||
rootLogger = new Logger("", null);
|
||||
addLogger(rootLogger);
|
||||
|
||||
/* Make sure that Logger.global has the rootLogger as its parent.
|
||||
*
|
||||
* Logger.global is set during class initialization of Logger,
|
||||
* which may or may not be before this code is being executed.
|
||||
* For example, on the Sun 1.3.1 and 1.4.0 JVMs, Logger.global
|
||||
* has been set before this code is being executed. In contrast,
|
||||
* Logger.global still is null on GCJ 3.2. Since the LogManager
|
||||
* and Logger classes are mutually dependent, both behaviors are
|
||||
* correct.
|
||||
*
|
||||
* This means that we cannot depend on Logger.global to have its
|
||||
* value when this code executes, although that variable is final.
|
||||
* Since Logger.getLogger will always return the same logger for
|
||||
* the same name, the subsequent line works fine irrespective of
|
||||
* the order in which classes are initialized.
|
||||
*/
|
||||
Logger.getLogger("global").setParent(rootLogger);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the globally shared LogManager instance.
|
||||
*/
|
||||
public static LogManager getLogManager()
|
||||
{
|
||||
return logManager;
|
||||
}
|
||||
|
||||
static
|
||||
{
|
||||
makeLogManager();
|
||||
|
||||
/* The Javadoc description of the class explains
|
||||
* what is going on here.
|
||||
*/
|
||||
Object configurator = createInstance(
|
||||
System.getProperty("java.util.logging.config.class"),
|
||||
/* must be instance of */ Object.class);
|
||||
|
||||
try
|
||||
{
|
||||
if (configurator == null)
|
||||
getLogManager().readConfiguration();
|
||||
}
|
||||
catch (IOException ex)
|
||||
{
|
||||
/* FIXME: Is it ok to ignore exceptions here? */
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
private static LogManager makeLogManager()
|
||||
{
|
||||
String managerClassName;
|
||||
LogManager manager;
|
||||
|
||||
managerClassName = System.getProperty("java.util.logging.manager");
|
||||
manager = (LogManager) createInstance(managerClassName, LogManager.class);
|
||||
if (manager != null)
|
||||
return manager;
|
||||
|
||||
if (managerClassName != null)
|
||||
System.err.println("WARNING: System property \"java.util.logging.manager\""
|
||||
+ " should be the name of a subclass of java.util.logging.LogManager");
|
||||
|
||||
return new LogManager();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Registers a listener which will be notified when the
|
||||
* logging properties are re-read.
|
||||
*/
|
||||
public synchronized void addPropertyChangeListener(PropertyChangeListener listener)
|
||||
{
|
||||
/* do not register null. */
|
||||
listener.getClass();
|
||||
|
||||
pcs.addPropertyChangeListener(listener);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Unregisters a listener.
|
||||
*
|
||||
* If <code>listener</code> has not been registered previously,
|
||||
* nothing happens. Also, no exception is thrown if
|
||||
* <code>listener</code> is <code>null</code>.
|
||||
*/
|
||||
public synchronized void removePropertyChangeListener(PropertyChangeListener listener)
|
||||
{
|
||||
if (listener != null)
|
||||
pcs.removePropertyChangeListener(listener);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Adds a named logger. If a logger with the same name has
|
||||
* already been registered, the method returns <code>false</code>
|
||||
* without adding the logger.
|
||||
*
|
||||
* <p>The <code>LogManager</code> only keeps weak references
|
||||
* to registered loggers. Therefore, names can become available
|
||||
* after automatic garbage collection.
|
||||
*
|
||||
* @param logger the logger to be added.
|
||||
*
|
||||
* @return <code>true<code>if <code>logger</code> was added,
|
||||
* <code>false</code> otherwise.
|
||||
*
|
||||
* @throws NullPointerException if <code>name<code> is
|
||||
* <code>null</code>.
|
||||
*/
|
||||
public synchronized boolean addLogger(Logger logger)
|
||||
{
|
||||
/* To developers thinking about to remove the 'synchronized'
|
||||
* declaration from this method: Please read the comment
|
||||
* in java.util.logging.Logger.getLogger(String, String)
|
||||
* and make sure that whatever you change wrt. synchronization
|
||||
* does not endanger thread-safety of Logger.getLogger.
|
||||
* The current implementation of Logger.getLogger assumes
|
||||
* that LogManager does its synchronization on the globally
|
||||
* shared instance of LogManager.
|
||||
*/
|
||||
|
||||
String name;
|
||||
WeakReference ref;
|
||||
|
||||
/* This will throw a NullPointerException if logger is null,
|
||||
* as required by the API specification.
|
||||
*/
|
||||
name = logger.getName();
|
||||
|
||||
ref = (WeakReference) loggers.get(name);
|
||||
if (ref != null)
|
||||
{
|
||||
if (ref.get() != null)
|
||||
return false;
|
||||
|
||||
/* There has been a logger under this name in the past,
|
||||
* but it has been garbage collected.
|
||||
*/
|
||||
loggers.remove(ref);
|
||||
}
|
||||
|
||||
/* Adding a named logger requires a security permission. */
|
||||
if ((name != null) && !name.equals(""))
|
||||
checkAccess();
|
||||
|
||||
Logger parent = findAncestor(logger);
|
||||
loggers.put(name, new WeakReference(logger));
|
||||
if (parent != logger.getParent())
|
||||
logger.setParent(parent);
|
||||
|
||||
/* It can happen that existing loggers should be children of
|
||||
* the newly added logger. For example, assume that there
|
||||
* already exist loggers under the names "", "foo", and "foo.bar.baz".
|
||||
* When adding "foo.bar", the logger "foo.bar.baz" should change
|
||||
* its parent to "foo.bar".
|
||||
*/
|
||||
if (parent != rootLogger)
|
||||
{
|
||||
for (Iterator iter = loggers.keySet().iterator(); iter.hasNext();)
|
||||
{
|
||||
Logger possChild = (Logger) ((WeakReference) loggers.get(iter.next())).get();
|
||||
if ((possChild == null) || (possChild == logger) || (possChild.getParent() != parent))
|
||||
continue;
|
||||
|
||||
if (!possChild.getName().startsWith(name))
|
||||
continue;
|
||||
|
||||
if (possChild.getName().charAt(name.length()) != '.')
|
||||
continue;
|
||||
|
||||
possChild.setParent(logger);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Finds the closest ancestor for a logger among the currently
|
||||
* registered ones. For example, if the currently registered
|
||||
* loggers have the names "", "foo", and "foo.bar", the result for
|
||||
* "foo.bar.baz" will be the logger whose name is "foo.bar".
|
||||
*
|
||||
* @param child a logger for whose name no logger has been
|
||||
* registered.
|
||||
*
|
||||
* @return the closest ancestor for <code>child</code>,
|
||||
* or <code>null</code> if <code>child</code>
|
||||
* is the root logger.
|
||||
*
|
||||
* @throws NullPointerException if <code>child</code>
|
||||
* is <code>null</code>.
|
||||
*/
|
||||
private synchronized Logger findAncestor(Logger child)
|
||||
{
|
||||
String childName = child.getName();
|
||||
Logger best = rootLogger;
|
||||
int bestNameLength = 0;
|
||||
|
||||
Logger cand;
|
||||
String candName;
|
||||
int candNameLength;
|
||||
|
||||
if (child == rootLogger)
|
||||
return null;
|
||||
|
||||
for (Iterator iter = loggers.keySet().iterator(); iter.hasNext();)
|
||||
{
|
||||
candName = (String) iter.next();
|
||||
candNameLength = candName.length();
|
||||
|
||||
if ((candNameLength > bestNameLength)
|
||||
&& childName.startsWith(candName)
|
||||
&& (childName.charAt(candNameLength) == '.'))
|
||||
{
|
||||
cand = (Logger) ((WeakReference) loggers.get(candName)).get();
|
||||
if ((cand == null) || (cand == child))
|
||||
continue;
|
||||
|
||||
bestNameLength = candName.length();
|
||||
best = cand;
|
||||
}
|
||||
}
|
||||
|
||||
return best;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns a Logger given its name.
|
||||
*
|
||||
* @param name the name of the logger.
|
||||
*
|
||||
* @return a named Logger, or <code>null</code> if there is no
|
||||
* logger with that name.
|
||||
*
|
||||
* @throw java.lang.NullPointerException if <code>name</code>
|
||||
* is <code>null</code>.
|
||||
*/
|
||||
public synchronized Logger getLogger(String name)
|
||||
{
|
||||
WeakReference ref;
|
||||
|
||||
/* Throw a NullPointerException if name is null. */
|
||||
name.getClass();
|
||||
|
||||
ref = (WeakReference) loggers.get(name);
|
||||
if (ref != null)
|
||||
return (Logger) ref.get();
|
||||
else
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns an Enumeration of currently registered Logger names.
|
||||
* Since other threads can register loggers at any time, the
|
||||
* result could be different any time this method is called.
|
||||
*
|
||||
* @return an Enumeration with the names of the currently
|
||||
* registered Loggers.
|
||||
*/
|
||||
public synchronized Enumeration getLoggerNames()
|
||||
{
|
||||
return Collections.enumeration(loggers.keySet());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Resets the logging configuration by removing all handlers for
|
||||
* registered named loggers and setting their level to <code>null</code>.
|
||||
* The level of the root logger will be set to <code>Level.INFO</code>.
|
||||
*
|
||||
* @throws SecurityException if a security manager exists and
|
||||
* the caller is not granted the permission to control
|
||||
* the logging infrastructure.
|
||||
*/
|
||||
public synchronized void reset()
|
||||
throws SecurityException
|
||||
{
|
||||
/* Throw a SecurityException if the caller does not have the
|
||||
* permission to control the logging infrastructure.
|
||||
*/
|
||||
checkAccess();
|
||||
|
||||
properties = new Properties();
|
||||
|
||||
Iterator iter = loggers.values().iterator();
|
||||
while (iter.hasNext())
|
||||
{
|
||||
WeakReference ref;
|
||||
Logger logger;
|
||||
|
||||
ref = (WeakReference) iter.next();
|
||||
if (ref != null)
|
||||
{
|
||||
logger = (Logger) ref.get();
|
||||
|
||||
if (logger == null)
|
||||
iter.remove();
|
||||
else if (logger != rootLogger)
|
||||
logger.setLevel(null);
|
||||
}
|
||||
}
|
||||
|
||||
rootLogger.setLevel(Level.INFO);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Configures the logging framework by reading a configuration file.
|
||||
* The name and location of this file are specified by the system
|
||||
* property <code>java.util.logging.config.file</code>. If this
|
||||
* property is not set, the URL
|
||||
* "{gnu.classpath.home.url}/logging.properties" is taken, where
|
||||
* "{gnu.classpath.home.url}" stands for the value of the system
|
||||
* property <code>gnu.classpath.home.url</code>.
|
||||
*
|
||||
* <p>The task of configuring the framework is then delegated to
|
||||
* {@link #readConfiguration(java.io.InputStream)}, which will
|
||||
* notify registered listeners after having read the properties.
|
||||
*
|
||||
* @throws SecurityException if a security manager exists and
|
||||
* the caller is not granted the permission to control
|
||||
* the logging infrastructure, or if the caller is
|
||||
* not granted the permission to read the configuration
|
||||
* file.
|
||||
*
|
||||
* @throws IOException if there is a problem reading in the
|
||||
* configuration file.
|
||||
*/
|
||||
public synchronized void readConfiguration()
|
||||
throws IOException, SecurityException
|
||||
{
|
||||
String path;
|
||||
InputStream inputStream;
|
||||
|
||||
path = System.getProperty("java.util.logging.config.file");
|
||||
if ((path == null) || (path.length() == 0))
|
||||
{
|
||||
String url = (System.getProperty("gnu.classpath.home.url")
|
||||
+ "/logging.properties");
|
||||
inputStream = new URL(url).openStream();
|
||||
}
|
||||
else
|
||||
{
|
||||
inputStream = new java.io.FileInputStream(path);
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
readConfiguration(inputStream);
|
||||
}
|
||||
finally
|
||||
{
|
||||
/* Close the stream in order to save
|
||||
* resources such as file descriptors.
|
||||
*/
|
||||
inputStream.close();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public synchronized void readConfiguration(InputStream inputStream)
|
||||
throws IOException, SecurityException
|
||||
{
|
||||
Properties newProperties;
|
||||
Enumeration keys;
|
||||
|
||||
checkAccess();
|
||||
newProperties = new Properties();
|
||||
newProperties.load(inputStream);
|
||||
this.properties = newProperties;
|
||||
keys = newProperties.propertyNames();
|
||||
|
||||
while (keys.hasMoreElements())
|
||||
{
|
||||
String key = (String) keys.nextElement();
|
||||
String value = newProperties.getProperty(key);
|
||||
|
||||
if (value == null)
|
||||
continue;
|
||||
|
||||
if (key.endsWith(".level"))
|
||||
{
|
||||
String loggerName = key.substring(0, key.length() - 6);
|
||||
Logger logger = getLogger(loggerName);
|
||||
if (logger != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
logger.setLevel(Level.parse(value));
|
||||
}
|
||||
catch (Exception _)
|
||||
{
|
||||
}
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* The API specification does not talk about the
|
||||
* property name that is distributed with the
|
||||
* PropertyChangeEvent. With test code, it could
|
||||
* be determined that the Sun J2SE 1.4 reference
|
||||
* implementation uses null for the property name.
|
||||
*/
|
||||
pcs.firePropertyChange(null, null, null);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the value of a configuration property as a String.
|
||||
*/
|
||||
public synchronized String getProperty(String name)
|
||||
{
|
||||
if (properties != null)
|
||||
return properties.getProperty(name);
|
||||
else
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the value of a configuration property as an integer.
|
||||
* This function is a helper used by the Classpath implementation
|
||||
* of java.util.logging, it is <em>not</em> specified in the
|
||||
* logging API.
|
||||
*
|
||||
* @param name the name of the configuration property.
|
||||
*
|
||||
* @param defaultValue the value that will be returned if the
|
||||
* property is not defined, or if its value is not an integer
|
||||
* number.
|
||||
*/
|
||||
static int getIntProperty(String name, int defaultValue)
|
||||
{
|
||||
try
|
||||
{
|
||||
return Integer.parseInt(getLogManager().getProperty(name));
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return defaultValue;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the value of a configuration property as an integer,
|
||||
* provided it is inside the acceptable range.
|
||||
* This function is a helper used by the Classpath implementation
|
||||
* of java.util.logging, it is <em>not</em> specified in the
|
||||
* logging API.
|
||||
*
|
||||
* @param name the name of the configuration property.
|
||||
*
|
||||
* @param minValue the lowest acceptable value.
|
||||
*
|
||||
* @param maxValue the highest acceptable value.
|
||||
*
|
||||
* @param defaultValue the value that will be returned if the
|
||||
* property is not defined, or if its value is not an integer
|
||||
* number, or if it is less than the minimum value,
|
||||
* or if it is greater than the maximum value.
|
||||
*/
|
||||
static int getIntPropertyClamped(String name, int defaultValue,
|
||||
int minValue, int maxValue)
|
||||
{
|
||||
int val = getIntProperty(name, defaultValue);
|
||||
if ((val < minValue) || (val > maxValue))
|
||||
val = defaultValue;
|
||||
return val;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the value of a configuration property as a boolean.
|
||||
* This function is a helper used by the Classpath implementation
|
||||
* of java.util.logging, it is <em>not</em> specified in the
|
||||
* logging API.
|
||||
*
|
||||
* @param name the name of the configuration property.
|
||||
*
|
||||
* @param defaultValue the value that will be returned if the
|
||||
* property is not defined, or if its value is neither
|
||||
* <code>"true"</code> nor <code>"false"</code>.
|
||||
*/
|
||||
static boolean getBooleanProperty(String name, boolean defaultValue)
|
||||
{
|
||||
try
|
||||
{
|
||||
return (new Boolean(getLogManager().getProperty(name)))
|
||||
.booleanValue();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return defaultValue;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the value of a configuration property as a Level.
|
||||
* This function is a helper used by the Classpath implementation
|
||||
* of java.util.logging, it is <em>not</em> specified in the
|
||||
* logging API.
|
||||
*
|
||||
* @param propertyName the name of the configuration property.
|
||||
*
|
||||
* @param defaultValue the value that will be returned if the
|
||||
* property is not defined, or if
|
||||
* {@link Level.parse(java.lang.String)} does not like
|
||||
* the property value.
|
||||
*/
|
||||
static Level getLevelProperty(String propertyName, Level defaultValue)
|
||||
{
|
||||
try
|
||||
{
|
||||
return Level.parse(getLogManager().getProperty(propertyName));
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return defaultValue;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the value of a configuration property as a Class.
|
||||
* This function is a helper used by the Classpath implementation
|
||||
* of java.util.logging, it is <em>not</em> specified in the
|
||||
* logging API.
|
||||
*
|
||||
* @param propertyName the name of the configuration property.
|
||||
*
|
||||
* @param defaultValue the value that will be returned if the
|
||||
* property is not defined, or if it does not specify
|
||||
* the name of a loadable class.
|
||||
*/
|
||||
static final Class getClassProperty(String propertyName, Class defaultValue)
|
||||
{
|
||||
Class usingClass = null;
|
||||
|
||||
try
|
||||
{
|
||||
String propertyValue = logManager.getProperty(propertyName);
|
||||
if (propertyValue != null)
|
||||
usingClass = Class.forName(propertyValue);
|
||||
if (usingClass != null)
|
||||
return usingClass;
|
||||
}
|
||||
catch (Exception _)
|
||||
{
|
||||
}
|
||||
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
|
||||
static final Object getInstanceProperty(String propertyName,
|
||||
Class ofClass,
|
||||
Class defaultClass)
|
||||
{
|
||||
Class klass = getClassProperty(propertyName, defaultClass);
|
||||
if (klass == null)
|
||||
return null;
|
||||
|
||||
try
|
||||
{
|
||||
Object obj = klass.newInstance();
|
||||
if (ofClass.isInstance(obj))
|
||||
return obj;
|
||||
}
|
||||
catch (Exception _)
|
||||
{
|
||||
}
|
||||
|
||||
if (defaultClass == null)
|
||||
return null;
|
||||
|
||||
try
|
||||
{
|
||||
return defaultClass.newInstance();
|
||||
}
|
||||
catch (java.lang.InstantiationException ex)
|
||||
{
|
||||
throw new RuntimeException(ex.getMessage());
|
||||
}
|
||||
catch (java.lang.IllegalAccessException ex)
|
||||
{
|
||||
throw new RuntimeException(ex.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* An instance of <code>LoggingPermission("control")</code>
|
||||
* that is shared between calls to <code>checkAccess()</code>.
|
||||
*/
|
||||
private static final LoggingPermission controlPermission
|
||||
= new LoggingPermission("control", null);
|
||||
|
||||
|
||||
/**
|
||||
* Checks whether the current security context allows changing
|
||||
* the configuration of the logging framework. For the security
|
||||
* context to be trusted, it has to be granted
|
||||
* a LoggingPermission("control").
|
||||
*
|
||||
* @throws SecurityException if a security manager exists and
|
||||
* the caller is not granted the permission to control
|
||||
* the logging infrastructure.
|
||||
*/
|
||||
public void checkAccess()
|
||||
throws SecurityException
|
||||
{
|
||||
SecurityManager sm = System.getSecurityManager();
|
||||
if (sm != null)
|
||||
sm.checkPermission(controlPermission);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Creates a new instance of a class specified by name.
|
||||
*
|
||||
* @param className the name of the class of which a new instance
|
||||
* should be created.
|
||||
*
|
||||
* @param ofClass the class to which the new instance should
|
||||
* be either an instance or an instance of a subclass.
|
||||
* FIXME: This description is just terrible.
|
||||
*
|
||||
* @return the new instance, or <code>null</code> if
|
||||
* <code>className</code> is <code>null</code>, if no class
|
||||
* with that name could be found, if there was an error
|
||||
* loading that class, or if the constructor of the class
|
||||
* has thrown an exception.
|
||||
*/
|
||||
static final Object createInstance(String className, Class ofClass)
|
||||
{
|
||||
Class klass;
|
||||
|
||||
if ((className == null) || (className.length() == 0))
|
||||
return null;
|
||||
|
||||
try
|
||||
{
|
||||
klass = Class.forName(className);
|
||||
if (!ofClass.isAssignableFrom(klass))
|
||||
return null;
|
||||
|
||||
return klass.newInstance();
|
||||
}
|
||||
catch (Exception _)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
catch (java.lang.LinkageError _)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
675
libjava/java/util/logging/LogRecord.java
Normal file
675
libjava/java/util/logging/LogRecord.java
Normal file
@ -0,0 +1,675 @@
|
||||
/* LogRecord.java
|
||||
-- a class for the state associated with individual logging events
|
||||
|
||||
Copyright (C) 2002, 2003 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Classpath.
|
||||
|
||||
GNU Classpath is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
GNU Classpath is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GNU Classpath; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
02111-1307 USA.
|
||||
|
||||
Linking this library statically or dynamically with other modules is
|
||||
making a combined work based on this library. Thus, the terms and
|
||||
conditions of the GNU General Public License cover the whole
|
||||
combination.
|
||||
|
||||
As a special exception, the copyright holders of this library give you
|
||||
permission to link this library with independent modules to produce an
|
||||
executable, regardless of the license terms of these independent
|
||||
modules, and to copy and distribute the resulting executable under
|
||||
terms of your choice, provided that you also meet, for each linked
|
||||
independent module, the terms and conditions of the license of that
|
||||
module. An independent module is a module which is not derived from
|
||||
or based on this library. If you modify this library, you may extend
|
||||
this exception to your version of the library, but you are not
|
||||
obligated to do so. If you do not wish to do so, delete this
|
||||
exception statement from your version.
|
||||
|
||||
*/
|
||||
|
||||
|
||||
package java.util.logging;
|
||||
|
||||
import java.util.ResourceBundle;
|
||||
|
||||
|
||||
/**
|
||||
* A <code>LogRecord</code> contains the state for an individual
|
||||
* event to be logged.
|
||||
*
|
||||
* <p>As soon as a LogRecord instance has been handed over to the
|
||||
* logging framework, applications should not manipulate it anymore.
|
||||
*
|
||||
* @author Sascha Brawer (brawer@acm.org)
|
||||
*/
|
||||
public class LogRecord
|
||||
implements java.io.Serializable
|
||||
{
|
||||
/**
|
||||
* The severity level of this <code>LogRecord</code>.
|
||||
*/
|
||||
private Level level;
|
||||
|
||||
|
||||
/**
|
||||
* The sequence number of this <code>LogRecord</code>.
|
||||
*/
|
||||
private long sequenceNumber;
|
||||
|
||||
|
||||
/**
|
||||
* The name of the class that issued the logging request, or
|
||||
* <code>null</code> if this information could not be obtained.
|
||||
*/
|
||||
private String sourceClassName;
|
||||
|
||||
|
||||
/**
|
||||
* The name of the method that issued the logging request, or
|
||||
* <code>null</code> if this information could not be obtained.
|
||||
*/
|
||||
private String sourceMethodName;
|
||||
|
||||
|
||||
/**
|
||||
* The message for this <code>LogRecord</code> before
|
||||
* any localization or formatting.
|
||||
*/
|
||||
private String message;
|
||||
|
||||
|
||||
/**
|
||||
* An identifier for the thread in which this <code>LogRecord</code>
|
||||
* was created. The identifier is not necessarily related to any
|
||||
* thread identifiers used by the operating system.
|
||||
*/
|
||||
private int threadID;
|
||||
|
||||
|
||||
/**
|
||||
* The time when this <code>LogRecord</code> was created,
|
||||
* in milliseconds since the beginning of January 1, 1970.
|
||||
*/
|
||||
private long millis;
|
||||
|
||||
|
||||
/**
|
||||
* The Throwable associated with this <code>LogRecord</code>, or
|
||||
* <code>null</code> if the logged event is not related to an
|
||||
* exception or error.
|
||||
*/
|
||||
private Throwable thrown;
|
||||
|
||||
|
||||
/**
|
||||
* The name of the logger where this <code>LogRecord</code> has
|
||||
* originated, or <code>null</code> if this <code>LogRecord</code>
|
||||
* does not originate from a <code>Logger</code>.
|
||||
*/
|
||||
private String loggerName;
|
||||
|
||||
|
||||
/**
|
||||
* The name of the resource bundle used for localizing log messages,
|
||||
* or <code>null</code> if no bundle has been specified.
|
||||
*/
|
||||
private String resourceBundleName;
|
||||
|
||||
private transient Object[] parameters;
|
||||
|
||||
private transient ResourceBundle bundle;
|
||||
|
||||
|
||||
/**
|
||||
* Constructs a <code>LogRecord</code> given a severity level and
|
||||
* an unlocalized message text. In addition, the sequence number,
|
||||
* creation time (as returned by <code>getMillis()</code>) and
|
||||
* thread ID are assigned. All other properties are set to
|
||||
* <code>null</code>.
|
||||
*
|
||||
* @param level the severity level, for example <code>Level.WARNING</code>.
|
||||
*
|
||||
* @param message the message text (which will be used as key
|
||||
* for looking up the localized message text
|
||||
* if a resource bundle has been associated).
|
||||
*/
|
||||
public LogRecord(Level level, String message)
|
||||
{
|
||||
this.level = level;
|
||||
this.message = message;
|
||||
this.millis = System.currentTimeMillis();
|
||||
|
||||
/* A subclass of java.lang.Thread could override hashCode(),
|
||||
* in which case the result would not be guaranteed anymore
|
||||
* to be unique among all threads. While System.identityHashCode
|
||||
* is not necessarily unique either, it at least cannot be
|
||||
* overridden by user code. However, is might be a good idea
|
||||
* to use something better for generating thread IDs.
|
||||
*/
|
||||
this.threadID = System.identityHashCode(Thread.currentThread());
|
||||
|
||||
sequenceNumber = allocateSeqNum();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Determined with the serialver tool of the Sun J2SE 1.4.
|
||||
*/
|
||||
static final long serialVersionUID = 5372048053134512534L;
|
||||
|
||||
private void readObject(java.io.ObjectInputStream in)
|
||||
throws java.io.IOException, java.lang.ClassNotFoundException
|
||||
{
|
||||
in.defaultReadObject();
|
||||
|
||||
/* We assume that future versions will be downwards compatible,
|
||||
* so we can ignore the versions.
|
||||
*/
|
||||
byte majorVersion = in.readByte();
|
||||
byte minorVersion = in.readByte();
|
||||
|
||||
int numParams = in.readInt();
|
||||
if (numParams >= 0)
|
||||
{
|
||||
parameters = new Object[numParams];
|
||||
for (int i = 0; i < numParams; i++)
|
||||
parameters[i] = in.readObject();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @serialData The default fields, followed by a major byte version
|
||||
* number, followed by a minor byte version number, followed by
|
||||
* information about the log record parameters. If
|
||||
* <code>parameters</code> is <code>null</code>, the integer -1 is
|
||||
* written, otherwise the length of the <code>parameters</code>
|
||||
* array (which can be zero), followed by the result of calling
|
||||
* {@link Object#toString() toString()} on the parameter (or
|
||||
* <code>null</code> if the parameter is <code>null</code>).
|
||||
*
|
||||
* <p><strong>Specification Note:</strong> The Javadoc for the
|
||||
* Sun reference implementation does not specify the version
|
||||
* number. FIXME: Reverse-engineer the JDK and file a bug
|
||||
* report with Sun, asking for amendment of the specification.
|
||||
*/
|
||||
private void writeObject(java.io.ObjectOutputStream out)
|
||||
throws java.io.IOException
|
||||
{
|
||||
out.defaultWriteObject();
|
||||
|
||||
/* Major, minor version number: The Javadoc for J2SE1.4 does not
|
||||
* specify the values.
|
||||
*/
|
||||
out.writeByte(0);
|
||||
out.writeByte(0);
|
||||
|
||||
if (parameters == null)
|
||||
out.writeInt(-1);
|
||||
else
|
||||
{
|
||||
out.writeInt(parameters.length);
|
||||
for (int i = 0; i < parameters.length; i++)
|
||||
{
|
||||
if (parameters[i] == null)
|
||||
out.writeObject(null);
|
||||
else
|
||||
out.writeObject(parameters[i].toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the name of the logger where this <code>LogRecord</code>
|
||||
* has originated.
|
||||
*
|
||||
* @return the name of the source {@link Logger}, or
|
||||
* <code>null</code> if this <code>LogRecord</code>
|
||||
* does not originate from a <code>Logger</code>.
|
||||
*/
|
||||
public String getLoggerName()
|
||||
{
|
||||
return loggerName;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Sets the name of the logger where this <code>LogRecord</code>
|
||||
* has originated.
|
||||
*
|
||||
* <p>As soon as a <code>LogRecord</code> has been handed over
|
||||
* to the logging framework, applications should not modify it
|
||||
* anymore. Therefore, this method should only be called on
|
||||
* freshly constructed LogRecords.
|
||||
*
|
||||
* @param name the name of the source logger, or <code>null</code> to
|
||||
* indicate that this <code>LogRecord</code> does not
|
||||
* originate from a <code>Logger</code>.
|
||||
*/
|
||||
public void setLoggerName(String name)
|
||||
{
|
||||
loggerName = name;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the resource bundle that is used when the message
|
||||
* of this <code>LogRecord</code> needs to be localized.
|
||||
*
|
||||
* @return the resource bundle used for localization,
|
||||
* or <code>null</code> if this message does not need
|
||||
* to be localized.
|
||||
*/
|
||||
public ResourceBundle getResourceBundle()
|
||||
{
|
||||
return bundle;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Sets the resource bundle that is used when the message
|
||||
* of this <code>LogRecord</code> needs to be localized.
|
||||
*
|
||||
* <p>As soon as a <code>LogRecord</code> has been handed over
|
||||
* to the logging framework, applications should not modify it
|
||||
* anymore. Therefore, this method should only be called on
|
||||
* freshly constructed LogRecords.
|
||||
*
|
||||
* @param bundle the resource bundle to be used, or
|
||||
* <code>null</code> to indicate that this
|
||||
* message does not need to be localized.
|
||||
*/
|
||||
public void setResourceBundle(ResourceBundle bundle)
|
||||
{
|
||||
this.bundle = bundle;
|
||||
|
||||
/* FIXME: Is there a way to infer the name
|
||||
* of a resource bundle from a ResourceBundle object?
|
||||
*/
|
||||
this.resourceBundleName = null;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the name of the resource bundle that is used when the
|
||||
* message of this <code>LogRecord</code> needs to be localized.
|
||||
*
|
||||
* @return the name of the resource bundle used for localization,
|
||||
* or <code>null</code> if this message does not need
|
||||
* to be localized.
|
||||
*/
|
||||
public String getResourceBundleName()
|
||||
{
|
||||
return resourceBundleName;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Sets the name of the resource bundle that is used when the
|
||||
* message of this <code>LogRecord</code> needs to be localized.
|
||||
*
|
||||
* <p>As soon as a <code>LogRecord</code> has been handed over
|
||||
* to the logging framework, applications should not modify it
|
||||
* anymore. Therefore, this method should only be called on
|
||||
* freshly constructed LogRecords.
|
||||
*
|
||||
* @param name the name of the resource bundle to be used, or
|
||||
* <code>null</code> to indicate that this message
|
||||
* does not need to be localized.
|
||||
*/
|
||||
public void setResourceBundleName(String name)
|
||||
{
|
||||
resourceBundleName = name;
|
||||
bundle = null;
|
||||
|
||||
try
|
||||
{
|
||||
if (resourceBundleName != null)
|
||||
bundle = ResourceBundle.getBundle(resourceBundleName);
|
||||
}
|
||||
catch (java.util.MissingResourceException _)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the level of the LogRecord.
|
||||
*
|
||||
* <p>Applications should be aware of the possibility that the
|
||||
* result is not necessarily one of the standard logging levels,
|
||||
* since the logging framework allows to create custom subclasses
|
||||
* of <code>java.util.logging.Level</code>. Therefore, filters
|
||||
* should perform checks like <code>theRecord.getLevel().intValue()
|
||||
* == Level.INFO.intValue()</code> instead of <code>theRecord.getLevel()
|
||||
* == Level.INFO</code>.
|
||||
*/
|
||||
public Level getLevel()
|
||||
{
|
||||
return level;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Sets the severity level of this <code>LogRecord</code> to a new
|
||||
* value.
|
||||
*
|
||||
* <p>As soon as a <code>LogRecord</code> has been handed over
|
||||
* to the logging framework, applications should not modify it
|
||||
* anymore. Therefore, this method should only be called on
|
||||
* freshly constructed LogRecords.
|
||||
*
|
||||
* @param level the new severity level, for example
|
||||
* <code>Level.WARNING</code>.
|
||||
*/
|
||||
public void setLevel(Level level)
|
||||
{
|
||||
this.level = level;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* The last used sequence number for any LogRecord.
|
||||
*/
|
||||
private static long lastSeqNum = 0;
|
||||
|
||||
|
||||
/**
|
||||
* Allocates a sequence number for a new LogRecord. This class
|
||||
* method is only called by the LogRecord constructor.
|
||||
*/
|
||||
private synchronized static long allocateSeqNum()
|
||||
{
|
||||
lastSeqNum += 1;
|
||||
return lastSeqNum;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the sequence number of this <code>LogRecord</code>.
|
||||
*/
|
||||
public long getSequenceNumber()
|
||||
{
|
||||
return sequenceNumber;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Sets the sequence number of this <code>LogRecord</code> to a new
|
||||
* value.
|
||||
*
|
||||
* <p>As soon as a <code>LogRecord</code> has been handed over
|
||||
* to the logging framework, applications should not modify it
|
||||
* anymore. Therefore, this method should only be called on
|
||||
* freshly constructed LogRecords.
|
||||
*
|
||||
* @param seqNum the new sequence number.
|
||||
*/
|
||||
public void setSequenceNumber(long seqNum)
|
||||
{
|
||||
this.sequenceNumber = seqNum;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the name of the class where the event being logged
|
||||
* has had its origin. This information can be passed as
|
||||
* parameter to some logging calls, and in certain cases, the
|
||||
* logging framework tries to determine an approximation
|
||||
* (which may or may not be accurate).
|
||||
*
|
||||
* @return the name of the class that issued the logging request,
|
||||
* or <code>null</code> if this information could not
|
||||
* be obtained.
|
||||
*/
|
||||
public String getSourceClassName()
|
||||
{
|
||||
if (sourceClassName != null)
|
||||
return sourceClassName;
|
||||
|
||||
/* FIXME: Should infer this information from the call stack. */
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Sets the name of the class where the event being logged
|
||||
* has had its origin.
|
||||
*
|
||||
* <p>As soon as a <code>LogRecord</code> has been handed over
|
||||
* to the logging framework, applications should not modify it
|
||||
* anymore. Therefore, this method should only be called on
|
||||
* freshly constructed LogRecords.
|
||||
*
|
||||
* @param sourceClassName the name of the class that issued the
|
||||
* logging request, or <code>null</code> to indicate that
|
||||
* this information could not be obtained.
|
||||
*/
|
||||
public void setSourceClassName(String sourceClassName)
|
||||
{
|
||||
this.sourceClassName = sourceClassName;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the name of the method where the event being logged
|
||||
* has had its origin. This information can be passed as
|
||||
* parameter to some logging calls, and in certain cases, the
|
||||
* logging framework tries to determine an approximation
|
||||
* (which may or may not be accurate).
|
||||
*
|
||||
* @return the name of the method that issued the logging request,
|
||||
* or <code>null</code> if this information could not
|
||||
* be obtained.
|
||||
*/
|
||||
public String getSourceMethodName()
|
||||
{
|
||||
if (sourceMethodName != null)
|
||||
return sourceMethodName;
|
||||
|
||||
/* FIXME: Should infer this information from the call stack. */
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Sets the name of the method where the event being logged
|
||||
* has had its origin.
|
||||
*
|
||||
* <p>As soon as a <code>LogRecord</code> has been handed over
|
||||
* to the logging framework, applications should not modify it
|
||||
* anymore. Therefore, this method should only be called on
|
||||
* freshly constructed LogRecords.
|
||||
*
|
||||
* @param sourceMethodName the name of the method that issued the
|
||||
* logging request, or <code>null</code> to indicate that
|
||||
* this information could not be obtained.
|
||||
*/
|
||||
public void setSourceMethodName(String sourceMethodName)
|
||||
{
|
||||
this.sourceMethodName = sourceMethodName;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the message for this <code>LogRecord</code> before
|
||||
* any localization or parameter substitution.
|
||||
*
|
||||
* <p>A {@link Logger} will try to localize the message
|
||||
* if a resource bundle has been associated with this
|
||||
* <code>LogRecord</code>. In this case, the logger will call
|
||||
* <code>getMessage()</code> and use the result as the key
|
||||
* for looking up the localized message in the bundle.
|
||||
* If no bundle has been associated, or if the result of
|
||||
* <code>getMessage()</code> is not a valid key in the
|
||||
* bundle, the logger will use the raw message text as
|
||||
* returned by this method.
|
||||
*
|
||||
* @return the message text, or <code>null</code> if there
|
||||
* is no message text.
|
||||
*/
|
||||
public String getMessage()
|
||||
{
|
||||
return message;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Sets the message for this <code>LogRecord</code>.
|
||||
*
|
||||
* <p>A <code>Logger</code> will try to localize the message
|
||||
* if a resource bundle has been associated with this
|
||||
* <code>LogRecord</code>. In this case, the logger will call
|
||||
* <code>getMessage()</code> and use the result as the key
|
||||
* for looking up the localized message in the bundle.
|
||||
* If no bundle has been associated, or if the result of
|
||||
* <code>getMessage()</code> is not a valid key in the
|
||||
* bundle, the logger will use the raw message text as
|
||||
* returned by this method.
|
||||
*
|
||||
* <p>It is possible to set the message to either an empty String or
|
||||
* <code>null</code>, although this does not make the the message
|
||||
* very helpful to human users.
|
||||
*
|
||||
* @param message the message text (which will be used as key
|
||||
* for looking up the localized message text
|
||||
* if a resource bundle has been associated).
|
||||
*/
|
||||
public void setMessage(String message)
|
||||
{
|
||||
this.message = message;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the parameters to the log message.
|
||||
*
|
||||
* @return the parameters to the message, or <code>null</code> if
|
||||
* the message has no parameters.
|
||||
*/
|
||||
public Object[] getParameters()
|
||||
{
|
||||
return parameters;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Sets the parameters to the log message.
|
||||
*
|
||||
* <p>As soon as a <code>LogRecord</code> has been handed over
|
||||
* to the logging framework, applications should not modify it
|
||||
* anymore. Therefore, this method should only be called on
|
||||
* freshly constructed LogRecords.
|
||||
*
|
||||
* @param parameters the parameters to the message, or <code>null</code>
|
||||
* to indicate that the message has no parameters.
|
||||
*/
|
||||
public void setParameters(Object[] parameters)
|
||||
{
|
||||
this.parameters = parameters;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns an identifier for the thread in which this
|
||||
* <code>LogRecord</code> was created. The identifier is not
|
||||
* necessarily related to any thread identifiers used by the
|
||||
* operating system.
|
||||
*
|
||||
* @return an identifier for the source thread.
|
||||
*/
|
||||
public int getThreadID()
|
||||
{
|
||||
return threadID;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Sets the identifier indicating in which thread this
|
||||
* <code>LogRecord</code> was created. The identifier is not
|
||||
* necessarily related to any thread identifiers used by the
|
||||
* operating system.
|
||||
*
|
||||
* <p>As soon as a <code>LogRecord</code> has been handed over
|
||||
* to the logging framework, applications should not modify it
|
||||
* anymore. Therefore, this method should only be called on
|
||||
* freshly constructed LogRecords.
|
||||
*
|
||||
* @param threadID the identifier for the source thread.
|
||||
*/
|
||||
public void setThreadID(int threadID)
|
||||
{
|
||||
this.threadID = threadID;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the time when this <code>LogRecord</code> was created.
|
||||
*
|
||||
* @return the time of creation in milliseconds since the beginning
|
||||
* of January 1, 1970.
|
||||
*/
|
||||
public long getMillis()
|
||||
{
|
||||
return millis;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Sets the time when this <code>LogRecord</code> was created.
|
||||
*
|
||||
* <p>As soon as a <code>LogRecord</code> has been handed over
|
||||
* to the logging framework, applications should not modify it
|
||||
* anymore. Therefore, this method should only be called on
|
||||
* freshly constructed LogRecords.
|
||||
*
|
||||
* @param millis the time of creation in milliseconds since the
|
||||
* beginning of January 1, 1970.
|
||||
*/
|
||||
public void setMillis(long millis)
|
||||
{
|
||||
this.millis = millis;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the Throwable associated with this <code>LogRecord</code>,
|
||||
* or <code>null</code> if the logged event is not related to an exception
|
||||
* or error.
|
||||
*/
|
||||
public Throwable getThrown()
|
||||
{
|
||||
return thrown;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Associates this <code>LogRecord</code> with an exception or error.
|
||||
*
|
||||
* <p>As soon as a <code>LogRecord</code> has been handed over
|
||||
* to the logging framework, applications should not modify it
|
||||
* anymore. Therefore, this method should only be called on
|
||||
* freshly constructed LogRecords.
|
||||
*
|
||||
* @param thrown the exception or error to associate with, or
|
||||
* <code>null</code> if this <code>LogRecord</code>
|
||||
* should be made unrelated to an exception or error.
|
||||
*/
|
||||
public void setThrown(Throwable thrown)
|
||||
{
|
||||
this.thrown = thrown;
|
||||
}
|
||||
}
|
1167
libjava/java/util/logging/Logger.java
Normal file
1167
libjava/java/util/logging/Logger.java
Normal file
File diff suppressed because it is too large
Load Diff
75
libjava/java/util/logging/LoggingPermission.java
Normal file
75
libjava/java/util/logging/LoggingPermission.java
Normal file
@ -0,0 +1,75 @@
|
||||
/* LoggingPermission.java -- a class for logging permissions.
|
||||
Copyright (C) 2002 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Classpath.
|
||||
|
||||
GNU Classpath is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
GNU Classpath is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GNU Classpath; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
02111-1307 USA.
|
||||
|
||||
Linking this library statically or dynamically with other modules is
|
||||
making a combined work based on this library. Thus, the terms and
|
||||
conditions of the GNU General Public License cover the whole
|
||||
combination.
|
||||
|
||||
As a special exception, the copyright holders of this library give you
|
||||
permission to link this library with independent modules to produce an
|
||||
executable, regardless of the license terms of these independent
|
||||
modules, and to copy and distribute the resulting executable under
|
||||
terms of your choice, provided that you also meet, for each linked
|
||||
independent module, the terms and conditions of the license of that
|
||||
module. An independent module is a module which is not derived from
|
||||
or based on this library. If you modify this library, you may extend
|
||||
this exception to your version of the library, but you are not
|
||||
obligated to do so. If you do not wish to do so, delete this
|
||||
exception statement from your version.
|
||||
|
||||
*/
|
||||
|
||||
|
||||
package java.util.logging;
|
||||
|
||||
public final class LoggingPermission
|
||||
extends java.security.BasicPermission
|
||||
{
|
||||
/**
|
||||
* Creates a new LoggingPermission.
|
||||
*
|
||||
* @param name the name of the permission, which must be "control".
|
||||
*
|
||||
* @param actions the list of actions for the permission, which
|
||||
* must be either <code>null</code> or an empty
|
||||
* string.
|
||||
*
|
||||
* @exception IllegalArgumentException if <code>name</code>
|
||||
* is not "control", or <code>actions</code> is
|
||||
* neither <code>null</code> nor empty.
|
||||
*/
|
||||
public LoggingPermission(String name, String actions)
|
||||
{
|
||||
super("control", "");
|
||||
|
||||
if (!"control".equals(name))
|
||||
{
|
||||
throw new IllegalArgumentException(
|
||||
"name of LoggingPermission must be \"control\"");
|
||||
}
|
||||
|
||||
if ((actions != null) && (actions.length() != 0))
|
||||
{
|
||||
throw new IllegalArgumentException(
|
||||
"actions of LoggingPermissions must be null or empty");
|
||||
}
|
||||
}
|
||||
}
|
356
libjava/java/util/logging/MemoryHandler.java
Normal file
356
libjava/java/util/logging/MemoryHandler.java
Normal file
@ -0,0 +1,356 @@
|
||||
/* MemoryHandler.java
|
||||
-- a class for buffering log messages in a memory buffer
|
||||
|
||||
Copyright (C) 2002 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Classpath.
|
||||
|
||||
GNU Classpath is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
GNU Classpath is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GNU Classpath; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
02111-1307 USA.
|
||||
|
||||
Linking this library statically or dynamically with other modules is
|
||||
making a combined work based on this library. Thus, the terms and
|
||||
conditions of the GNU General Public License cover the whole
|
||||
combination.
|
||||
|
||||
As a special exception, the copyright holders of this library give you
|
||||
permission to link this library with independent modules to produce an
|
||||
executable, regardless of the license terms of these independent
|
||||
modules, and to copy and distribute the resulting executable under
|
||||
terms of your choice, provided that you also meet, for each linked
|
||||
independent module, the terms and conditions of the license of that
|
||||
module. An independent module is a module which is not derived from
|
||||
or based on this library. If you modify this library, you may extend
|
||||
this exception to your version of the library, but you are not
|
||||
obligated to do so. If you do not wish to do so, delete this
|
||||
exception statement from your version.
|
||||
|
||||
*/
|
||||
|
||||
|
||||
package java.util.logging;
|
||||
|
||||
/**
|
||||
* A <code>MemoryHandler</code> maintains a circular buffer of
|
||||
* log records.
|
||||
*
|
||||
* <p><strong>Configuration:</strong> Values of the subsequent
|
||||
* <code>LogManager</code> properties are taken into consideration
|
||||
* when a <code>MemoryHandler</code> is initialized.
|
||||
* If a property is not defined, or if it has an invalid
|
||||
* value, a default is taken without an exception being thrown.
|
||||
*
|
||||
* <ul>
|
||||
*
|
||||
* <li><code>java.util.MemoryHandler.level</code> - specifies
|
||||
* the initial severity level threshold. Default value:
|
||||
* <code>Level.ALL</code>.</li>
|
||||
*
|
||||
* <li><code>java.util.MemoryHandler.filter</code> - specifies
|
||||
* the name of a Filter class. Default value: No Filter.</li>
|
||||
*
|
||||
* <li><code>java.util.MemoryHandler.size</code> - specifies the
|
||||
* maximum number of log records that are kept in the circular
|
||||
* buffer. Default value: 1000.</li>
|
||||
*
|
||||
* <li><code>java.util.MemoryHandler.push</code> - specifies the
|
||||
* <code>pushLevel</code>. Default value:
|
||||
* <code>Level.SEVERE</code>.</li>
|
||||
*
|
||||
* <li><code>java.util.MemoryHandler.target</code> - specifies the
|
||||
* name of a subclass of {@link Handler} that will be used as the
|
||||
* target handler. There is no default value for this property;
|
||||
* if it is not set, the no-argument MemoryHandler constructor
|
||||
* will throw an exception.</li>
|
||||
*
|
||||
* </ul>
|
||||
*
|
||||
* @author Sascha Brawer (brawer@acm.org)
|
||||
*/
|
||||
public class MemoryHandler
|
||||
extends Handler
|
||||
{
|
||||
/**
|
||||
* The storage area used for buffering the unpushed log records in
|
||||
* memory.
|
||||
*/
|
||||
private final LogRecord[] buffer;
|
||||
|
||||
|
||||
/**
|
||||
* The current position in the circular buffer. For a new
|
||||
* MemoryHandler, or immediately after {@link #push()} was called,
|
||||
* the value of this variable is zero. Each call to {@link
|
||||
* #publish(LogRecord)} will store the published LogRecord into
|
||||
* <code>buffer[position]</code> before position is incremented by
|
||||
* one. If position becomes greater than the size of the buffer, it
|
||||
* is reset to zero.
|
||||
*/
|
||||
private int position;
|
||||
|
||||
|
||||
/**
|
||||
* The number of log records which have been published, but not
|
||||
* pushed yet to the target handler.
|
||||
*/
|
||||
private int numPublished;
|
||||
|
||||
|
||||
/**
|
||||
* The push level threshold for this <code>Handler</code>. When a
|
||||
* record is published whose severity level is greater than or equal
|
||||
* to the <code>pushLevel</code> of this <code>MemoryHandler</code>,
|
||||
* the {@link #push()} method will be invoked for pushing the buffer
|
||||
* contents to the target <code>Handler</code>.
|
||||
*/
|
||||
private Level pushLevel;
|
||||
|
||||
|
||||
/**
|
||||
* The Handler to which log records are forwarded for actual
|
||||
* publication.
|
||||
*/
|
||||
private final Handler target;
|
||||
|
||||
|
||||
/**
|
||||
* Constructs a <code>MemoryHandler</code> for keeping a circular
|
||||
* buffer of LogRecords; the initial configuration is determined by
|
||||
* the <code>LogManager</code> properties described above.
|
||||
*/
|
||||
public MemoryHandler()
|
||||
{
|
||||
this((Handler) LogManager.getInstanceProperty(
|
||||
"java.util.logging.MemoryHandler.target",
|
||||
Handler.class, /* default */ null),
|
||||
LogManager.getIntPropertyClamped(
|
||||
"java.util.logging.MemoryHandler.size",
|
||||
/* default */ 1000,
|
||||
/* minimum value */ 1,
|
||||
/* maximum value */ Integer.MAX_VALUE),
|
||||
LogManager.getLevelProperty(
|
||||
"java.util.logging.MemoryHandler.push",
|
||||
/* default push level */ Level.SEVERE));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Constructs a <code>MemoryHandler</code> for keeping a circular
|
||||
* buffer of LogRecords, given some parameters. The values of the
|
||||
* other parameters are taken from LogManager properties, as
|
||||
* described above.
|
||||
*
|
||||
* @param target the target handler that will receive those
|
||||
* log records that are passed on for publication.
|
||||
*
|
||||
* @param size the number of log records that are kept in the buffer.
|
||||
* The value must be a at least one.
|
||||
*
|
||||
* @param pushLevel the push level threshold for this
|
||||
* <code>MemoryHandler</code>. When a record is published whose
|
||||
* severity level is greater than or equal to
|
||||
* <code>pushLevel</code>, the {@link #push()} method will be
|
||||
* invoked in order to push the bufffer contents to
|
||||
* <code>target</code>.
|
||||
*
|
||||
* @throws java.lang.IllegalArgumentException if <code>size</code>
|
||||
* is negative or zero. The GNU implementation also throws
|
||||
* an IllegalArgumentException if <code>target</code> or
|
||||
* <code>pushLevel</code> are <code>null</code>, but the
|
||||
* API specification does not prescribe what should happen
|
||||
* in those cases.
|
||||
*/
|
||||
public MemoryHandler(Handler target, int size, Level pushLevel)
|
||||
{
|
||||
if ((target == null) || (size <= 0) || (pushLevel == null))
|
||||
throw new IllegalArgumentException();
|
||||
|
||||
buffer = new LogRecord[size];
|
||||
this.pushLevel = pushLevel;
|
||||
this.target = target;
|
||||
|
||||
setLevel(LogManager.getLevelProperty(
|
||||
"java.util.logging.MemoryHandler.level",
|
||||
/* default value */ Level.ALL));
|
||||
|
||||
setFilter((Filter) LogManager.getInstanceProperty(
|
||||
"java.util.logging.MemoryHandler.filter",
|
||||
/* must be instance of */ Filter.class,
|
||||
/* default value */ null));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Stores a <code>LogRecord</code> in a fixed-size circular buffer,
|
||||
* provided the record passes all tests for being loggable. If the
|
||||
* buffer is full, the oldest record will be discarded.
|
||||
*
|
||||
* <p>If the record has a severity level which is greater than or
|
||||
* equal to the <code>pushLevel</code> of this
|
||||
* <code>MemoryHandler</code>, the {@link #push()} method will be
|
||||
* invoked for pushing the buffer contents to the target
|
||||
* <code>Handler</code>.
|
||||
*
|
||||
* <p>Most applications do not need to call this method directly.
|
||||
* Instead, they will use use a {@link Logger}, which will create
|
||||
* LogRecords and distribute them to registered handlers.
|
||||
*
|
||||
* @param record the log event to be published.
|
||||
*/
|
||||
public void publish(LogRecord record)
|
||||
{
|
||||
if (!isLoggable(record))
|
||||
return;
|
||||
|
||||
buffer[position] = record;
|
||||
position = (position + 1) % buffer.length;
|
||||
numPublished = numPublished + 1;
|
||||
|
||||
if (record.getLevel().intValue() >= pushLevel.intValue())
|
||||
push();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Pushes the contents of the memory buffer to the target
|
||||
* <code>Handler</code> and clears the buffer. Note that
|
||||
* the target handler will discard those records that do
|
||||
* not satisfy its own severity level threshold, or that are
|
||||
* not considered loggable by an installed {@link Filter}.
|
||||
*
|
||||
* <p>In case of an I/O failure, the {@link ErrorManager} of the
|
||||
* target <code>Handler</code> will be notified, but the caller of
|
||||
* this method will not receive an exception.
|
||||
*/
|
||||
public void push()
|
||||
{
|
||||
int i;
|
||||
|
||||
if (numPublished < buffer.length)
|
||||
{
|
||||
for (i = 0; i < position; i++)
|
||||
target.publish(buffer[i]);
|
||||
}
|
||||
else
|
||||
{
|
||||
for (i = position; i < buffer.length; i++)
|
||||
target.publish(buffer[i]);
|
||||
for (i = 0; i < position; i++)
|
||||
target.publish(buffer[i]);
|
||||
}
|
||||
|
||||
numPublished = 0;
|
||||
position = 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Forces any data that may have been buffered by the target
|
||||
* <code>Handler</code> to the underlying output device, but
|
||||
* does <em>not</em> push the contents of the circular memory
|
||||
* buffer to the target handler.
|
||||
*
|
||||
* <p>In case of an I/O failure, the {@link ErrorManager} of the
|
||||
* target <code>Handler</code> will be notified, but the caller of
|
||||
* this method will not receive an exception.
|
||||
*
|
||||
* @see #push()
|
||||
*/
|
||||
public void flush()
|
||||
{
|
||||
target.flush();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Closes this <code>MemoryHandler</code> and its associated target
|
||||
* handler, discarding the contents of the memory buffer. However,
|
||||
* any data that may have been buffered by the target
|
||||
* <code>Handler</code> is forced to the underlying output device.
|
||||
*
|
||||
* <p>As soon as <code>close</code> has been called,
|
||||
* a <code>Handler</code> should not be used anymore. Attempts
|
||||
* to publish log records, to flush buffers, or to modify the
|
||||
* <code>Handler</code> in any other way may throw runtime
|
||||
* exceptions after calling <code>close</code>.</p>
|
||||
*
|
||||
* <p>In case of an I/O failure, the <code>ErrorManager</code> of
|
||||
* the associated target <code>Handler</code> will be informed, but
|
||||
* the caller of this method will not receive an exception.</p>
|
||||
*
|
||||
* @throws SecurityException if a security manager exists and
|
||||
* the caller is not granted the permission to control
|
||||
* the logging infrastructure.
|
||||
*
|
||||
* @see #push()
|
||||
*/
|
||||
public void close()
|
||||
throws SecurityException
|
||||
{
|
||||
push();
|
||||
|
||||
/* This will check for LoggingPermission("control"). If the
|
||||
* current security context does not grant this permission,
|
||||
* push() has been executed, but this does not impose a
|
||||
* security risk.
|
||||
*/
|
||||
target.close();
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Returns the push level threshold for this <code>Handler</code>.
|
||||
* When a record is published whose severity level is greater
|
||||
* than or equal to the <code>pushLevel</code> of this
|
||||
* <code>MemoryHandler</code>, the {@link #push()} method will be
|
||||
* invoked for pushing the buffer contents to the target
|
||||
* <code>Handler</code>.
|
||||
*
|
||||
* @return the push level threshold for automatic pushing.
|
||||
*/
|
||||
public Level getPushLevel()
|
||||
{
|
||||
return pushLevel;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Sets the push level threshold for this <code>Handler</code>.
|
||||
* When a record is published whose severity level is greater
|
||||
* than or equal to the <code>pushLevel</code> of this
|
||||
* <code>MemoryHandler</code>, the {@link #push()} method will be
|
||||
* invoked for pushing the buffer contents to the target
|
||||
* <code>Handler</code>.
|
||||
*
|
||||
* @param pushLevel the push level threshold for automatic pushing.
|
||||
*
|
||||
* @exception SecurityException if a security manager exists and
|
||||
* the caller is not granted the permission to control
|
||||
* the logging infrastructure.
|
||||
*
|
||||
* @exception NullPointerException if <code>pushLevel</code> is
|
||||
* <code>null</code>.
|
||||
*/
|
||||
public void setPushLevel(Level pushLevel)
|
||||
{
|
||||
LogManager.getLogManager().checkAccess();
|
||||
|
||||
/* Throws a NullPointerException if pushLevel is null. */
|
||||
pushLevel.getClass();
|
||||
|
||||
this.pushLevel = pushLevel;
|
||||
}
|
||||
}
|
120
libjava/java/util/logging/SimpleFormatter.java
Normal file
120
libjava/java/util/logging/SimpleFormatter.java
Normal file
@ -0,0 +1,120 @@
|
||||
/* SimpleFormatter.java
|
||||
-- a class for formatting log records into short human-readable messages
|
||||
|
||||
Copyright (C) 2002 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Classpath.
|
||||
|
||||
GNU Classpath is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
GNU Classpath is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GNU Classpath; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
02111-1307 USA.
|
||||
|
||||
Linking this library statically or dynamically with other modules is
|
||||
making a combined work based on this library. Thus, the terms and
|
||||
conditions of the GNU General Public License cover the whole
|
||||
combination.
|
||||
|
||||
As a special exception, the copyright holders of this library give you
|
||||
permission to link this library with independent modules to produce an
|
||||
executable, regardless of the license terms of these independent
|
||||
modules, and to copy and distribute the resulting executable under
|
||||
terms of your choice, provided that you also meet, for each linked
|
||||
independent module, the terms and conditions of the license of that
|
||||
module. An independent module is a module which is not derived from
|
||||
or based on this library. If you modify this library, you may extend
|
||||
this exception to your version of the library, but you are not
|
||||
obligated to do so. If you do not wish to do so, delete this
|
||||
exception statement from your version.
|
||||
|
||||
*/
|
||||
|
||||
|
||||
package java.util.logging;
|
||||
|
||||
import java.util.Date;
|
||||
import java.text.DateFormat;
|
||||
|
||||
/**
|
||||
* A <code>SimpleFormatter</code> formats log records into
|
||||
* short human-readable messages, typically one or two lines.
|
||||
*
|
||||
* @author Sascha Brawer (brawer@acm.org)
|
||||
*/
|
||||
public class SimpleFormatter
|
||||
extends Formatter
|
||||
{
|
||||
/**
|
||||
* Constructs a SimpleFormatter.
|
||||
*/
|
||||
public SimpleFormatter()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* An instance of a DateFormatter that is used for formatting
|
||||
* the time of a log record into a human-readable string,
|
||||
* according to the rules of the current locale. The value
|
||||
* is set after the first invocation of format, since it is
|
||||
* common that a JVM will instantiate a SimpleFormatter without
|
||||
* ever using it.
|
||||
*/
|
||||
private DateFormat dateFormat;
|
||||
|
||||
/**
|
||||
* The character sequence that is used to separate lines in the
|
||||
* generated stream. Somewhat surprisingly, the Sun J2SE 1.4
|
||||
* reference implementation always uses UNIX line endings, even on
|
||||
* platforms that have different line ending conventions (i.e.,
|
||||
* DOS). The GNU implementation does not replicate this bug.
|
||||
*
|
||||
* @see Sun bug parade, bug #4462871,
|
||||
* "java.util.logging.SimpleFormatter uses hard-coded line separator".
|
||||
*/
|
||||
static final String lineSep = System.getProperty("line.separator");
|
||||
|
||||
|
||||
/**
|
||||
* Formats a log record into a String.
|
||||
*
|
||||
* @param the log record to be formatted.
|
||||
*
|
||||
* @return a short human-readable message, typically one or two
|
||||
* lines. Lines are separated using the default platform line
|
||||
* separator.
|
||||
*
|
||||
* @throws NullPointerException if <code>record</code>
|
||||
* is <code>null</code>.
|
||||
*/
|
||||
public String format(LogRecord record)
|
||||
{
|
||||
StringBuffer buf = new StringBuffer(180);
|
||||
|
||||
if (dateFormat == null)
|
||||
dateFormat = DateFormat.getDateTimeInstance();
|
||||
|
||||
buf.append(dateFormat.format(new Date(record.getMillis())));
|
||||
buf.append(' ');
|
||||
buf.append(record.getLoggerName());
|
||||
buf.append(lineSep);
|
||||
|
||||
buf.append(record.getLevel());
|
||||
buf.append(": ");
|
||||
buf.append(formatMessage(record));
|
||||
|
||||
buf.append(lineSep);
|
||||
|
||||
return buf.toString();
|
||||
}
|
||||
}
|
225
libjava/java/util/logging/SocketHandler.java
Normal file
225
libjava/java/util/logging/SocketHandler.java
Normal file
@ -0,0 +1,225 @@
|
||||
/* SocketHandler.java
|
||||
-- a class for publishing log messages to network sockets
|
||||
|
||||
Copyright (C) 2002 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Classpath.
|
||||
|
||||
GNU Classpath is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
GNU Classpath is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GNU Classpath; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
02111-1307 USA.
|
||||
|
||||
Linking this library statically or dynamically with other modules is
|
||||
making a combined work based on this library. Thus, the terms and
|
||||
conditions of the GNU General Public License cover the whole
|
||||
combination.
|
||||
|
||||
As a special exception, the copyright holders of this library give you
|
||||
permission to link this library with independent modules to produce an
|
||||
executable, regardless of the license terms of these independent
|
||||
modules, and to copy and distribute the resulting executable under
|
||||
terms of your choice, provided that you also meet, for each linked
|
||||
independent module, the terms and conditions of the license of that
|
||||
module. An independent module is a module which is not derived from
|
||||
or based on this library. If you modify this library, you may extend
|
||||
this exception to your version of the library, but you are not
|
||||
obligated to do so. If you do not wish to do so, delete this
|
||||
exception statement from your version.
|
||||
|
||||
*/
|
||||
|
||||
|
||||
package java.util.logging;
|
||||
|
||||
|
||||
/**
|
||||
* A <code>SocketHandler</code> publishes log records to
|
||||
* a TCP/IP socket.
|
||||
*
|
||||
* <p><strong>Configuration:</strong> Values of the subsequent
|
||||
* <code>LogManager</code> properties are taken into consideration
|
||||
* when a <code>SocketHandler</code> is initialized.
|
||||
* If a property is not defined, or if it has an invalid
|
||||
* value, a default is taken without an exception being thrown.
|
||||
*
|
||||
* <ul>
|
||||
*
|
||||
* <li><code>java.util.SocketHandler.level</code> - specifies
|
||||
* the initial severity level threshold. Default value:
|
||||
* <code>Level.ALL</code>.</li>
|
||||
*
|
||||
* <li><code>java.util.SocketHandler.filter</code> - specifies
|
||||
* the name of a Filter class. Default value: No Filter.</li>
|
||||
*
|
||||
* <li><code>java.util.SocketHandler.formatter</code> - specifies
|
||||
* the name of a Formatter class. Default value:
|
||||
* <code>java.util.logging.XMLFormatter</code>.</li>
|
||||
*
|
||||
* <li><code>java.util.SocketHandler.encoding</code> - specifies
|
||||
* the name of the character encoding. Default value:
|
||||
* the default platform encoding.
|
||||
*
|
||||
* <li><code>java.util.SocketHandler.host</code> - specifies
|
||||
* the name of the host to which records are published.
|
||||
* There is no default value for this property; if it is
|
||||
* not set, the SocketHandler constructor will throw
|
||||
* an exception.</li>
|
||||
*
|
||||
* <li><code>java.util.SocketHandler.port</code> - specifies
|
||||
* the TCP/IP port to which records are published.
|
||||
* There is no default value for this property; if it is
|
||||
* not set, the SocketHandler constructor will throw
|
||||
* an exception.</li>
|
||||
*
|
||||
* </ul>
|
||||
*
|
||||
* @author Sascha Brawer (brawer@acm.org)
|
||||
*/
|
||||
public class SocketHandler
|
||||
extends StreamHandler
|
||||
{
|
||||
/**
|
||||
* Constructs a <code>SocketHandler</code> that publishes log
|
||||
* records to a TCP/IP socket. Tthe initial configuration is
|
||||
* determined by the <code>LogManager</code> properties described
|
||||
* above.
|
||||
*
|
||||
* @throws java.io.IOException if the connection to the specified
|
||||
* network host and port cannot be established.
|
||||
*
|
||||
* @throws java.lang.IllegalArgumentException if either the
|
||||
* <code>java.util.logging.SocketHandler.host</code>
|
||||
* or <code>java.util.logging.SocketHandler.port</code>
|
||||
* LogManager properties is not defined, or specifies
|
||||
* an invalid value.
|
||||
*/
|
||||
public SocketHandler()
|
||||
throws java.io.IOException
|
||||
{
|
||||
this(LogManager.getLogManager().getProperty("java.util.logging.SocketHandler.host"),
|
||||
getPortNumber());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Constructs a <code>SocketHandler</code> that publishes log
|
||||
* records to a TCP/IP socket. With the exception of the internet
|
||||
* host and port, the initial configuration is determined by the
|
||||
* <code>LogManager</code> properties described above.
|
||||
*
|
||||
* @param host the Internet host to which log records will be
|
||||
* forwarded.
|
||||
*
|
||||
* @param port the port at the host which will accept a request
|
||||
* for a TCP/IP connection.
|
||||
*
|
||||
* @throws java.io.IOException if the connection to the specified
|
||||
* network host and port cannot be established.
|
||||
*
|
||||
* @throws java.lang.IllegalArgumentException if either
|
||||
* <code>host</code> or <code>port</code> specify
|
||||
* an invalid value.
|
||||
*/
|
||||
public SocketHandler(String host, int port)
|
||||
throws java.io.IOException
|
||||
{
|
||||
super(createSocket(host, port),
|
||||
"java.util.logging.SocketHandler",
|
||||
/* default level */ Level.ALL,
|
||||
/* formatter */ null,
|
||||
/* default formatter */ XMLFormatter.class);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Retrieves the port number from the java.util.logging.SocketHandler.port
|
||||
* LogManager property.
|
||||
*
|
||||
* @throws IllegalArgumentException if the property is not defined or
|
||||
* does not specify an integer value.
|
||||
*/
|
||||
private static int getPortNumber()
|
||||
{
|
||||
try {
|
||||
return Integer.parseInt(LogManager.getLogManager().getProperty("java.util.logging.SocketHandler.port"));
|
||||
} catch (Exception ex) {
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Creates an OutputStream for publishing log records to an Internet
|
||||
* host and port. This private method is a helper for use by the
|
||||
* constructor of SocketHandler.
|
||||
*
|
||||
* @param host the Internet host to which log records will be
|
||||
* forwarded.
|
||||
*
|
||||
* @param port the port at the host which will accept a request
|
||||
* for a TCP/IP connection.
|
||||
*
|
||||
* @throws java.io.IOException if the connection to the specified
|
||||
* network host and port cannot be established.
|
||||
*
|
||||
* @throws java.lang.IllegalArgumentException if either
|
||||
* <code>host</code> or <code>port</code> specify
|
||||
* an invalid value.
|
||||
*/
|
||||
private static java.io.OutputStream createSocket(String host, int port)
|
||||
throws java.io.IOException, java.lang.IllegalArgumentException
|
||||
{
|
||||
java.net.Socket socket;
|
||||
|
||||
if ((host == null) || (port < 1))
|
||||
throw new IllegalArgumentException();
|
||||
|
||||
socket = new java.net.Socket(host, port);
|
||||
|
||||
socket.shutdownInput();
|
||||
|
||||
/* The architecture of the logging framework provides replaceable
|
||||
* formatters. Because these formatters perform their task by
|
||||
* returning one single String for each LogRecord to be formatted,
|
||||
* there is no need to buffer.
|
||||
*/
|
||||
socket.setTcpNoDelay(true);
|
||||
|
||||
return socket.getOutputStream();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Publishes a <code>LogRecord</code> to the network socket,
|
||||
* provided the record passes all tests for being loggable.
|
||||
* In addition, all data that may have been buffered will
|
||||
* be forced to the network stream.
|
||||
*
|
||||
* <p>Most applications do not need to call this method directly.
|
||||
* Instead, they will use a {@link Logger} instance, which will
|
||||
* create LogRecords and distribute them to registered handlers.
|
||||
*
|
||||
* <p>In case of an I/O failure, the <code>ErrorManager</code>
|
||||
* of this <code>SocketHandler</code> will be informed, but the caller
|
||||
* of this method will not receive an exception.
|
||||
*
|
||||
* @param record the log event to be published.
|
||||
*/
|
||||
public void publish(LogRecord record)
|
||||
{
|
||||
super.publish(record);
|
||||
flush();
|
||||
}
|
||||
}
|
||||
|
524
libjava/java/util/logging/StreamHandler.java
Normal file
524
libjava/java/util/logging/StreamHandler.java
Normal file
@ -0,0 +1,524 @@
|
||||
/* StreamHandler.java
|
||||
-- a class for publishing log messages to instances of java.io.OutputStream
|
||||
|
||||
Copyright (C) 2002 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Classpath.
|
||||
|
||||
GNU Classpath is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
GNU Classpath is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GNU Classpath; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
02111-1307 USA.
|
||||
|
||||
Linking this library statically or dynamically with other modules is
|
||||
making a combined work based on this library. Thus, the terms and
|
||||
conditions of the GNU General Public License cover the whole
|
||||
combination.
|
||||
|
||||
As a special exception, the copyright holders of this library give you
|
||||
permission to link this library with independent modules to produce an
|
||||
executable, regardless of the license terms of these independent
|
||||
modules, and to copy and distribute the resulting executable under
|
||||
terms of your choice, provided that you also meet, for each linked
|
||||
independent module, the terms and conditions of the license of that
|
||||
module. An independent module is a module which is not derived from
|
||||
or based on this library. If you modify this library, you may extend
|
||||
this exception to your version of the library, but you are not
|
||||
obligated to do so. If you do not wish to do so, delete this
|
||||
exception statement from your version.
|
||||
|
||||
*/
|
||||
|
||||
|
||||
package java.util.logging;
|
||||
|
||||
import java.io.OutputStream;
|
||||
import java.io.OutputStreamWriter;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.io.Writer;
|
||||
|
||||
/**
|
||||
* A <code>StreamHandler</code> publishes <code>LogRecords</code> to
|
||||
* a instances of <code>java.io.OutputStream</code>.
|
||||
*
|
||||
* @author Sascha Brawer (brawer@acm.org)
|
||||
*/
|
||||
public class StreamHandler
|
||||
extends Handler
|
||||
{
|
||||
private OutputStream out;
|
||||
private Writer writer;
|
||||
|
||||
|
||||
/**
|
||||
* Indicates the current state of this StreamHandler. The value
|
||||
* should be one of STATE_FRESH, STATE_PUBLISHED, or STATE_CLOSED.
|
||||
*/
|
||||
private int streamState = STATE_FRESH;
|
||||
|
||||
|
||||
/**
|
||||
* streamState having this value indicates that the StreamHandler
|
||||
* has been created, but the publish(LogRecord) method has not been
|
||||
* called yet. If the StreamHandler has been constructed without an
|
||||
* OutputStream, writer will be null, otherwise it is set to a
|
||||
* freshly created OutputStreamWriter.
|
||||
*/
|
||||
private static final int STATE_FRESH = 0;
|
||||
|
||||
|
||||
/**
|
||||
* streamState having this value indicates that the publish(LocRecord)
|
||||
* method has been called at least once.
|
||||
*/
|
||||
private static final int STATE_PUBLISHED = 1;
|
||||
|
||||
|
||||
/**
|
||||
* streamState having this value indicates that the close() method
|
||||
* has been called.
|
||||
*/
|
||||
private static final int STATE_CLOSED = 2;
|
||||
|
||||
|
||||
/**
|
||||
* Creates a <code>StreamHandler</code> without an output stream.
|
||||
* Subclasses can later use {@link
|
||||
* #setOutputStream(java.io.OutputStream)} to associate an output
|
||||
* stream with this StreamHandler.
|
||||
*/
|
||||
public StreamHandler()
|
||||
{
|
||||
this(null, null);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Creates a <code>StreamHandler</code> that formats log messages
|
||||
* with the specified Formatter and publishes them to the specified
|
||||
* output stream.
|
||||
*
|
||||
* @param out the output stream to which the formatted log messages
|
||||
* are published.
|
||||
*
|
||||
* @param formatter the <code>Formatter</code> that will be used
|
||||
* to format log messages.
|
||||
*/
|
||||
public StreamHandler(OutputStream out, Formatter formatter)
|
||||
{
|
||||
this(out, "java.util.logging.StreamHandler", Level.INFO,
|
||||
formatter, SimpleFormatter.class);
|
||||
}
|
||||
|
||||
|
||||
StreamHandler(
|
||||
OutputStream out,
|
||||
String propertyPrefix,
|
||||
Level defaultLevel,
|
||||
Formatter formatter, Class defaultFormatterClass)
|
||||
{
|
||||
this.level = LogManager.getLevelProperty(propertyPrefix + ".level",
|
||||
defaultLevel);
|
||||
|
||||
this.filter = (Filter) LogManager.getInstanceProperty(
|
||||
propertyPrefix + ".filter",
|
||||
/* must be instance of */ Filter.class,
|
||||
/* default: new instance of */ null);
|
||||
|
||||
if (formatter != null)
|
||||
this.formatter = formatter;
|
||||
else
|
||||
this.formatter = (Formatter) LogManager.getInstanceProperty(
|
||||
propertyPrefix + ".formatter",
|
||||
/* must be instance of */ Formatter.class,
|
||||
/* default: new instance of */ defaultFormatterClass);
|
||||
|
||||
try
|
||||
{
|
||||
String enc = LogManager.getLogManager().getProperty(propertyPrefix
|
||||
+ ".encoding");
|
||||
|
||||
/* make sure enc actually is a valid encoding */
|
||||
if ((enc != null) && (enc.length() > 0))
|
||||
new String(new byte[0], enc);
|
||||
|
||||
this.encoding = enc;
|
||||
}
|
||||
catch (Exception _)
|
||||
{
|
||||
}
|
||||
|
||||
if (out != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
changeWriter(out, getEncoding());
|
||||
}
|
||||
catch (UnsupportedEncodingException uex)
|
||||
{
|
||||
/* This should never happen, since the validity of the encoding
|
||||
* name has been checked above.
|
||||
*/
|
||||
throw new RuntimeException(uex.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void checkOpen()
|
||||
{
|
||||
if (streamState == STATE_CLOSED)
|
||||
throw new IllegalStateException(this.toString() + " has been closed");
|
||||
}
|
||||
|
||||
private void checkFresh()
|
||||
{
|
||||
checkOpen();
|
||||
if (streamState != STATE_FRESH)
|
||||
throw new IllegalStateException("some log records have been published to " + this);
|
||||
}
|
||||
|
||||
|
||||
private void changeWriter(OutputStream out, String encoding)
|
||||
throws UnsupportedEncodingException
|
||||
{
|
||||
OutputStreamWriter writer;
|
||||
|
||||
/* The logging API says that a null encoding means the default
|
||||
* platform encoding. However, java.io.OutputStreamWriter needs
|
||||
* another constructor for the default platform encoding,
|
||||
* passing null would throw an exception.
|
||||
*/
|
||||
if (encoding == null)
|
||||
writer = new OutputStreamWriter(out);
|
||||
else
|
||||
writer = new OutputStreamWriter(out, encoding);
|
||||
|
||||
/* Closing the stream has side effects -- do this only after
|
||||
* creating a new writer has been successful.
|
||||
*/
|
||||
if ((streamState != STATE_FRESH) || (this.writer != null))
|
||||
close();
|
||||
|
||||
this.writer = writer;
|
||||
this.out = out;
|
||||
this.encoding = encoding;
|
||||
streamState = STATE_FRESH;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Sets the character encoding which this handler uses for publishing
|
||||
* log records. The encoding of a <code>StreamHandler</code> must be
|
||||
* set before any log records have been published.
|
||||
*
|
||||
* @param encoding the name of a character encoding, or <code>null</code>
|
||||
* for the default encoding.
|
||||
*
|
||||
* @throws SecurityException if a security manager exists and
|
||||
* the caller is not granted the permission to control the
|
||||
* the logging infrastructure.
|
||||
*
|
||||
* @exception IllegalStateException if any log records have been
|
||||
* published to this <code>StreamHandler</code> before. Please
|
||||
* be aware that this is a pecularity of the GNU implementation.
|
||||
* While the API specification indicates that it is an error
|
||||
* if the encoding is set after records have been published,
|
||||
* it does not mandate any specific behavior for that case.
|
||||
*/
|
||||
public void setEncoding(String encoding)
|
||||
throws SecurityException, UnsupportedEncodingException
|
||||
{
|
||||
/* The inherited implementation first checks whether the invoking
|
||||
* code indeed has the permission to control the logging infra-
|
||||
* structure, and throws a SecurityException if this was not the
|
||||
* case.
|
||||
*
|
||||
* Next, it verifies that the encoding is supported and throws
|
||||
* an UnsupportedEncodingExcpetion otherwise. Finally, it remembers
|
||||
* the name of the encoding.
|
||||
*/
|
||||
super.setEncoding(encoding);
|
||||
|
||||
checkFresh();
|
||||
|
||||
/* If out is null, setEncoding is being called before an output
|
||||
* stream has been set. In that case, we need to check that the
|
||||
* encoding is valid, and remember it if this is the case. Since
|
||||
* this is exactly what the inherited implementation of
|
||||
* Handler.setEncoding does, we can delegate.
|
||||
*/
|
||||
if (out != null)
|
||||
{
|
||||
/* The logging API says that a null encoding means the default
|
||||
* platform encoding. However, java.io.OutputStreamWriter needs
|
||||
* another constructor for the default platform encoding, passing
|
||||
* null would throw an exception.
|
||||
*/
|
||||
if (encoding == null)
|
||||
writer = new OutputStreamWriter(out);
|
||||
else
|
||||
writer = new OutputStreamWriter(out, encoding);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Changes the output stream to which this handler publishes
|
||||
* logging records.
|
||||
*
|
||||
* @throws SecurityException if a security manager exists and
|
||||
* the caller is not granted the permission to control
|
||||
* the logging infrastructure.
|
||||
*
|
||||
* @throws NullPointerException if <code>out</code>
|
||||
* is <code>null</code>.
|
||||
*/
|
||||
protected void setOutputStream(OutputStream out)
|
||||
throws SecurityException
|
||||
{
|
||||
LogManager.getLogManager().checkAccess();
|
||||
|
||||
/* Throw a NullPointerException if out is null. */
|
||||
out.getClass();
|
||||
|
||||
try
|
||||
{
|
||||
changeWriter(out, getEncoding());
|
||||
}
|
||||
catch (UnsupportedEncodingException ex)
|
||||
{
|
||||
/* This seems quite unlikely to happen, unless the underlying
|
||||
* implementation of java.io.OutputStreamWriter changes its
|
||||
* mind (at runtime) about the set of supported character
|
||||
* encodings.
|
||||
*/
|
||||
throw new RuntimeException(ex.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Publishes a <code>LogRecord</code> to the associated output
|
||||
* stream, provided the record passes all tests for being loggable.
|
||||
* The <code>StreamHandler</code> will localize the message of the
|
||||
* log record and substitute any message parameters.
|
||||
*
|
||||
* <p>Most applications do not need to call this method directly.
|
||||
* Instead, they will use use a {@link Logger}, which will create
|
||||
* LogRecords and distribute them to registered handlers.
|
||||
*
|
||||
* <p>In case of an I/O failure, the <code>ErrorManager</code>
|
||||
* of this <code>Handler</code> will be informed, but the caller
|
||||
* of this method will not receive an exception.
|
||||
*
|
||||
* <p>If a log record is being published to a
|
||||
* <code>StreamHandler</code> that has been closed earlier, the Sun
|
||||
* J2SE 1.4 reference can be observed to silently ignore the
|
||||
* call. The GNU implementation, however, intentionally behaves
|
||||
* differently by informing the <code>ErrorManager</code> associated
|
||||
* with this <code>StreamHandler</code>. Since the condition
|
||||
* indicates a programming error, the programmer should be
|
||||
* informed. It also seems extremely unlikely that any application
|
||||
* would depend on the exact behavior in this rather obscure,
|
||||
* erroneous case -- especially since the API specification does not
|
||||
* prescribe what is supposed to happen.
|
||||
*
|
||||
* @param record the log event to be published.
|
||||
*/
|
||||
public void publish(LogRecord record)
|
||||
{
|
||||
String formattedMessage;
|
||||
|
||||
if (!isLoggable(record))
|
||||
return;
|
||||
|
||||
if (streamState == STATE_FRESH)
|
||||
{
|
||||
try
|
||||
{
|
||||
writer.write(formatter.getHead(this));
|
||||
}
|
||||
catch (java.io.IOException ex)
|
||||
{
|
||||
reportError(null, ex, ErrorManager.WRITE_FAILURE);
|
||||
return;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
reportError(null, ex, ErrorManager.GENERIC_FAILURE);
|
||||
return;
|
||||
}
|
||||
|
||||
streamState = STATE_PUBLISHED;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
formattedMessage = formatter.format(record);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
reportError(null, ex, ErrorManager.FORMAT_FAILURE);
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
writer.write(formattedMessage);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
reportError(null, ex, ErrorManager.WRITE_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Checks whether or not a <code>LogRecord</code> would be logged
|
||||
* if it was passed to this <code>StreamHandler</code> for publication.
|
||||
*
|
||||
* <p>The <code>StreamHandler</code> implementation first checks
|
||||
* whether a writer is present and the handler's level is greater
|
||||
* than or equal to the severity level threshold. In a second step,
|
||||
* if a {@link Filter} has been installed, its {@link
|
||||
* Filter#isLoggable(LogRecord) isLoggable} method is
|
||||
* invoked. Subclasses of <code>StreamHandler</code> can override
|
||||
* this method to impose their own constraints.
|
||||
*
|
||||
* @param record the <code>LogRecord</code> to be checked.
|
||||
*
|
||||
* @return <code>true</code> if <code>record</code> would
|
||||
* be published by {@link #publish(LogRecord) publish},
|
||||
* <code>false</code> if it would be discarded.
|
||||
*
|
||||
* @see #setLevel(Level)
|
||||
* @see #setFilter(Filter)
|
||||
* @see Filter#isLoggable(LogRecord)
|
||||
*
|
||||
* @throws NullPointerException if <code>record</code> is
|
||||
* <code>null</code>. */
|
||||
public boolean isLoggable(LogRecord record)
|
||||
{
|
||||
return (writer != null) && super.isLoggable(record);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Forces any data that may have been buffered to the underlying
|
||||
* output device.
|
||||
*
|
||||
* <p>In case of an I/O failure, the <code>ErrorManager</code>
|
||||
* of this <code>Handler</code> will be informed, but the caller
|
||||
* of this method will not receive an exception.
|
||||
*
|
||||
* <p>If a <code>StreamHandler</code> that has been closed earlier
|
||||
* is closed a second time, the Sun J2SE 1.4 reference can be
|
||||
* observed to silently ignore the call. The GNU implementation,
|
||||
* however, intentionally behaves differently by informing the
|
||||
* <code>ErrorManager</code> associated with this
|
||||
* <code>StreamHandler</code>. Since the condition indicates a
|
||||
* programming error, the programmer should be informed. It also
|
||||
* seems extremely unlikely that any application would depend on the
|
||||
* exact behavior in this rather obscure, erroneous case --
|
||||
* especially since the API specification does not prescribe what is
|
||||
* supposed to happen.
|
||||
*/
|
||||
public void flush()
|
||||
{
|
||||
try
|
||||
{
|
||||
checkOpen();
|
||||
if (writer != null)
|
||||
writer.flush();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
reportError(null, ex, ErrorManager.FLUSH_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Closes this <code>StreamHandler</code> after having forced any
|
||||
* data that may have been buffered to the underlying output
|
||||
* device.
|
||||
*
|
||||
* <p>As soon as <code>close</code> has been called,
|
||||
* a <code>Handler</code> should not be used anymore. Attempts
|
||||
* to publish log records, to flush buffers, or to modify the
|
||||
* <code>Handler</code> in any other way may throw runtime
|
||||
* exceptions after calling <code>close</code>.</p>
|
||||
*
|
||||
* <p>In case of an I/O failure, the <code>ErrorManager</code>
|
||||
* of this <code>Handler</code> will be informed, but the caller
|
||||
* of this method will not receive an exception.</p>
|
||||
*
|
||||
* <p>If a <code>StreamHandler</code> that has been closed earlier
|
||||
* is closed a second time, the Sun J2SE 1.4 reference can be
|
||||
* observed to silently ignore the call. The GNU implementation,
|
||||
* however, intentionally behaves differently by informing the
|
||||
* <code>ErrorManager</code> associated with this
|
||||
* <code>StreamHandler</code>. Since the condition indicates a
|
||||
* programming error, the programmer should be informed. It also
|
||||
* seems extremely unlikely that any application would depend on the
|
||||
* exact behavior in this rather obscure, erroneous case --
|
||||
* especially since the API specification does not prescribe what is
|
||||
* supposed to happen.
|
||||
*
|
||||
* @throws SecurityException if a security manager exists and
|
||||
* the caller is not granted the permission to control
|
||||
* the logging infrastructure.
|
||||
*/
|
||||
public void close()
|
||||
throws SecurityException
|
||||
{
|
||||
LogManager.getLogManager().checkAccess();
|
||||
|
||||
try
|
||||
{
|
||||
/* Although flush also calls checkOpen, it catches
|
||||
* any exceptions and reports them to the ErrorManager
|
||||
* as flush failures. However, we want to report
|
||||
* a closed stream as a close failure, not as a
|
||||
* flush failure here. Therefore, we call checkOpen()
|
||||
* before flush().
|
||||
*/
|
||||
checkOpen();
|
||||
flush();
|
||||
|
||||
if (writer != null)
|
||||
{
|
||||
if (formatter != null)
|
||||
{
|
||||
/* Even if the StreamHandler has never published a record,
|
||||
* it emits head and tail upon closing. An earlier version
|
||||
* of the GNU Classpath implementation did not emitted
|
||||
* anything. However, this had caused XML log files to be
|
||||
* entirely empty instead of containing no log records.
|
||||
*/
|
||||
if (streamState == STATE_FRESH)
|
||||
writer.write(formatter.getHead(this));
|
||||
if (streamState != STATE_CLOSED)
|
||||
writer.write(formatter.getTail(this));
|
||||
}
|
||||
streamState = STATE_CLOSED;
|
||||
writer.close();
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
reportError(null, ex, ErrorManager.CLOSE_FAILURE);
|
||||
}
|
||||
}
|
||||
}
|
395
libjava/java/util/logging/XMLFormatter.java
Normal file
395
libjava/java/util/logging/XMLFormatter.java
Normal file
@ -0,0 +1,395 @@
|
||||
/* XMLFormatter.java
|
||||
-- a class for formatting log messages into a standard XML format
|
||||
|
||||
Copyright (C) 2002 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Classpath.
|
||||
|
||||
GNU Classpath is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
GNU Classpath is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GNU Classpath; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
02111-1307 USA.
|
||||
|
||||
Linking this library statically or dynamically with other modules is
|
||||
making a combined work based on this library. Thus, the terms and
|
||||
conditions of the GNU General Public License cover the whole
|
||||
combination.
|
||||
|
||||
As a special exception, the copyright holders of this library give you
|
||||
permission to link this library with independent modules to produce an
|
||||
executable, regardless of the license terms of these independent
|
||||
modules, and to copy and distribute the resulting executable under
|
||||
terms of your choice, provided that you also meet, for each linked
|
||||
independent module, the terms and conditions of the license of that
|
||||
module. An independent module is a module which is not derived from
|
||||
or based on this library. If you modify this library, you may extend
|
||||
this exception to your version of the library, but you are not
|
||||
obligated to do so. If you do not wish to do so, delete this
|
||||
exception statement from your version.
|
||||
|
||||
*/
|
||||
|
||||
|
||||
package java.util.logging;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.ResourceBundle;
|
||||
import java.text.MessageFormat;
|
||||
import java.text.SimpleDateFormat;
|
||||
|
||||
/**
|
||||
* An <code>XMLFormatter</code> formats LogRecords into
|
||||
* a standard XML format.
|
||||
*
|
||||
* @author Sascha Brawer (brawer@acm.org)
|
||||
*/
|
||||
public class XMLFormatter
|
||||
extends Formatter
|
||||
{
|
||||
/**
|
||||
* Constructs a new XMLFormatter.
|
||||
*/
|
||||
public XMLFormatter()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* The character sequence that is used to separate lines in the
|
||||
* generated XML stream. Somewhat surprisingly, the Sun J2SE 1.4
|
||||
* reference implementation always uses UNIX line endings, even on
|
||||
* platforms that have different line ending conventions (i.e.,
|
||||
* DOS). The GNU Classpath implementation does not replicates this
|
||||
* bug.
|
||||
*
|
||||
* See also the Sun bug parade, bug #4462871,
|
||||
* "java.util.logging.SimpleFormatter uses hard-coded line separator".
|
||||
*/
|
||||
private static final String lineSep = SimpleFormatter.lineSep;
|
||||
|
||||
|
||||
/**
|
||||
* A DateFormat for emitting time in the ISO 8601 format.
|
||||
* Since the API specification of SimpleDateFormat does not talk
|
||||
* about its thread-safety, we cannot share a singleton instance.
|
||||
*/
|
||||
private final SimpleDateFormat iso8601
|
||||
= new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
|
||||
|
||||
|
||||
/**
|
||||
* Appends a line consisting of indentation, opening element tag,
|
||||
* element content, closing element tag and line separator to
|
||||
* a StringBuffer, provided that the element content is
|
||||
* actually existing.
|
||||
*
|
||||
* @param buf the StringBuffer to which the line will be appended.
|
||||
*
|
||||
* @param indent the indentation level.
|
||||
*
|
||||
* @param tag the element tag name, for instance <code>method</code>.
|
||||
*
|
||||
* @param content the element content, or <code>null</code> to
|
||||
* have no output whatsoever appended to <code>buf</code>.
|
||||
*/
|
||||
private static final void appendTag(StringBuffer buf,
|
||||
int indent,
|
||||
String tag,
|
||||
String content)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (content == null)
|
||||
return;
|
||||
|
||||
for (i = 0; i < indent * 2; i++)
|
||||
buf.append(' ');
|
||||
|
||||
buf.append("<");
|
||||
buf.append(tag);
|
||||
buf.append('>');
|
||||
|
||||
/* Append the content, but escape for XML by replacing
|
||||
* '&', '<', '>' and all non-ASCII characters with
|
||||
* appropriate escape sequences.
|
||||
* The Sun J2SE 1.4 reference implementation does not
|
||||
* escape non-ASCII characters. This is a bug in their
|
||||
* implementation which has been reported in the Java
|
||||
* bug parade as bug number (FIXME: Insert number here).
|
||||
*/
|
||||
for (i = 0; i < content.length(); i++)
|
||||
{
|
||||
char c = content.charAt(i);
|
||||
switch (c)
|
||||
{
|
||||
case '&':
|
||||
buf.append("&");
|
||||
break;
|
||||
|
||||
case '<':
|
||||
buf.append("<");
|
||||
break;
|
||||
|
||||
case '>':
|
||||
buf.append(">");
|
||||
break;
|
||||
|
||||
default:
|
||||
if (((c >= 0x20) && (c <= 0x7e))
|
||||
|| (c == /* line feed */ 10)
|
||||
|| (c == /* carriage return */ 13))
|
||||
buf.append(c);
|
||||
else
|
||||
{
|
||||
buf.append("&#");
|
||||
buf.append((int) c);
|
||||
buf.append(';');
|
||||
}
|
||||
break;
|
||||
} /* switch (c) */
|
||||
} /* for i */
|
||||
|
||||
buf.append("</");
|
||||
buf.append(tag);
|
||||
buf.append(">");
|
||||
buf.append(lineSep);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Appends a line consisting of indentation, opening element tag,
|
||||
* numeric element content, closing element tag and line separator
|
||||
* to a StringBuffer.
|
||||
*
|
||||
* @param buf the StringBuffer to which the line will be appended.
|
||||
*
|
||||
* @param indent the indentation level.
|
||||
*
|
||||
* @param tag the element tag name, for instance <code>method</code>.
|
||||
*
|
||||
* @param content the element content.
|
||||
*/
|
||||
private static final void appendTag(StringBuffer buf,
|
||||
int indent,
|
||||
String tag,
|
||||
long content)
|
||||
{
|
||||
appendTag(buf, indent, tag, Long.toString(content));
|
||||
}
|
||||
|
||||
|
||||
public String format(LogRecord record)
|
||||
{
|
||||
StringBuffer buf = new StringBuffer(400);
|
||||
Level level = record.getLevel();
|
||||
long millis = record.getMillis();
|
||||
Object[] params = record.getParameters();
|
||||
ResourceBundle bundle = record.getResourceBundle();
|
||||
String key, message;
|
||||
|
||||
buf.append("<record>");
|
||||
buf.append(lineSep);
|
||||
|
||||
|
||||
appendTag(buf, 1, "date", iso8601.format(new Date(millis)));
|
||||
appendTag(buf, 1, "millis", record.getMillis());
|
||||
appendTag(buf, 1, "sequence", record.getSequenceNumber());
|
||||
appendTag(buf, 1, "logger", record.getLoggerName());
|
||||
|
||||
if (level.isStandardLevel())
|
||||
appendTag(buf, 1, "level", level.toString());
|
||||
else
|
||||
appendTag(buf, 1, "level", level.intValue());
|
||||
|
||||
appendTag(buf, 1, "class", record.getSourceClassName());
|
||||
appendTag(buf, 1, "method", record.getSourceMethodName());
|
||||
appendTag(buf, 1, "thread", record.getThreadID());
|
||||
|
||||
/* The Sun J2SE 1.4 reference implementation does not emit the
|
||||
* message in localized form. This is in violation of the API
|
||||
* specification. The GNU Classpath implementation intentionally
|
||||
* replicates the buggy behavior of the Sun implementation, as
|
||||
* different log files might be a big nuisance to users.
|
||||
*/
|
||||
try
|
||||
{
|
||||
record.setResourceBundle(null);
|
||||
message = formatMessage(record);
|
||||
}
|
||||
finally
|
||||
{
|
||||
record.setResourceBundle(bundle);
|
||||
}
|
||||
appendTag(buf, 1, "message", message);
|
||||
|
||||
/* The Sun J2SE 1.4 reference implementation does not
|
||||
* emit key, catalog and param tags. This is in violation
|
||||
* of the API specification. The Classpath implementation
|
||||
* intentionally replicates the buggy behavior of the
|
||||
* Sun implementation, as different log files might be
|
||||
* a big nuisance to users.
|
||||
*
|
||||
* FIXME: File a bug report with Sun. Insert bug number here.
|
||||
*
|
||||
*
|
||||
* key = record.getMessage();
|
||||
* if (key == null)
|
||||
* key = "";
|
||||
*
|
||||
* if ((bundle != null) && !key.equals(message))
|
||||
* {
|
||||
* appendTag(buf, 1, "key", key);
|
||||
* appendTag(buf, 1, "catalog", record.getResourceBundleName());
|
||||
* }
|
||||
*
|
||||
* if (params != null)
|
||||
* {
|
||||
* for (int i = 0; i < params.length; i++)
|
||||
* appendTag(buf, 1, "param", params[i].toString());
|
||||
* }
|
||||
*/
|
||||
|
||||
/* FIXME: We have no way to obtain the stacktrace before free JVMs
|
||||
* support the corresponding method in java.lang.Throwable. Well,
|
||||
* it would be possible to parse the output of printStackTrace,
|
||||
* but this would be pretty kludgy. Instead, we postpose the
|
||||
* implementation until Throwable has made progress.
|
||||
*/
|
||||
Throwable thrown = record.getThrown();
|
||||
if (thrown != null)
|
||||
{
|
||||
buf.append(" <exception>");
|
||||
buf.append(lineSep);
|
||||
|
||||
/* The API specification is not clear about what exactly
|
||||
* goes into the XML record for a thrown exception: It
|
||||
* could be the result of getMessage(), getLocalizedMessage(),
|
||||
* or toString(). Therefore, it was necessary to write a
|
||||
* Mauve testlet and run it with the Sun J2SE 1.4 reference
|
||||
* implementation. It turned out that the we need to call
|
||||
* toString().
|
||||
*
|
||||
* FIXME: File a bug report with Sun, asking for clearer
|
||||
* specs.
|
||||
*/
|
||||
appendTag(buf, 2, "message", thrown.toString());
|
||||
|
||||
/* FIXME: The Logging DTD specifies:
|
||||
*
|
||||
* <!ELEMENT exception (message?, frame+)>
|
||||
*
|
||||
* However, java.lang.Throwable.getStackTrace() is
|
||||
* allowed to return an empty array. So, what frame should
|
||||
* be emitted for an empty stack trace? We probably
|
||||
* should file a bug report with Sun, asking for the DTD
|
||||
* to be changed.
|
||||
*/
|
||||
|
||||
buf.append(" </exception>");
|
||||
buf.append(lineSep);
|
||||
}
|
||||
|
||||
|
||||
buf.append("</record>");
|
||||
buf.append(lineSep);
|
||||
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns a string that handlers are supposed to emit before
|
||||
* the first log record. The base implementation returns an
|
||||
* empty string, but subclasses such as {@link XMLFormatter}
|
||||
* override this method in order to provide a suitable header.
|
||||
*
|
||||
* @return a string for the header.
|
||||
*
|
||||
* @param handler the handler which will prepend the returned
|
||||
* string in front of the first log record. This method
|
||||
* will inspect certain properties of the handler, for
|
||||
* example its encoding, in order to construct the header.
|
||||
*/
|
||||
public String getHead(Handler h)
|
||||
{
|
||||
StringBuffer buf;
|
||||
String encoding;
|
||||
|
||||
buf = new StringBuffer(80);
|
||||
buf.append("<?xml version=\"1.0\" encoding=\"");
|
||||
|
||||
encoding = h.getEncoding();
|
||||
|
||||
/* file.encoding is a system property with the Sun JVM, indicating
|
||||
* the platform-default file encoding. Unfortunately, the API
|
||||
* specification for java.lang.System.getProperties() does not
|
||||
* list this property.
|
||||
*/
|
||||
if (encoding == null)
|
||||
encoding = System.getProperty("file.encoding");
|
||||
|
||||
/* Since file.encoding is not listed with the API specification of
|
||||
* java.lang.System.getProperties(), there might be some VMs that
|
||||
* do not define this system property. Therefore, we use UTF-8 as
|
||||
* a reasonable default. Please note that if the platform encoding
|
||||
* uses the same codepoints as US-ASCII for the US-ASCII character
|
||||
* set (e.g, 65 for A), it does not matter whether we emit the
|
||||
* wrong encoding into the XML header -- the GNU Classpath will
|
||||
* emit XML escape sequences like Ӓ for any non-ASCII
|
||||
* character. Virtually all character encodings use the same code
|
||||
* points as US-ASCII for ASCII characters. Probably, EBCDIC is
|
||||
* the only exception.
|
||||
*/
|
||||
if (encoding == null)
|
||||
encoding = "UTF-8";
|
||||
|
||||
/* On Windows XP localized for Swiss German (this is one of
|
||||
* my [Sascha Brawer's] test machines), the default encoding
|
||||
* has the canonical name "windows-1252". The "historical" name
|
||||
* of this encoding is "Cp1252" (see the Javadoc for the class
|
||||
* java.nio.charset.Charset for the distinction). Now, that class
|
||||
* does have a method for mapping historical to canonical encoding
|
||||
* names. However, if we used it here, we would be come dependent
|
||||
* on java.nio.*, which was only introduced with J2SE 1.4.
|
||||
* Thus, we do this little hack here. As soon as Classpath supports
|
||||
* java.nio.charset.CharSet, this hack should be replaced by
|
||||
* code that correctly canonicalizes the encoding name.
|
||||
*/
|
||||
if ((encoding.length() > 2) && encoding.startsWith("Cp"))
|
||||
encoding = "windows-" + encoding.substring(2);
|
||||
|
||||
buf.append(encoding);
|
||||
|
||||
buf.append("\" standalone=\"no\"?>");
|
||||
buf.append(lineSep);
|
||||
|
||||
/* SYSTEM is not a fully qualified URL so that validating
|
||||
* XML parsers do not need to connect to the Internet in
|
||||
* order to read in a log file. See also the Sun Bug Parade,
|
||||
* bug #4372790, "Logging APIs: need to use relative URL for XML
|
||||
* doctype".
|
||||
*/
|
||||
buf.append("<!DOCTYPE log SYSTEM \"logger.dtd\">");
|
||||
buf.append(lineSep);
|
||||
buf.append("<log>");
|
||||
buf.append(lineSep);
|
||||
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
|
||||
public String getTail(Handler h)
|
||||
{
|
||||
return "</log>" + lineSep;
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user