feat(jdk8): move files to new folder to avoid resources compiled.
This commit is contained in:
129
jdkSrc/jdk8/java/util/logging/ConsoleHandler.java
Normal file
129
jdkSrc/jdk8/java/util/logging/ConsoleHandler.java
Normal file
@@ -0,0 +1,129 @@
|
||||
/*
|
||||
* Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code 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
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
|
||||
package java.util.logging;
|
||||
|
||||
/**
|
||||
* This <tt>Handler</tt> publishes log records to <tt>System.err</tt>.
|
||||
* By default the <tt>SimpleFormatter</tt> is used to generate brief summaries.
|
||||
* <p>
|
||||
* <b>Configuration:</b>
|
||||
* By default each <tt>ConsoleHandler</tt> is initialized using the following
|
||||
* <tt>LogManager</tt> configuration properties where {@code <handler-name>}
|
||||
* refers to the fully-qualified class name of the handler.
|
||||
* If properties are not defined
|
||||
* (or have invalid values) then the specified default values are used.
|
||||
* <ul>
|
||||
* <li> <handler-name>.level
|
||||
* specifies the default level for the <tt>Handler</tt>
|
||||
* (defaults to <tt>Level.INFO</tt>). </li>
|
||||
* <li> <handler-name>.filter
|
||||
* specifies the name of a <tt>Filter</tt> class to use
|
||||
* (defaults to no <tt>Filter</tt>). </li>
|
||||
* <li> <handler-name>.formatter
|
||||
* specifies the name of a <tt>Formatter</tt> class to use
|
||||
* (defaults to <tt>java.util.logging.SimpleFormatter</tt>). </li>
|
||||
* <li> <handler-name>.encoding
|
||||
* the name of the character set encoding to use (defaults to
|
||||
* the default platform encoding). </li>
|
||||
* </ul>
|
||||
* <p>
|
||||
* For example, the properties for {@code ConsoleHandler} would be:
|
||||
* <ul>
|
||||
* <li> java.util.logging.ConsoleHandler.level=INFO </li>
|
||||
* <li> java.util.logging.ConsoleHandler.formatter=java.util.logging.SimpleFormatter </li>
|
||||
* </ul>
|
||||
* <p>
|
||||
* For a custom handler, e.g. com.foo.MyHandler, the properties would be:
|
||||
* <ul>
|
||||
* <li> com.foo.MyHandler.level=INFO </li>
|
||||
* <li> com.foo.MyHandler.formatter=java.util.logging.SimpleFormatter </li>
|
||||
* </ul>
|
||||
* <p>
|
||||
* @since 1.4
|
||||
*/
|
||||
public class ConsoleHandler extends StreamHandler {
|
||||
// Private method to configure a ConsoleHandler from LogManager
|
||||
// properties and/or default values as specified in the class
|
||||
// javadoc.
|
||||
private void configure() {
|
||||
LogManager manager = LogManager.getLogManager();
|
||||
String cname = getClass().getName();
|
||||
|
||||
setLevel(manager.getLevelProperty(cname +".level", Level.INFO));
|
||||
setFilter(manager.getFilterProperty(cname +".filter", null));
|
||||
setFormatter(manager.getFormatterProperty(cname +".formatter", new SimpleFormatter()));
|
||||
try {
|
||||
setEncoding(manager.getStringProperty(cname +".encoding", null));
|
||||
} catch (Exception ex) {
|
||||
try {
|
||||
setEncoding(null);
|
||||
} catch (Exception ex2) {
|
||||
// doing a setEncoding with null should always work.
|
||||
// assert false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a <tt>ConsoleHandler</tt> for <tt>System.err</tt>.
|
||||
* <p>
|
||||
* The <tt>ConsoleHandler</tt> is configured based on
|
||||
* <tt>LogManager</tt> properties (or their default values).
|
||||
*
|
||||
*/
|
||||
public ConsoleHandler() {
|
||||
sealed = false;
|
||||
configure();
|
||||
setOutputStream(System.err);
|
||||
sealed = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Publish a <tt>LogRecord</tt>.
|
||||
* <p>
|
||||
* The logging request was made initially to a <tt>Logger</tt> object,
|
||||
* which initialized the <tt>LogRecord</tt> and forwarded it here.
|
||||
* <p>
|
||||
* @param record description of the log event. A null record is
|
||||
* silently ignored and is not published
|
||||
*/
|
||||
@Override
|
||||
public void publish(LogRecord record) {
|
||||
super.publish(record);
|
||||
flush();
|
||||
}
|
||||
|
||||
/**
|
||||
* Override <tt>StreamHandler.close</tt> to do a flush but not
|
||||
* to close the output stream. That is, we do <b>not</b>
|
||||
* close <tt>System.err</tt>.
|
||||
*/
|
||||
@Override
|
||||
public void close() {
|
||||
flush();
|
||||
}
|
||||
}
|
||||
99
jdkSrc/jdk8/java/util/logging/ErrorManager.java
Normal file
99
jdkSrc/jdk8/java/util/logging/ErrorManager.java
Normal file
@@ -0,0 +1,99 @@
|
||||
/*
|
||||
* Copyright (c) 2001, 2004, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code 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
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
|
||||
package java.util.logging;
|
||||
|
||||
/**
|
||||
* ErrorManager objects can be attached to Handlers to process
|
||||
* any error that occurs on a Handler during Logging.
|
||||
* <p>
|
||||
* When processing logging output, if a Handler encounters problems
|
||||
* then rather than throwing an Exception back to the issuer of
|
||||
* the logging call (who is unlikely to be interested) the Handler
|
||||
* should call its associated ErrorManager.
|
||||
*/
|
||||
|
||||
public class ErrorManager {
|
||||
private boolean reported = false;
|
||||
|
||||
/*
|
||||
* We declare standard error codes for important categories of errors.
|
||||
*/
|
||||
|
||||
/**
|
||||
* GENERIC_FAILURE is used for failure that don't fit
|
||||
* into one of the other categories.
|
||||
*/
|
||||
public final static int GENERIC_FAILURE = 0;
|
||||
/**
|
||||
* WRITE_FAILURE is used when a write to an output stream fails.
|
||||
*/
|
||||
public final static int WRITE_FAILURE = 1;
|
||||
/**
|
||||
* FLUSH_FAILURE is used when a flush to an output stream fails.
|
||||
*/
|
||||
public final static int FLUSH_FAILURE = 2;
|
||||
/**
|
||||
* CLOSE_FAILURE is used when a close of an output stream fails.
|
||||
*/
|
||||
public final static int CLOSE_FAILURE = 3;
|
||||
/**
|
||||
* OPEN_FAILURE is used when an open of an output stream fails.
|
||||
*/
|
||||
public final static int OPEN_FAILURE = 4;
|
||||
/**
|
||||
* FORMAT_FAILURE is used when formatting fails for any reason.
|
||||
*/
|
||||
public final static int FORMAT_FAILURE = 5;
|
||||
|
||||
/**
|
||||
* The error method is called when a Handler failure occurs.
|
||||
* <p>
|
||||
* This method may be overridden in subclasses. The default
|
||||
* behavior in this base class is that the first call is
|
||||
* reported to System.err, and subsequent calls are ignored.
|
||||
*
|
||||
* @param msg a descriptive string (may be null)
|
||||
* @param ex an exception (may be null)
|
||||
* @param code an error code defined in ErrorManager
|
||||
*/
|
||||
public synchronized void error(String msg, Exception ex, int code) {
|
||||
if (reported) {
|
||||
// We only report the first error, to avoid clogging
|
||||
// the screen.
|
||||
return;
|
||||
}
|
||||
reported = true;
|
||||
String text = "java.util.logging.ErrorManager: " + code;
|
||||
if (msg != null) {
|
||||
text = text + ": " + msg;
|
||||
}
|
||||
System.err.println(text);
|
||||
if (ex != null) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
775
jdkSrc/jdk8/java/util/logging/FileHandler.java
Normal file
775
jdkSrc/jdk8/java/util/logging/FileHandler.java
Normal file
@@ -0,0 +1,775 @@
|
||||
/*
|
||||
* Copyright (c) 2000, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code 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
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package java.util.logging;
|
||||
|
||||
import static java.nio.file.StandardOpenOption.APPEND;
|
||||
import static java.nio.file.StandardOpenOption.CREATE_NEW;
|
||||
import static java.nio.file.StandardOpenOption.WRITE;
|
||||
|
||||
import java.io.BufferedOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.nio.channels.FileChannel;
|
||||
import java.nio.channels.OverlappingFileLockException;
|
||||
import java.nio.file.AccessDeniedException;
|
||||
import java.nio.file.FileAlreadyExistsException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.LinkOption;
|
||||
import java.nio.file.NoSuchFileException;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.security.AccessController;
|
||||
import java.security.PrivilegedAction;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Simple file logging <tt>Handler</tt>.
|
||||
* <p>
|
||||
* The <tt>FileHandler</tt> can either write to a specified file,
|
||||
* or it can write to a rotating set of files.
|
||||
* <p>
|
||||
* For a rotating set of files, as each file reaches a given size
|
||||
* limit, it is closed, rotated out, and a new file opened.
|
||||
* Successively older files are named by adding "0", "1", "2",
|
||||
* etc. into the base filename.
|
||||
* <p>
|
||||
* By default buffering is enabled in the IO libraries but each log
|
||||
* record is flushed out when it is complete.
|
||||
* <p>
|
||||
* By default the <tt>XMLFormatter</tt> class is used for formatting.
|
||||
* <p>
|
||||
* <b>Configuration:</b>
|
||||
* By default each <tt>FileHandler</tt> is initialized using the following
|
||||
* <tt>LogManager</tt> configuration properties where <tt><handler-name></tt>
|
||||
* refers to the fully-qualified class name of the handler.
|
||||
* If properties are not defined
|
||||
* (or have invalid values) then the specified default values are used.
|
||||
* <ul>
|
||||
* <li> <handler-name>.level
|
||||
* specifies the default level for the <tt>Handler</tt>
|
||||
* (defaults to <tt>Level.ALL</tt>). </li>
|
||||
* <li> <handler-name>.filter
|
||||
* specifies the name of a <tt>Filter</tt> class to use
|
||||
* (defaults to no <tt>Filter</tt>). </li>
|
||||
* <li> <handler-name>.formatter
|
||||
* specifies the name of a <tt>Formatter</tt> class to use
|
||||
* (defaults to <tt>java.util.logging.XMLFormatter</tt>) </li>
|
||||
* <li> <handler-name>.encoding
|
||||
* the name of the character set encoding to use (defaults to
|
||||
* the default platform encoding). </li>
|
||||
* <li> <handler-name>.limit
|
||||
* specifies an approximate maximum amount to write (in bytes)
|
||||
* to any one file. If this is zero, then there is no limit.
|
||||
* (Defaults to no limit). </li>
|
||||
* <li> <handler-name>.count
|
||||
* specifies how many output files to cycle through (defaults to 1). </li>
|
||||
* <li> <handler-name>.pattern
|
||||
* specifies a pattern for generating the output file name. See
|
||||
* below for details. (Defaults to "%h/java%u.log"). </li>
|
||||
* <li> <handler-name>.append
|
||||
* specifies whether the FileHandler should append onto
|
||||
* any existing files (defaults to false). </li>
|
||||
* </ul>
|
||||
* <p>
|
||||
* For example, the properties for {@code FileHandler} would be:
|
||||
* <ul>
|
||||
* <li> java.util.logging.FileHandler.level=INFO </li>
|
||||
* <li> java.util.logging.FileHandler.formatter=java.util.logging.SimpleFormatter </li>
|
||||
* </ul>
|
||||
* <p>
|
||||
* For a custom handler, e.g. com.foo.MyHandler, the properties would be:
|
||||
* <ul>
|
||||
* <li> com.foo.MyHandler.level=INFO </li>
|
||||
* <li> com.foo.MyHandler.formatter=java.util.logging.SimpleFormatter </li>
|
||||
* </ul>
|
||||
* <p>
|
||||
* A pattern consists of a string that includes the following special
|
||||
* components that will be replaced at runtime:
|
||||
* <ul>
|
||||
* <li> "/" the local pathname separator </li>
|
||||
* <li> "%t" the system temporary directory </li>
|
||||
* <li> "%h" the value of the "user.home" system property </li>
|
||||
* <li> "%g" the generation number to distinguish rotated logs </li>
|
||||
* <li> "%u" a unique number to resolve conflicts </li>
|
||||
* <li> "%%" translates to a single percent sign "%" </li>
|
||||
* </ul>
|
||||
* If no "%g" field has been specified and the file count is greater
|
||||
* than one, then the generation number will be added to the end of
|
||||
* the generated filename, after a dot.
|
||||
* <p>
|
||||
* Thus for example a pattern of "%t/java%g.log" with a count of 2
|
||||
* would typically cause log files to be written on Solaris to
|
||||
* /var/tmp/java0.log and /var/tmp/java1.log whereas on Windows 95 they
|
||||
* would be typically written to C:\TEMP\java0.log and C:\TEMP\java1.log
|
||||
* <p>
|
||||
* Generation numbers follow the sequence 0, 1, 2, etc.
|
||||
* <p>
|
||||
* Normally the "%u" unique field is set to 0. However, if the <tt>FileHandler</tt>
|
||||
* tries to open the filename and finds the file is currently in use by
|
||||
* another process it will increment the unique number field and try
|
||||
* again. This will be repeated until <tt>FileHandler</tt> finds a file name that
|
||||
* is not currently in use. If there is a conflict and no "%u" field has
|
||||
* been specified, it will be added at the end of the filename after a dot.
|
||||
* (This will be after any automatically added generation number.)
|
||||
* <p>
|
||||
* Thus if three processes were all trying to log to fred%u.%g.txt then
|
||||
* they might end up using fred0.0.txt, fred1.0.txt, fred2.0.txt as
|
||||
* the first file in their rotating sequences.
|
||||
* <p>
|
||||
* Note that the use of unique ids to avoid conflicts is only guaranteed
|
||||
* to work reliably when using a local disk file system.
|
||||
*
|
||||
* @since 1.4
|
||||
*/
|
||||
|
||||
public class FileHandler extends StreamHandler {
|
||||
private MeteredStream meter;
|
||||
private boolean append;
|
||||
private int limit; // zero => no limit.
|
||||
private int count;
|
||||
private String pattern;
|
||||
private String lockFileName;
|
||||
private FileChannel lockFileChannel;
|
||||
private File files[];
|
||||
private static final int DEFAULT_MAX_LOCKS = 100;
|
||||
private static int maxLocks;
|
||||
private static final Set<String> locks = new HashSet<>();
|
||||
|
||||
/*
|
||||
* Initialize maxLocks from the System property if set.
|
||||
* If invalid/no property is provided 100 will be used as a default value.
|
||||
*/
|
||||
static {
|
||||
maxLocks = java.security.AccessController.doPrivileged(
|
||||
(PrivilegedAction<Integer>) () ->
|
||||
Integer.getInteger(
|
||||
"jdk.internal.FileHandlerLogging.maxLocks",
|
||||
DEFAULT_MAX_LOCKS)
|
||||
);
|
||||
|
||||
if (maxLocks <= 0) {
|
||||
maxLocks = DEFAULT_MAX_LOCKS;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A metered stream is a subclass of OutputStream that
|
||||
* (a) forwards all its output to a target stream
|
||||
* (b) keeps track of how many bytes have been written
|
||||
*/
|
||||
private class MeteredStream extends OutputStream {
|
||||
final OutputStream out;
|
||||
int written;
|
||||
|
||||
MeteredStream(OutputStream out, int written) {
|
||||
this.out = out;
|
||||
this.written = written;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(int b) throws IOException {
|
||||
out.write(b);
|
||||
written++;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(byte buff[]) throws IOException {
|
||||
out.write(buff);
|
||||
written += buff.length;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(byte buff[], int off, int len) throws IOException {
|
||||
out.write(buff,off,len);
|
||||
written += len;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void flush() throws IOException {
|
||||
out.flush();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() throws IOException {
|
||||
out.close();
|
||||
}
|
||||
}
|
||||
|
||||
private void open(File fname, boolean append) throws IOException {
|
||||
int len = 0;
|
||||
if (append) {
|
||||
len = (int)fname.length();
|
||||
}
|
||||
FileOutputStream fout = new FileOutputStream(fname.toString(), append);
|
||||
BufferedOutputStream bout = new BufferedOutputStream(fout);
|
||||
meter = new MeteredStream(bout, len);
|
||||
setOutputStream(meter);
|
||||
}
|
||||
|
||||
/**
|
||||
* Configure a FileHandler from LogManager properties and/or default values
|
||||
* as specified in the class javadoc.
|
||||
*/
|
||||
private void configure() {
|
||||
LogManager manager = LogManager.getLogManager();
|
||||
|
||||
String cname = getClass().getName();
|
||||
|
||||
pattern = manager.getStringProperty(cname + ".pattern", "%h/java%u.log");
|
||||
limit = manager.getIntProperty(cname + ".limit", 0);
|
||||
if (limit < 0) {
|
||||
limit = 0;
|
||||
}
|
||||
count = manager.getIntProperty(cname + ".count", 1);
|
||||
if (count <= 0) {
|
||||
count = 1;
|
||||
}
|
||||
append = manager.getBooleanProperty(cname + ".append", false);
|
||||
setLevel(manager.getLevelProperty(cname + ".level", Level.ALL));
|
||||
setFilter(manager.getFilterProperty(cname + ".filter", null));
|
||||
setFormatter(manager.getFormatterProperty(cname + ".formatter", new XMLFormatter()));
|
||||
try {
|
||||
setEncoding(manager.getStringProperty(cname +".encoding", null));
|
||||
} catch (Exception ex) {
|
||||
try {
|
||||
setEncoding(null);
|
||||
} catch (Exception ex2) {
|
||||
// doing a setEncoding with null should always work.
|
||||
// assert false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Construct a default <tt>FileHandler</tt>. This will be configured
|
||||
* entirely from <tt>LogManager</tt> properties (or their default values).
|
||||
* <p>
|
||||
* @exception IOException if there are IO problems opening the files.
|
||||
* @exception SecurityException if a security manager exists and if
|
||||
* the caller does not have <tt>LoggingPermission("control"))</tt>.
|
||||
* @exception NullPointerException if pattern property is an empty String.
|
||||
*/
|
||||
public FileHandler() throws IOException, SecurityException {
|
||||
checkPermission();
|
||||
configure();
|
||||
openFiles();
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize a <tt>FileHandler</tt> to write to the given filename.
|
||||
* <p>
|
||||
* The <tt>FileHandler</tt> is configured based on <tt>LogManager</tt>
|
||||
* properties (or their default values) except that the given pattern
|
||||
* argument is used as the filename pattern, the file limit is
|
||||
* set to no limit, and the file count is set to one.
|
||||
* <p>
|
||||
* There is no limit on the amount of data that may be written,
|
||||
* so use this with care.
|
||||
*
|
||||
* @param pattern the name of the output file
|
||||
* @exception IOException if there are IO problems opening the files.
|
||||
* @exception SecurityException if a security manager exists and if
|
||||
* the caller does not have <tt>LoggingPermission("control")</tt>.
|
||||
* @exception IllegalArgumentException if pattern is an empty string
|
||||
*/
|
||||
public FileHandler(String pattern) throws IOException, SecurityException {
|
||||
if (pattern.length() < 1 ) {
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
checkPermission();
|
||||
configure();
|
||||
this.pattern = pattern;
|
||||
this.limit = 0;
|
||||
this.count = 1;
|
||||
openFiles();
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize a <tt>FileHandler</tt> to write to the given filename,
|
||||
* with optional append.
|
||||
* <p>
|
||||
* The <tt>FileHandler</tt> is configured based on <tt>LogManager</tt>
|
||||
* properties (or their default values) except that the given pattern
|
||||
* argument is used as the filename pattern, the file limit is
|
||||
* set to no limit, the file count is set to one, and the append
|
||||
* mode is set to the given <tt>append</tt> argument.
|
||||
* <p>
|
||||
* There is no limit on the amount of data that may be written,
|
||||
* so use this with care.
|
||||
*
|
||||
* @param pattern the name of the output file
|
||||
* @param append specifies append mode
|
||||
* @exception IOException if there are IO problems opening the files.
|
||||
* @exception SecurityException if a security manager exists and if
|
||||
* the caller does not have <tt>LoggingPermission("control")</tt>.
|
||||
* @exception IllegalArgumentException if pattern is an empty string
|
||||
*/
|
||||
public FileHandler(String pattern, boolean append) throws IOException,
|
||||
SecurityException {
|
||||
if (pattern.length() < 1 ) {
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
checkPermission();
|
||||
configure();
|
||||
this.pattern = pattern;
|
||||
this.limit = 0;
|
||||
this.count = 1;
|
||||
this.append = append;
|
||||
openFiles();
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize a <tt>FileHandler</tt> to write to a set of files. When
|
||||
* (approximately) the given limit has been written to one file,
|
||||
* another file will be opened. The output will cycle through a set
|
||||
* of count files.
|
||||
* <p>
|
||||
* The <tt>FileHandler</tt> is configured based on <tt>LogManager</tt>
|
||||
* properties (or their default values) except that the given pattern
|
||||
* argument is used as the filename pattern, the file limit is
|
||||
* set to the limit argument, and the file count is set to the
|
||||
* given count argument.
|
||||
* <p>
|
||||
* The count must be at least 1.
|
||||
*
|
||||
* @param pattern the pattern for naming the output file
|
||||
* @param limit the maximum number of bytes to write to any one file
|
||||
* @param count the number of files to use
|
||||
* @exception IOException if there are IO problems opening the files.
|
||||
* @exception SecurityException if a security manager exists and if
|
||||
* the caller does not have <tt>LoggingPermission("control")</tt>.
|
||||
* @exception IllegalArgumentException if {@code limit < 0}, or {@code count < 1}.
|
||||
* @exception IllegalArgumentException if pattern is an empty string
|
||||
*/
|
||||
public FileHandler(String pattern, int limit, int count)
|
||||
throws IOException, SecurityException {
|
||||
if (limit < 0 || count < 1 || pattern.length() < 1) {
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
checkPermission();
|
||||
configure();
|
||||
this.pattern = pattern;
|
||||
this.limit = limit;
|
||||
this.count = count;
|
||||
openFiles();
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize a <tt>FileHandler</tt> to write to a set of files
|
||||
* with optional append. When (approximately) the given limit has
|
||||
* been written to one file, another file will be opened. The
|
||||
* output will cycle through a set of count files.
|
||||
* <p>
|
||||
* The <tt>FileHandler</tt> is configured based on <tt>LogManager</tt>
|
||||
* properties (or their default values) except that the given pattern
|
||||
* argument is used as the filename pattern, the file limit is
|
||||
* set to the limit argument, and the file count is set to the
|
||||
* given count argument, and the append mode is set to the given
|
||||
* <tt>append</tt> argument.
|
||||
* <p>
|
||||
* The count must be at least 1.
|
||||
*
|
||||
* @param pattern the pattern for naming the output file
|
||||
* @param limit the maximum number of bytes to write to any one file
|
||||
* @param count the number of files to use
|
||||
* @param append specifies append mode
|
||||
* @exception IOException if there are IO problems opening the files.
|
||||
* @exception SecurityException if a security manager exists and if
|
||||
* the caller does not have <tt>LoggingPermission("control")</tt>.
|
||||
* @exception IllegalArgumentException if {@code limit < 0}, or {@code count < 1}.
|
||||
* @exception IllegalArgumentException if pattern is an empty string
|
||||
*
|
||||
*/
|
||||
public FileHandler(String pattern, int limit, int count, boolean append)
|
||||
throws IOException, SecurityException {
|
||||
if (limit < 0 || count < 1 || pattern.length() < 1) {
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
checkPermission();
|
||||
configure();
|
||||
this.pattern = pattern;
|
||||
this.limit = limit;
|
||||
this.count = count;
|
||||
this.append = append;
|
||||
openFiles();
|
||||
}
|
||||
|
||||
private boolean isParentWritable(Path path) {
|
||||
Path parent = path.getParent();
|
||||
if (parent == null) {
|
||||
parent = path.toAbsolutePath().getParent();
|
||||
}
|
||||
return parent != null && Files.isWritable(parent);
|
||||
}
|
||||
|
||||
/**
|
||||
* Open the set of output files, based on the configured
|
||||
* instance variables.
|
||||
*/
|
||||
private void openFiles() throws IOException {
|
||||
LogManager manager = LogManager.getLogManager();
|
||||
manager.checkPermission();
|
||||
if (count < 1) {
|
||||
throw new IllegalArgumentException("file count = " + count);
|
||||
}
|
||||
if (limit < 0) {
|
||||
limit = 0;
|
||||
}
|
||||
|
||||
// We register our own ErrorManager during initialization
|
||||
// so we can record exceptions.
|
||||
InitializationErrorManager em = new InitializationErrorManager();
|
||||
setErrorManager(em);
|
||||
|
||||
// Create a lock file. This grants us exclusive access
|
||||
// to our set of output files, as long as we are alive.
|
||||
int unique = -1;
|
||||
for (;;) {
|
||||
unique++;
|
||||
if (unique > maxLocks) {
|
||||
throw new IOException("Couldn't get lock for " + pattern
|
||||
+ ", maxLocks: " + maxLocks);
|
||||
}
|
||||
// Generate a lock file name from the "unique" int.
|
||||
lockFileName = generate(pattern, 0, unique).toString() + ".lck";
|
||||
// Now try to lock that filename.
|
||||
// Because some systems (e.g., Solaris) can only do file locks
|
||||
// between processes (and not within a process), we first check
|
||||
// if we ourself already have the file locked.
|
||||
synchronized(locks) {
|
||||
if (locks.contains(lockFileName)) {
|
||||
// We already own this lock, for a different FileHandler
|
||||
// object. Try again.
|
||||
continue;
|
||||
}
|
||||
|
||||
final Path lockFilePath = Paths.get(lockFileName);
|
||||
FileChannel channel = null;
|
||||
int retries = -1;
|
||||
boolean fileCreated = false;
|
||||
while (channel == null && retries++ < 1) {
|
||||
try {
|
||||
channel = FileChannel.open(lockFilePath,
|
||||
CREATE_NEW, WRITE);
|
||||
fileCreated = true;
|
||||
} catch (AccessDeniedException ade) {
|
||||
// This can be either a temporary, or a more permanent issue.
|
||||
// The lock file might be still pending deletion from a previous run
|
||||
// (temporary), or the parent directory might not be accessible,
|
||||
// not writable, etc..
|
||||
// If we can write to the current directory, and this is a regular file,
|
||||
// let's try again.
|
||||
if (Files.isRegularFile(lockFilePath, LinkOption.NOFOLLOW_LINKS)
|
||||
&& isParentWritable(lockFilePath)) {
|
||||
// Try again. If it doesn't work, then this will
|
||||
// eventually ensure that we increment "unique" and
|
||||
// use another file name.
|
||||
continue;
|
||||
} else {
|
||||
throw ade; // no need to retry
|
||||
}
|
||||
} catch (FileAlreadyExistsException ix) {
|
||||
// This may be a zombie file left over by a previous
|
||||
// execution. Reuse it - but only if we can actually
|
||||
// write to its directory.
|
||||
// Note that this is a situation that may happen,
|
||||
// but not too frequently.
|
||||
if (Files.isRegularFile(lockFilePath, LinkOption.NOFOLLOW_LINKS)
|
||||
&& isParentWritable(lockFilePath)) {
|
||||
try {
|
||||
channel = FileChannel.open(lockFilePath,
|
||||
WRITE, APPEND);
|
||||
} catch (NoSuchFileException x) {
|
||||
// Race condition - retry once, and if that
|
||||
// fails again just try the next name in
|
||||
// the sequence.
|
||||
continue;
|
||||
} catch(IOException x) {
|
||||
// the file may not be writable for us.
|
||||
// try the next name in the sequence
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
// at this point channel should still be null.
|
||||
// break and try the next name in the sequence.
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (channel == null) continue; // try the next name;
|
||||
lockFileChannel = channel;
|
||||
|
||||
boolean available;
|
||||
try {
|
||||
available = lockFileChannel.tryLock() != null;
|
||||
// We got the lock OK.
|
||||
// At this point we could call File.deleteOnExit().
|
||||
// However, this could have undesirable side effects
|
||||
// as indicated by JDK-4872014. So we will instead
|
||||
// rely on the fact that close() will remove the lock
|
||||
// file and that whoever is creating FileHandlers should
|
||||
// be responsible for closing them.
|
||||
} catch (IOException ix) {
|
||||
// We got an IOException while trying to get the lock.
|
||||
// This normally indicates that locking is not supported
|
||||
// on the target directory. We have to proceed without
|
||||
// getting a lock. Drop through, but only if we did
|
||||
// create the file...
|
||||
available = fileCreated;
|
||||
} catch (OverlappingFileLockException x) {
|
||||
// someone already locked this file in this VM, through
|
||||
// some other channel - that is - using something else
|
||||
// than new FileHandler(...);
|
||||
// continue searching for an available lock.
|
||||
available = false;
|
||||
}
|
||||
if (available) {
|
||||
// We got the lock. Remember it.
|
||||
locks.add(lockFileName);
|
||||
break;
|
||||
}
|
||||
|
||||
// We failed to get the lock. Try next file.
|
||||
lockFileChannel.close();
|
||||
}
|
||||
}
|
||||
|
||||
files = new File[count];
|
||||
for (int i = 0; i < count; i++) {
|
||||
files[i] = generate(pattern, i, unique);
|
||||
}
|
||||
|
||||
// Create the initial log file.
|
||||
if (append) {
|
||||
open(files[0], true);
|
||||
} else {
|
||||
rotate();
|
||||
}
|
||||
|
||||
// Did we detect any exceptions during initialization?
|
||||
Exception ex = em.lastException;
|
||||
if (ex != null) {
|
||||
if (ex instanceof IOException) {
|
||||
throw (IOException) ex;
|
||||
} else if (ex instanceof SecurityException) {
|
||||
throw (SecurityException) ex;
|
||||
} else {
|
||||
throw new IOException("Exception: " + ex);
|
||||
}
|
||||
}
|
||||
|
||||
// Install the normal default ErrorManager.
|
||||
setErrorManager(new ErrorManager());
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate a file based on a user-supplied pattern, generation number,
|
||||
* and an integer uniqueness suffix
|
||||
* @param pattern the pattern for naming the output file
|
||||
* @param generation the generation number to distinguish rotated logs
|
||||
* @param unique a unique number to resolve conflicts
|
||||
* @return the generated File
|
||||
* @throws IOException
|
||||
*/
|
||||
private File generate(String pattern, int generation, int unique)
|
||||
throws IOException {
|
||||
File file = null;
|
||||
String word = "";
|
||||
int ix = 0;
|
||||
boolean sawg = false;
|
||||
boolean sawu = false;
|
||||
while (ix < pattern.length()) {
|
||||
char ch = pattern.charAt(ix);
|
||||
ix++;
|
||||
char ch2 = 0;
|
||||
if (ix < pattern.length()) {
|
||||
ch2 = Character.toLowerCase(pattern.charAt(ix));
|
||||
}
|
||||
if (ch == '/') {
|
||||
if (file == null) {
|
||||
file = new File(word);
|
||||
} else {
|
||||
file = new File(file, word);
|
||||
}
|
||||
word = "";
|
||||
continue;
|
||||
} else if (ch == '%') {
|
||||
if (ch2 == 't') {
|
||||
String tmpDir = System.getProperty("java.io.tmpdir");
|
||||
if (tmpDir == null) {
|
||||
tmpDir = System.getProperty("user.home");
|
||||
}
|
||||
file = new File(tmpDir);
|
||||
ix++;
|
||||
word = "";
|
||||
continue;
|
||||
} else if (ch2 == 'h') {
|
||||
file = new File(System.getProperty("user.home"));
|
||||
if (isSetUID()) {
|
||||
// Ok, we are in a set UID program. For safety's sake
|
||||
// we disallow attempts to open files relative to %h.
|
||||
throw new IOException("can't use %h in set UID program");
|
||||
}
|
||||
ix++;
|
||||
word = "";
|
||||
continue;
|
||||
} else if (ch2 == 'g') {
|
||||
word = word + generation;
|
||||
sawg = true;
|
||||
ix++;
|
||||
continue;
|
||||
} else if (ch2 == 'u') {
|
||||
word = word + unique;
|
||||
sawu = true;
|
||||
ix++;
|
||||
continue;
|
||||
} else if (ch2 == '%') {
|
||||
word = word + "%";
|
||||
ix++;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
word = word + ch;
|
||||
}
|
||||
if (count > 1 && !sawg) {
|
||||
word = word + "." + generation;
|
||||
}
|
||||
if (unique > 0 && !sawu) {
|
||||
word = word + "." + unique;
|
||||
}
|
||||
if (word.length() > 0) {
|
||||
if (file == null) {
|
||||
file = new File(word);
|
||||
} else {
|
||||
file = new File(file, word);
|
||||
}
|
||||
}
|
||||
return file;
|
||||
}
|
||||
|
||||
/**
|
||||
* Rotate the set of output files
|
||||
*/
|
||||
private synchronized void rotate() {
|
||||
Level oldLevel = getLevel();
|
||||
setLevel(Level.OFF);
|
||||
|
||||
super.close();
|
||||
for (int i = count-2; i >= 0; i--) {
|
||||
File f1 = files[i];
|
||||
File f2 = files[i+1];
|
||||
if (f1.exists()) {
|
||||
if (f2.exists()) {
|
||||
f2.delete();
|
||||
}
|
||||
f1.renameTo(f2);
|
||||
}
|
||||
}
|
||||
try {
|
||||
open(files[0], false);
|
||||
} catch (IOException ix) {
|
||||
// We don't want to throw an exception here, but we
|
||||
// report the exception to any registered ErrorManager.
|
||||
reportError(null, ix, ErrorManager.OPEN_FAILURE);
|
||||
|
||||
}
|
||||
setLevel(oldLevel);
|
||||
}
|
||||
|
||||
/**
|
||||
* Format and publish a <tt>LogRecord</tt>.
|
||||
*
|
||||
* @param record description of the log event. A null record is
|
||||
* silently ignored and is not published
|
||||
*/
|
||||
@Override
|
||||
public synchronized void publish(LogRecord record) {
|
||||
if (!isLoggable(record)) {
|
||||
return;
|
||||
}
|
||||
super.publish(record);
|
||||
flush();
|
||||
if (limit > 0 && meter.written >= limit) {
|
||||
// We performed access checks in the "init" method to make sure
|
||||
// we are only initialized from trusted code. So we assume
|
||||
// it is OK to write the target files, even if we are
|
||||
// currently being called from untrusted code.
|
||||
// So it is safe to raise privilege here.
|
||||
AccessController.doPrivileged(new PrivilegedAction<Object>() {
|
||||
@Override
|
||||
public Object run() {
|
||||
rotate();
|
||||
return null;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Close all the files.
|
||||
*
|
||||
* @exception SecurityException if a security manager exists and if
|
||||
* the caller does not have <tt>LoggingPermission("control")</tt>.
|
||||
*/
|
||||
@Override
|
||||
public synchronized void close() throws SecurityException {
|
||||
super.close();
|
||||
// Unlock any lock file.
|
||||
if (lockFileName == null) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
// Close the lock file channel (which also will free any locks)
|
||||
lockFileChannel.close();
|
||||
} catch (Exception ex) {
|
||||
// Problems closing the stream. Punt.
|
||||
}
|
||||
synchronized(locks) {
|
||||
locks.remove(lockFileName);
|
||||
}
|
||||
new File(lockFileName).delete();
|
||||
lockFileName = null;
|
||||
lockFileChannel = null;
|
||||
}
|
||||
|
||||
private static class InitializationErrorManager extends ErrorManager {
|
||||
Exception lastException;
|
||||
@Override
|
||||
public void error(String msg, Exception ex, int code) {
|
||||
lastException = ex;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* check if we are in a set UID program.
|
||||
*/
|
||||
private static native boolean isSetUID();
|
||||
}
|
||||
49
jdkSrc/jdk8/java/util/logging/Filter.java
Normal file
49
jdkSrc/jdk8/java/util/logging/Filter.java
Normal file
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
* Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code 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
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
|
||||
package java.util.logging;
|
||||
|
||||
/**
|
||||
* A Filter can be used to provide fine grain control over
|
||||
* what is logged, beyond the control provided by log levels.
|
||||
* <p>
|
||||
* Each Logger and each Handler can have a filter associated with it.
|
||||
* The Logger or Handler will call the isLoggable method to check
|
||||
* if a given LogRecord should be published. If isLoggable returns
|
||||
* false, the LogRecord will be discarded.
|
||||
*
|
||||
* @since 1.4
|
||||
*/
|
||||
@FunctionalInterface
|
||||
public interface Filter {
|
||||
|
||||
/**
|
||||
* Check if a given log record should be published.
|
||||
* @param record a LogRecord
|
||||
* @return true if the log record should be published.
|
||||
*/
|
||||
public boolean isLoggable(LogRecord record);
|
||||
}
|
||||
147
jdkSrc/jdk8/java/util/logging/Formatter.java
Normal file
147
jdkSrc/jdk8/java/util/logging/Formatter.java
Normal file
@@ -0,0 +1,147 @@
|
||||
/*
|
||||
* Copyright (c) 2000, 2006, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code 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
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
|
||||
package java.util.logging;
|
||||
|
||||
/**
|
||||
* A Formatter provides support for formatting LogRecords.
|
||||
* <p>
|
||||
* Typically each logging Handler will have a Formatter associated
|
||||
* with it. The Formatter takes a LogRecord and converts it to
|
||||
* a string.
|
||||
* <p>
|
||||
* Some formatters (such as the XMLFormatter) need to wrap head
|
||||
* and tail strings around a set of formatted records. The getHeader
|
||||
* and getTail methods can be used to obtain these strings.
|
||||
*
|
||||
* @since 1.4
|
||||
*/
|
||||
|
||||
public abstract class Formatter {
|
||||
|
||||
/**
|
||||
* Construct a new formatter.
|
||||
*/
|
||||
protected Formatter() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Format the given log record and return the formatted string.
|
||||
* <p>
|
||||
* The resulting formatted String will normally include a
|
||||
* localized and formatted version of the LogRecord's message field.
|
||||
* It is recommended to use the {@link Formatter#formatMessage}
|
||||
* convenience method to localize and format the message field.
|
||||
*
|
||||
* @param record the log record to be formatted.
|
||||
* @return the formatted log record
|
||||
*/
|
||||
public abstract String format(LogRecord record);
|
||||
|
||||
|
||||
/**
|
||||
* Return the header string for a set of formatted records.
|
||||
* <p>
|
||||
* This base class returns an empty string, but this may be
|
||||
* overridden by subclasses.
|
||||
*
|
||||
* @param h The target handler (can be null)
|
||||
* @return header string
|
||||
*/
|
||||
public String getHead(Handler h) {
|
||||
return "";
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the tail string for a set of formatted records.
|
||||
* <p>
|
||||
* This base class returns an empty string, but this may be
|
||||
* overridden by subclasses.
|
||||
*
|
||||
* @param h The target handler (can be null)
|
||||
* @return tail string
|
||||
*/
|
||||
public String getTail(Handler h) {
|
||||
return "";
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Localize and format the message string from a log record. This
|
||||
* method is provided as a convenience for Formatter subclasses to
|
||||
* use when they are performing formatting.
|
||||
* <p>
|
||||
* The message string is first localized to a format string using
|
||||
* the record's ResourceBundle. (If there is no ResourceBundle,
|
||||
* or if the message key is not found, then the key is used as the
|
||||
* format string.) The format String uses java.text style
|
||||
* formatting.
|
||||
* <ul>
|
||||
* <li>If there are no parameters, no formatter is used.
|
||||
* <li>Otherwise, if the string contains "{0" then
|
||||
* java.text.MessageFormat is used to format the string.
|
||||
* <li>Otherwise no formatting is performed.
|
||||
* </ul>
|
||||
* <p>
|
||||
*
|
||||
* @param record the log record containing the raw message
|
||||
* @return a localized and formatted message
|
||||
*/
|
||||
public synchronized String formatMessage(LogRecord record) {
|
||||
String format = record.getMessage();
|
||||
java.util.ResourceBundle catalog = record.getResourceBundle();
|
||||
if (catalog != null) {
|
||||
try {
|
||||
format = catalog.getString(record.getMessage());
|
||||
} catch (java.util.MissingResourceException ex) {
|
||||
// Drop through. Use record message as format
|
||||
format = record.getMessage();
|
||||
}
|
||||
}
|
||||
// Do the formatting.
|
||||
try {
|
||||
Object parameters[] = record.getParameters();
|
||||
if (parameters == null || parameters.length == 0) {
|
||||
// No parameters. Just return format string.
|
||||
return format;
|
||||
}
|
||||
// Is it a java.text style format?
|
||||
// Ideally we could match with
|
||||
// Pattern.compile("\\{\\d").matcher(format).find())
|
||||
// However the cost is 14% higher, so we cheaply check for
|
||||
// 1 of the first 4 parameters
|
||||
if (format.indexOf("{0") >= 0 || format.indexOf("{1") >=0 ||
|
||||
format.indexOf("{2") >=0|| format.indexOf("{3") >=0) {
|
||||
return java.text.MessageFormat.format(format, parameters);
|
||||
}
|
||||
return format;
|
||||
|
||||
} catch (Exception ex) {
|
||||
// Formatting failed: use localized format string.
|
||||
return format;
|
||||
}
|
||||
}
|
||||
}
|
||||
313
jdkSrc/jdk8/java/util/logging/Handler.java
Normal file
313
jdkSrc/jdk8/java/util/logging/Handler.java
Normal file
@@ -0,0 +1,313 @@
|
||||
/*
|
||||
* Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code 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
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
|
||||
package java.util.logging;
|
||||
|
||||
import java.io.UnsupportedEncodingException;
|
||||
/**
|
||||
* A <tt>Handler</tt> object takes log messages from a <tt>Logger</tt> and
|
||||
* exports them. It might for example, write them to a console
|
||||
* or write them to a file, or send them to a network logging service,
|
||||
* or forward them to an OS log, or whatever.
|
||||
* <p>
|
||||
* A <tt>Handler</tt> can be disabled by doing a <tt>setLevel(Level.OFF)</tt>
|
||||
* and can be re-enabled by doing a <tt>setLevel</tt> with an appropriate level.
|
||||
* <p>
|
||||
* <tt>Handler</tt> classes typically use <tt>LogManager</tt> properties to set
|
||||
* default values for the <tt>Handler</tt>'s <tt>Filter</tt>, <tt>Formatter</tt>,
|
||||
* and <tt>Level</tt>. See the specific documentation for each concrete
|
||||
* <tt>Handler</tt> class.
|
||||
*
|
||||
*
|
||||
* @since 1.4
|
||||
*/
|
||||
|
||||
public abstract class Handler {
|
||||
private static final int offValue = Level.OFF.intValue();
|
||||
private final LogManager manager = LogManager.getLogManager();
|
||||
|
||||
// We're using volatile here to avoid synchronizing getters, which
|
||||
// would prevent other threads from calling isLoggable()
|
||||
// while publish() is executing.
|
||||
// On the other hand, setters will be synchronized to exclude concurrent
|
||||
// execution with more complex methods, such as StreamHandler.publish().
|
||||
// We wouldn't want 'level' to be changed by another thread in the middle
|
||||
// of the execution of a 'publish' call.
|
||||
private volatile Filter filter;
|
||||
private volatile Formatter formatter;
|
||||
private volatile Level logLevel = Level.ALL;
|
||||
private volatile ErrorManager errorManager = new ErrorManager();
|
||||
private volatile String encoding;
|
||||
|
||||
// Package private support for security checking. When sealed
|
||||
// is true, we access check updates to the class.
|
||||
boolean sealed = true;
|
||||
|
||||
/**
|
||||
* Default constructor. The resulting <tt>Handler</tt> has a log
|
||||
* level of <tt>Level.ALL</tt>, no <tt>Formatter</tt>, and no
|
||||
* <tt>Filter</tt>. A default <tt>ErrorManager</tt> instance is installed
|
||||
* as the <tt>ErrorManager</tt>.
|
||||
*/
|
||||
protected Handler() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Publish a <tt>LogRecord</tt>.
|
||||
* <p>
|
||||
* The logging request was made initially to a <tt>Logger</tt> object,
|
||||
* which initialized the <tt>LogRecord</tt> and forwarded it here.
|
||||
* <p>
|
||||
* The <tt>Handler</tt> is responsible for formatting the message, when and
|
||||
* if necessary. The formatting should include localization.
|
||||
*
|
||||
* @param record description of the log event. A null record is
|
||||
* silently ignored and is not published
|
||||
*/
|
||||
public abstract void publish(LogRecord record);
|
||||
|
||||
/**
|
||||
* Flush any buffered output.
|
||||
*/
|
||||
public abstract void flush();
|
||||
|
||||
/**
|
||||
* Close the <tt>Handler</tt> and free all associated resources.
|
||||
* <p>
|
||||
* The close method will perform a <tt>flush</tt> and then close the
|
||||
* <tt>Handler</tt>. After close has been called this <tt>Handler</tt>
|
||||
* should no longer be used. Method calls may either be silently
|
||||
* ignored or may throw runtime exceptions.
|
||||
*
|
||||
* @exception SecurityException if a security manager exists and if
|
||||
* the caller does not have <tt>LoggingPermission("control")</tt>.
|
||||
*/
|
||||
public abstract void close() throws SecurityException;
|
||||
|
||||
/**
|
||||
* Set a <tt>Formatter</tt>. This <tt>Formatter</tt> will be used
|
||||
* to format <tt>LogRecords</tt> for this <tt>Handler</tt>.
|
||||
* <p>
|
||||
* Some <tt>Handlers</tt> may not use <tt>Formatters</tt>, in
|
||||
* which case the <tt>Formatter</tt> will be remembered, but not used.
|
||||
* <p>
|
||||
* @param newFormatter the <tt>Formatter</tt> to use (may not be null)
|
||||
* @exception SecurityException if a security manager exists and if
|
||||
* the caller does not have <tt>LoggingPermission("control")</tt>.
|
||||
*/
|
||||
public synchronized void setFormatter(Formatter newFormatter) throws SecurityException {
|
||||
checkPermission();
|
||||
// Check for a null pointer:
|
||||
newFormatter.getClass();
|
||||
formatter = newFormatter;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the <tt>Formatter</tt> for this <tt>Handler</tt>.
|
||||
* @return the <tt>Formatter</tt> (may be null).
|
||||
*/
|
||||
public Formatter getFormatter() {
|
||||
return formatter;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the character encoding used by this <tt>Handler</tt>.
|
||||
* <p>
|
||||
* The encoding should be set before any <tt>LogRecords</tt> are written
|
||||
* to the <tt>Handler</tt>.
|
||||
*
|
||||
* @param encoding The name of a supported character encoding.
|
||||
* May be null, to indicate the default platform encoding.
|
||||
* @exception SecurityException if a security manager exists and if
|
||||
* the caller does not have <tt>LoggingPermission("control")</tt>.
|
||||
* @exception UnsupportedEncodingException if the named encoding is
|
||||
* not supported.
|
||||
*/
|
||||
public synchronized void setEncoding(String encoding)
|
||||
throws SecurityException, java.io.UnsupportedEncodingException {
|
||||
checkPermission();
|
||||
if (encoding != null) {
|
||||
try {
|
||||
if(!java.nio.charset.Charset.isSupported(encoding)) {
|
||||
throw new UnsupportedEncodingException(encoding);
|
||||
}
|
||||
} catch (java.nio.charset.IllegalCharsetNameException e) {
|
||||
throw new UnsupportedEncodingException(encoding);
|
||||
}
|
||||
}
|
||||
this.encoding = encoding;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the character encoding for this <tt>Handler</tt>.
|
||||
*
|
||||
* @return The encoding name. May be null, which indicates the
|
||||
* default encoding should be used.
|
||||
*/
|
||||
public String getEncoding() {
|
||||
return encoding;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a <tt>Filter</tt> to control output on this <tt>Handler</tt>.
|
||||
* <P>
|
||||
* For each call of <tt>publish</tt> the <tt>Handler</tt> will call
|
||||
* this <tt>Filter</tt> (if it is non-null) to check if the
|
||||
* <tt>LogRecord</tt> should be published or discarded.
|
||||
*
|
||||
* @param newFilter a <tt>Filter</tt> object (may be null)
|
||||
* @exception SecurityException if a security manager exists and if
|
||||
* the caller does not have <tt>LoggingPermission("control")</tt>.
|
||||
*/
|
||||
public synchronized void setFilter(Filter newFilter) throws SecurityException {
|
||||
checkPermission();
|
||||
filter = newFilter;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the current <tt>Filter</tt> for this <tt>Handler</tt>.
|
||||
*
|
||||
* @return a <tt>Filter</tt> object (may be null)
|
||||
*/
|
||||
public Filter getFilter() {
|
||||
return filter;
|
||||
}
|
||||
|
||||
/**
|
||||
* Define an ErrorManager for this Handler.
|
||||
* <p>
|
||||
* The ErrorManager's "error" method will be invoked if any
|
||||
* errors occur while using this Handler.
|
||||
*
|
||||
* @param em the new ErrorManager
|
||||
* @exception SecurityException if a security manager exists and if
|
||||
* the caller does not have <tt>LoggingPermission("control")</tt>.
|
||||
*/
|
||||
public synchronized void setErrorManager(ErrorManager em) {
|
||||
checkPermission();
|
||||
if (em == null) {
|
||||
throw new NullPointerException();
|
||||
}
|
||||
errorManager = em;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the ErrorManager for this Handler.
|
||||
*
|
||||
* @return the ErrorManager for this Handler
|
||||
* @exception SecurityException if a security manager exists and if
|
||||
* the caller does not have <tt>LoggingPermission("control")</tt>.
|
||||
*/
|
||||
public ErrorManager getErrorManager() {
|
||||
checkPermission();
|
||||
return errorManager;
|
||||
}
|
||||
|
||||
/**
|
||||
* Protected convenience method to report an error to this Handler's
|
||||
* ErrorManager. Note that this method retrieves and uses the ErrorManager
|
||||
* without doing a security check. It can therefore be used in
|
||||
* environments where the caller may be non-privileged.
|
||||
*
|
||||
* @param msg a descriptive string (may be null)
|
||||
* @param ex an exception (may be null)
|
||||
* @param code an error code defined in ErrorManager
|
||||
*/
|
||||
protected void reportError(String msg, Exception ex, int code) {
|
||||
try {
|
||||
errorManager.error(msg, ex, code);
|
||||
} catch (Exception ex2) {
|
||||
System.err.println("Handler.reportError caught:");
|
||||
ex2.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the log level specifying which message levels will be
|
||||
* logged by this <tt>Handler</tt>. Message levels lower than this
|
||||
* value will be discarded.
|
||||
* <p>
|
||||
* The intention is to allow developers to turn on voluminous
|
||||
* logging, but to limit the messages that are sent to certain
|
||||
* <tt>Handlers</tt>.
|
||||
*
|
||||
* @param newLevel the new value for the log level
|
||||
* @exception SecurityException if a security manager exists and if
|
||||
* the caller does not have <tt>LoggingPermission("control")</tt>.
|
||||
*/
|
||||
public synchronized void setLevel(Level newLevel) throws SecurityException {
|
||||
if (newLevel == null) {
|
||||
throw new NullPointerException();
|
||||
}
|
||||
checkPermission();
|
||||
logLevel = newLevel;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the log level specifying which messages will be
|
||||
* logged by this <tt>Handler</tt>. Message levels lower
|
||||
* than this level will be discarded.
|
||||
* @return the level of messages being logged.
|
||||
*/
|
||||
public Level getLevel() {
|
||||
return logLevel;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if this <tt>Handler</tt> would actually log a given <tt>LogRecord</tt>.
|
||||
* <p>
|
||||
* This method checks if the <tt>LogRecord</tt> has an appropriate
|
||||
* <tt>Level</tt> and whether it satisfies any <tt>Filter</tt>. It also
|
||||
* may make other <tt>Handler</tt> specific checks that might prevent a
|
||||
* handler from logging the <tt>LogRecord</tt>. It will return false if
|
||||
* the <tt>LogRecord</tt> is null.
|
||||
* <p>
|
||||
* @param record a <tt>LogRecord</tt>
|
||||
* @return true if the <tt>LogRecord</tt> would be logged.
|
||||
*
|
||||
*/
|
||||
public boolean isLoggable(LogRecord record) {
|
||||
final int levelValue = getLevel().intValue();
|
||||
if (record.getLevel().intValue() < levelValue || levelValue == offValue) {
|
||||
return false;
|
||||
}
|
||||
final Filter filter = getFilter();
|
||||
if (filter == null) {
|
||||
return true;
|
||||
}
|
||||
return filter.isLoggable(record);
|
||||
}
|
||||
|
||||
// Package-private support method for security checks.
|
||||
// If "sealed" is true, we check that the caller has
|
||||
// appropriate security privileges to update Handler
|
||||
// state and if not throw a SecurityException.
|
||||
void checkPermission() throws SecurityException {
|
||||
if (sealed) {
|
||||
manager.checkPermission();
|
||||
}
|
||||
}
|
||||
}
|
||||
623
jdkSrc/jdk8/java/util/logging/Level.java
Normal file
623
jdkSrc/jdk8/java/util/logging/Level.java
Normal file
@@ -0,0 +1,623 @@
|
||||
/*
|
||||
* Copyright (c) 2000, 2017, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code 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
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package java.util.logging;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.ResourceBundle;
|
||||
|
||||
/**
|
||||
* The Level class defines a set of standard logging levels that
|
||||
* can be used to control logging output. The logging Level objects
|
||||
* are ordered and are specified by ordered integers. Enabling logging
|
||||
* at a given level also enables logging at all higher levels.
|
||||
* <p>
|
||||
* Clients should normally use the predefined Level constants such
|
||||
* as Level.SEVERE.
|
||||
* <p>
|
||||
* The levels in descending order are:
|
||||
* <ul>
|
||||
* <li>SEVERE (highest value)
|
||||
* <li>WARNING
|
||||
* <li>INFO
|
||||
* <li>CONFIG
|
||||
* <li>FINE
|
||||
* <li>FINER
|
||||
* <li>FINEST (lowest value)
|
||||
* </ul>
|
||||
* In addition there is a level OFF that can be used to turn
|
||||
* off logging, and a level ALL that can be used to enable
|
||||
* logging of all messages.
|
||||
* <p>
|
||||
* It is possible for third parties to define additional logging
|
||||
* levels by subclassing Level. In such cases subclasses should
|
||||
* take care to chose unique integer level values and to ensure that
|
||||
* they maintain the Object uniqueness property across serialization
|
||||
* by defining a suitable readResolve method.
|
||||
*
|
||||
* @since 1.4
|
||||
*/
|
||||
|
||||
public class Level implements java.io.Serializable {
|
||||
private static final String defaultBundle = "sun.util.logging.resources.logging";
|
||||
|
||||
/**
|
||||
* @serial The non-localized name of the level.
|
||||
*/
|
||||
private final String name;
|
||||
|
||||
/**
|
||||
* @serial The integer value of the level.
|
||||
*/
|
||||
private final int value;
|
||||
|
||||
/**
|
||||
* @serial The resource bundle name to be used in localizing the level name.
|
||||
*/
|
||||
private final String resourceBundleName;
|
||||
|
||||
// localized level name
|
||||
private transient String localizedLevelName;
|
||||
private transient Locale cachedLocale;
|
||||
|
||||
/**
|
||||
* OFF is a special level that can be used to turn off logging.
|
||||
* This level is initialized to <CODE>Integer.MAX_VALUE</CODE>.
|
||||
*/
|
||||
public static final Level OFF = new Level("OFF",Integer.MAX_VALUE, defaultBundle);
|
||||
|
||||
/**
|
||||
* SEVERE is a message level indicating a serious failure.
|
||||
* <p>
|
||||
* In general SEVERE messages should describe events that are
|
||||
* of considerable importance and which will prevent normal
|
||||
* program execution. They should be reasonably intelligible
|
||||
* to end users and to system administrators.
|
||||
* This level is initialized to <CODE>1000</CODE>.
|
||||
*/
|
||||
public static final Level SEVERE = new Level("SEVERE",1000, defaultBundle);
|
||||
|
||||
/**
|
||||
* WARNING is a message level indicating a potential problem.
|
||||
* <p>
|
||||
* In general WARNING messages should describe events that will
|
||||
* be of interest to end users or system managers, or which
|
||||
* indicate potential problems.
|
||||
* This level is initialized to <CODE>900</CODE>.
|
||||
*/
|
||||
public static final Level WARNING = new Level("WARNING", 900, defaultBundle);
|
||||
|
||||
/**
|
||||
* INFO is a message level for informational messages.
|
||||
* <p>
|
||||
* Typically INFO messages will be written to the console
|
||||
* or its equivalent. So the INFO level should only be
|
||||
* used for reasonably significant messages that will
|
||||
* make sense to end users and system administrators.
|
||||
* This level is initialized to <CODE>800</CODE>.
|
||||
*/
|
||||
public static final Level INFO = new Level("INFO", 800, defaultBundle);
|
||||
|
||||
/**
|
||||
* CONFIG is a message level for static configuration messages.
|
||||
* <p>
|
||||
* CONFIG messages are intended to provide a variety of static
|
||||
* configuration information, to assist in debugging problems
|
||||
* that may be associated with particular configurations.
|
||||
* For example, CONFIG message might include the CPU type,
|
||||
* the graphics depth, the GUI look-and-feel, etc.
|
||||
* This level is initialized to <CODE>700</CODE>.
|
||||
*/
|
||||
public static final Level CONFIG = new Level("CONFIG", 700, defaultBundle);
|
||||
|
||||
/**
|
||||
* FINE is a message level providing tracing information.
|
||||
* <p>
|
||||
* All of FINE, FINER, and FINEST are intended for relatively
|
||||
* detailed tracing. The exact meaning of the three levels will
|
||||
* vary between subsystems, but in general, FINEST should be used
|
||||
* for the most voluminous detailed output, FINER for somewhat
|
||||
* less detailed output, and FINE for the lowest volume (and
|
||||
* most important) messages.
|
||||
* <p>
|
||||
* In general the FINE level should be used for information
|
||||
* that will be broadly interesting to developers who do not have
|
||||
* a specialized interest in the specific subsystem.
|
||||
* <p>
|
||||
* FINE messages might include things like minor (recoverable)
|
||||
* failures. Issues indicating potential performance problems
|
||||
* are also worth logging as FINE.
|
||||
* This level is initialized to <CODE>500</CODE>.
|
||||
*/
|
||||
public static final Level FINE = new Level("FINE", 500, defaultBundle);
|
||||
|
||||
/**
|
||||
* FINER indicates a fairly detailed tracing message.
|
||||
* By default logging calls for entering, returning, or throwing
|
||||
* an exception are traced at this level.
|
||||
* This level is initialized to <CODE>400</CODE>.
|
||||
*/
|
||||
public static final Level FINER = new Level("FINER", 400, defaultBundle);
|
||||
|
||||
/**
|
||||
* FINEST indicates a highly detailed tracing message.
|
||||
* This level is initialized to <CODE>300</CODE>.
|
||||
*/
|
||||
public static final Level FINEST = new Level("FINEST", 300, defaultBundle);
|
||||
|
||||
/**
|
||||
* ALL indicates that all messages should be logged.
|
||||
* This level is initialized to <CODE>Integer.MIN_VALUE</CODE>.
|
||||
*/
|
||||
public static final Level ALL = new Level("ALL", Integer.MIN_VALUE, defaultBundle);
|
||||
|
||||
/**
|
||||
* Create a named Level with a given integer value.
|
||||
* <p>
|
||||
* Note that this constructor is "protected" to allow subclassing.
|
||||
* In general clients of logging should use one of the constant Level
|
||||
* objects such as SEVERE or FINEST. However, if clients need to
|
||||
* add new logging levels, they may subclass Level and define new
|
||||
* constants.
|
||||
* @param name the name of the Level, for example "SEVERE".
|
||||
* @param value an integer value for the level.
|
||||
* @throws NullPointerException if the name is null
|
||||
*/
|
||||
protected Level(String name, int value) {
|
||||
this(name, value, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a named Level with a given integer value and a
|
||||
* given localization resource name.
|
||||
* <p>
|
||||
* @param name the name of the Level, for example "SEVERE".
|
||||
* @param value an integer value for the level.
|
||||
* @param resourceBundleName name of a resource bundle to use in
|
||||
* localizing the given name. If the resourceBundleName is null
|
||||
* or an empty string, it is ignored.
|
||||
* @throws NullPointerException if the name is null
|
||||
*/
|
||||
protected Level(String name, int value, String resourceBundleName) {
|
||||
this(name, value, resourceBundleName, true);
|
||||
}
|
||||
|
||||
// private constructor to specify whether this instance should be added
|
||||
// to the KnownLevel list from which Level.parse method does its look up
|
||||
private Level(String name, int value, String resourceBundleName, boolean visible) {
|
||||
if (name == null) {
|
||||
throw new NullPointerException();
|
||||
}
|
||||
this.name = name;
|
||||
this.value = value;
|
||||
this.resourceBundleName = resourceBundleName;
|
||||
this.localizedLevelName = resourceBundleName == null ? name : null;
|
||||
this.cachedLocale = null;
|
||||
if (visible) {
|
||||
KnownLevel.add(this);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the level's localization resource bundle name, or
|
||||
* null if no localization bundle is defined.
|
||||
*
|
||||
* @return localization resource bundle name
|
||||
*/
|
||||
public String getResourceBundleName() {
|
||||
return resourceBundleName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the non-localized string name of the Level.
|
||||
*
|
||||
* @return non-localized name
|
||||
*/
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the localized string name of the Level, for
|
||||
* the current default locale.
|
||||
* <p>
|
||||
* If no localization information is available, the
|
||||
* non-localized name is returned.
|
||||
*
|
||||
* @return localized name
|
||||
*/
|
||||
public String getLocalizedName() {
|
||||
return getLocalizedLevelName();
|
||||
}
|
||||
|
||||
// package-private getLevelName() is used by the implementation
|
||||
// instead of getName() to avoid calling the subclass's version
|
||||
final String getLevelName() {
|
||||
return this.name;
|
||||
}
|
||||
|
||||
private String computeLocalizedLevelName(Locale newLocale) {
|
||||
// If this is a custom Level, load resource bundles on the
|
||||
// classpath and return.
|
||||
if (!defaultBundle.equals(resourceBundleName)) {
|
||||
return ResourceBundle.getBundle(resourceBundleName, newLocale,
|
||||
ClassLoader.getSystemClassLoader()).getString(name);
|
||||
}
|
||||
|
||||
// The default bundle "sun.util.logging.resources.logging" should only
|
||||
// be loaded from the runtime; so use the extension class loader;
|
||||
final ResourceBundle rb = ResourceBundle.getBundle(defaultBundle, newLocale);
|
||||
final String localizedName = rb.getString(name);
|
||||
|
||||
// This is a trick to determine whether the name has been translated
|
||||
// or not. If it has not been translated, we need to use Locale.ROOT
|
||||
// when calling toUpperCase().
|
||||
final Locale rbLocale = rb.getLocale();
|
||||
final Locale locale =
|
||||
Locale.ROOT.equals(rbLocale)
|
||||
|| name.equals(localizedName.toUpperCase(Locale.ROOT))
|
||||
? Locale.ROOT : rbLocale;
|
||||
|
||||
// ALL CAPS in a resource bundle's message indicates no translation
|
||||
// needed per Oracle translation guideline. To workaround this
|
||||
// in Oracle JDK implementation, convert the localized level name
|
||||
// to uppercase for compatibility reason.
|
||||
return Locale.ROOT.equals(locale) ? name : localizedName.toUpperCase(locale);
|
||||
}
|
||||
|
||||
// Avoid looking up the localizedLevelName twice if we already
|
||||
// have it.
|
||||
final String getCachedLocalizedLevelName() {
|
||||
|
||||
if (localizedLevelName != null) {
|
||||
if (cachedLocale != null) {
|
||||
if (cachedLocale.equals(Locale.getDefault())) {
|
||||
// OK: our cached value was looked up with the same
|
||||
// locale. We can use it.
|
||||
return localizedLevelName;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (resourceBundleName == null) {
|
||||
// No resource bundle: just use the name.
|
||||
return name;
|
||||
}
|
||||
|
||||
// We need to compute the localized name.
|
||||
// Either because it's the first time, or because our cached
|
||||
// value is for a different locale. Just return null.
|
||||
return null;
|
||||
}
|
||||
|
||||
final synchronized String getLocalizedLevelName() {
|
||||
|
||||
// See if we have a cached localized name
|
||||
final String cachedLocalizedName = getCachedLocalizedLevelName();
|
||||
if (cachedLocalizedName != null) {
|
||||
return cachedLocalizedName;
|
||||
}
|
||||
|
||||
// No cached localized name or cache invalid.
|
||||
// Need to compute the localized name.
|
||||
final Locale newLocale = Locale.getDefault();
|
||||
try {
|
||||
localizedLevelName = computeLocalizedLevelName(newLocale);
|
||||
} catch (Exception ex) {
|
||||
localizedLevelName = name;
|
||||
}
|
||||
cachedLocale = newLocale;
|
||||
return localizedLevelName;
|
||||
}
|
||||
|
||||
// Returns a mirrored Level object that matches the given name as
|
||||
// specified in the Level.parse method. Returns null if not found.
|
||||
//
|
||||
// It returns the same Level object as the one returned by Level.parse
|
||||
// method if the given name is a non-localized name or integer.
|
||||
//
|
||||
// If the name is a localized name, findLevel and parse method may
|
||||
// return a different level value if there is a custom Level subclass
|
||||
// that overrides Level.getLocalizedName() to return a different string
|
||||
// than what's returned by the default implementation.
|
||||
//
|
||||
static Level findLevel(String name) {
|
||||
if (name == null) {
|
||||
throw new NullPointerException();
|
||||
}
|
||||
|
||||
KnownLevel level;
|
||||
|
||||
// Look for a known Level with the given non-localized name.
|
||||
level = KnownLevel.findByName(name);
|
||||
if (level != null) {
|
||||
return level.mirroredLevel;
|
||||
}
|
||||
|
||||
// Now, check if the given name is an integer. If so,
|
||||
// first look for a Level with the given value and then
|
||||
// if necessary create one.
|
||||
try {
|
||||
int x = Integer.parseInt(name);
|
||||
level = KnownLevel.findByValue(x);
|
||||
if (level == null) {
|
||||
// add new Level
|
||||
Level levelObject = new Level(name, x);
|
||||
level = KnownLevel.findByValue(x);
|
||||
}
|
||||
return level.mirroredLevel;
|
||||
} catch (NumberFormatException ex) {
|
||||
// Not an integer.
|
||||
// Drop through.
|
||||
}
|
||||
|
||||
level = KnownLevel.findByLocalizedLevelName(name);
|
||||
if (level != null) {
|
||||
return level.mirroredLevel;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a string representation of this Level.
|
||||
*
|
||||
* @return the non-localized name of the Level, for example "INFO".
|
||||
*/
|
||||
@Override
|
||||
public final String toString() {
|
||||
return name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the integer value for this level. This integer value
|
||||
* can be used for efficient ordering comparisons between
|
||||
* Level objects.
|
||||
* @return the integer value for this level.
|
||||
*/
|
||||
public final int intValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
private static final long serialVersionUID = -8176160795706313070L;
|
||||
|
||||
// Serialization magic to prevent "doppelgangers".
|
||||
// This is a performance optimization.
|
||||
private Object readResolve() {
|
||||
KnownLevel o = KnownLevel.matches(this);
|
||||
if (o != null) {
|
||||
return o.levelObject;
|
||||
}
|
||||
|
||||
// Woops. Whoever sent us this object knows
|
||||
// about a new log level. Add it to our list.
|
||||
Level level = new Level(this.name, this.value, this.resourceBundleName);
|
||||
return level;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse a level name string into a Level.
|
||||
* <p>
|
||||
* The argument string may consist of either a level name
|
||||
* or an integer value.
|
||||
* <p>
|
||||
* For example:
|
||||
* <ul>
|
||||
* <li> "SEVERE"
|
||||
* <li> "1000"
|
||||
* </ul>
|
||||
*
|
||||
* @param name string to be parsed
|
||||
* @throws NullPointerException if the name is null
|
||||
* @throws IllegalArgumentException if the value is not valid.
|
||||
* Valid values are integers between <CODE>Integer.MIN_VALUE</CODE>
|
||||
* and <CODE>Integer.MAX_VALUE</CODE>, and all known level names.
|
||||
* Known names are the levels defined by this class (e.g., <CODE>FINE</CODE>,
|
||||
* <CODE>FINER</CODE>, <CODE>FINEST</CODE>), or created by this class with
|
||||
* appropriate package access, or new levels defined or created
|
||||
* by subclasses.
|
||||
*
|
||||
* @return The parsed value. Passing an integer that corresponds to a known name
|
||||
* (e.g., 700) will return the associated name (e.g., <CODE>CONFIG</CODE>).
|
||||
* Passing an integer that does not (e.g., 1) will return a new level name
|
||||
* initialized to that value.
|
||||
*/
|
||||
public static synchronized Level parse(String name) throws IllegalArgumentException {
|
||||
// Check that name is not null.
|
||||
name.length();
|
||||
|
||||
KnownLevel level;
|
||||
|
||||
// Look for a known Level with the given non-localized name.
|
||||
level = KnownLevel.findByName(name);
|
||||
if (level != null) {
|
||||
return level.levelObject;
|
||||
}
|
||||
|
||||
// Now, check if the given name is an integer. If so,
|
||||
// first look for a Level with the given value and then
|
||||
// if necessary create one.
|
||||
try {
|
||||
int x = Integer.parseInt(name);
|
||||
level = KnownLevel.findByValue(x);
|
||||
if (level == null) {
|
||||
// add new Level
|
||||
Level levelObject = new Level(name, x);
|
||||
level = KnownLevel.findByValue(x);
|
||||
}
|
||||
return level.levelObject;
|
||||
} catch (NumberFormatException ex) {
|
||||
// Not an integer.
|
||||
// Drop through.
|
||||
}
|
||||
|
||||
// Finally, look for a known level with the given localized name,
|
||||
// in the current default locale.
|
||||
// This is relatively expensive, but not excessively so.
|
||||
level = KnownLevel.findByLocalizedLevelName(name);
|
||||
if (level != null) {
|
||||
return level.levelObject;
|
||||
}
|
||||
|
||||
// OK, we've tried everything and failed
|
||||
throw new IllegalArgumentException("Bad level \"" + name + "\"");
|
||||
}
|
||||
|
||||
/**
|
||||
* Compare two objects for value equality.
|
||||
* @return true if and only if the two objects have the same level value.
|
||||
*/
|
||||
@Override
|
||||
public boolean equals(Object ox) {
|
||||
try {
|
||||
Level lx = (Level)ox;
|
||||
return (lx.value == this.value);
|
||||
} catch (Exception ex) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate a hashcode.
|
||||
* @return a hashcode based on the level value
|
||||
*/
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return this.value;
|
||||
}
|
||||
|
||||
// KnownLevel class maintains the global list of all known levels.
|
||||
// The API allows multiple custom Level instances of the same name/value
|
||||
// be created. This class provides convenient methods to find a level
|
||||
// by a given name, by a given value, or by a given localized name.
|
||||
//
|
||||
// KnownLevel wraps the following Level objects:
|
||||
// 1. levelObject: standard Level object or custom Level object
|
||||
// 2. mirroredLevel: Level object representing the level specified in the
|
||||
// logging configuration.
|
||||
//
|
||||
// Level.getName, Level.getLocalizedName, Level.getResourceBundleName methods
|
||||
// are non-final but the name and resource bundle name are parameters to
|
||||
// the Level constructor. Use the mirroredLevel object instead of the
|
||||
// levelObject to prevent the logging framework to execute foreign code
|
||||
// implemented by untrusted Level subclass.
|
||||
//
|
||||
// Implementation Notes:
|
||||
// If Level.getName, Level.getLocalizedName, Level.getResourceBundleName methods
|
||||
// were final, the following KnownLevel implementation can be removed.
|
||||
// Future API change should take this into consideration.
|
||||
static final class KnownLevel {
|
||||
private static Map<String, List<KnownLevel>> nameToLevels = new HashMap<>();
|
||||
private static Map<Integer, List<KnownLevel>> intToLevels = new HashMap<>();
|
||||
final Level levelObject; // instance of Level class or Level subclass
|
||||
final Level mirroredLevel; // mirror of the custom Level
|
||||
KnownLevel(Level l) {
|
||||
this.levelObject = l;
|
||||
if (l.getClass() == Level.class) {
|
||||
this.mirroredLevel = l;
|
||||
} else {
|
||||
// this mirrored level object is hidden
|
||||
this.mirroredLevel = new Level(l.name, l.value, l.resourceBundleName, false);
|
||||
}
|
||||
}
|
||||
|
||||
static synchronized void add(Level l) {
|
||||
// the mirroredLevel object is always added to the list
|
||||
// before the custom Level instance
|
||||
KnownLevel o = new KnownLevel(l);
|
||||
List<KnownLevel> list = nameToLevels.get(l.name);
|
||||
if (list == null) {
|
||||
list = new ArrayList<>();
|
||||
nameToLevels.put(l.name, list);
|
||||
}
|
||||
list.add(o);
|
||||
|
||||
list = intToLevels.get(l.value);
|
||||
if (list == null) {
|
||||
list = new ArrayList<>();
|
||||
intToLevels.put(l.value, list);
|
||||
}
|
||||
list.add(o);
|
||||
}
|
||||
|
||||
// Returns a KnownLevel with the given non-localized name.
|
||||
static synchronized KnownLevel findByName(String name) {
|
||||
List<KnownLevel> list = nameToLevels.get(name);
|
||||
if (list != null) {
|
||||
return list.get(0);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
// Returns a KnownLevel with the given value.
|
||||
static synchronized KnownLevel findByValue(int value) {
|
||||
List<KnownLevel> list = intToLevels.get(value);
|
||||
if (list != null) {
|
||||
return list.get(0);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
// Returns a KnownLevel with the given localized name matching
|
||||
// by calling the Level.getLocalizedLevelName() method (i.e. found
|
||||
// from the resourceBundle associated with the Level object).
|
||||
// This method does not call Level.getLocalizedName() that may
|
||||
// be overridden in a subclass implementation
|
||||
static synchronized KnownLevel findByLocalizedLevelName(String name) {
|
||||
for (List<KnownLevel> levels : nameToLevels.values()) {
|
||||
for (KnownLevel l : levels) {
|
||||
String lname = l.levelObject.getLocalizedLevelName();
|
||||
if (name.equals(lname)) {
|
||||
return l;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
static synchronized KnownLevel matches(Level l) {
|
||||
List<KnownLevel> list = nameToLevels.get(l.name);
|
||||
if (list != null) {
|
||||
for (KnownLevel level : list) {
|
||||
Level other = level.mirroredLevel;
|
||||
Class<? extends Level> type = level.levelObject.getClass();
|
||||
if (l.value == other.value &&
|
||||
(l.resourceBundleName == other.resourceBundleName ||
|
||||
(l.resourceBundleName != null &&
|
||||
l.resourceBundleName.equals(other.resourceBundleName)))) {
|
||||
if (type == l.getClass()) {
|
||||
return level;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
1833
jdkSrc/jdk8/java/util/logging/LogManager.java
Normal file
1833
jdkSrc/jdk8/java/util/logging/LogManager.java
Normal file
File diff suppressed because it is too large
Load Diff
583
jdkSrc/jdk8/java/util/logging/LogRecord.java
Normal file
583
jdkSrc/jdk8/java/util/logging/LogRecord.java
Normal file
@@ -0,0 +1,583 @@
|
||||
/*
|
||||
* Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code 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
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package java.util.logging;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
import java.io.*;
|
||||
|
||||
import sun.misc.JavaLangAccess;
|
||||
import sun.misc.SharedSecrets;
|
||||
|
||||
/**
|
||||
* LogRecord objects are used to pass logging requests between
|
||||
* the logging framework and individual log Handlers.
|
||||
* <p>
|
||||
* When a LogRecord is passed into the logging framework it
|
||||
* logically belongs to the framework and should no longer be
|
||||
* used or updated by the client application.
|
||||
* <p>
|
||||
* Note that if the client application has not specified an
|
||||
* explicit source method name and source class name, then the
|
||||
* LogRecord class will infer them automatically when they are
|
||||
* first accessed (due to a call on getSourceMethodName or
|
||||
* getSourceClassName) by analyzing the call stack. Therefore,
|
||||
* if a logging Handler wants to pass off a LogRecord to another
|
||||
* thread, or to transmit it over RMI, and if it wishes to subsequently
|
||||
* obtain method name or class name information it should call
|
||||
* one of getSourceClassName or getSourceMethodName to force
|
||||
* the values to be filled in.
|
||||
* <p>
|
||||
* <b> Serialization notes:</b>
|
||||
* <ul>
|
||||
* <li>The LogRecord class is serializable.
|
||||
*
|
||||
* <li> Because objects in the parameters array may not be serializable,
|
||||
* during serialization all objects in the parameters array are
|
||||
* written as the corresponding Strings (using Object.toString).
|
||||
*
|
||||
* <li> The ResourceBundle is not transmitted as part of the serialized
|
||||
* form, but the resource bundle name is, and the recipient object's
|
||||
* readObject method will attempt to locate a suitable resource bundle.
|
||||
*
|
||||
* </ul>
|
||||
*
|
||||
* @since 1.4
|
||||
*/
|
||||
|
||||
public class LogRecord implements java.io.Serializable {
|
||||
private static final AtomicLong globalSequenceNumber
|
||||
= new AtomicLong(0);
|
||||
|
||||
/**
|
||||
* The default value of threadID will be the current thread's
|
||||
* thread id, for ease of correlation, unless it is greater than
|
||||
* MIN_SEQUENTIAL_THREAD_ID, in which case we try harder to keep
|
||||
* our promise to keep threadIDs unique by avoiding collisions due
|
||||
* to 32-bit wraparound. Unfortunately, LogRecord.getThreadID()
|
||||
* returns int, while Thread.getId() returns long.
|
||||
*/
|
||||
private static final int MIN_SEQUENTIAL_THREAD_ID = Integer.MAX_VALUE / 2;
|
||||
|
||||
private static final AtomicInteger nextThreadId
|
||||
= new AtomicInteger(MIN_SEQUENTIAL_THREAD_ID);
|
||||
|
||||
private static final ThreadLocal<Integer> threadIds = new ThreadLocal<>();
|
||||
|
||||
/**
|
||||
* @serial Logging message level
|
||||
*/
|
||||
private Level level;
|
||||
|
||||
/**
|
||||
* @serial Sequence number
|
||||
*/
|
||||
private long sequenceNumber;
|
||||
|
||||
/**
|
||||
* @serial Class that issued logging call
|
||||
*/
|
||||
private String sourceClassName;
|
||||
|
||||
/**
|
||||
* @serial Method that issued logging call
|
||||
*/
|
||||
private String sourceMethodName;
|
||||
|
||||
/**
|
||||
* @serial Non-localized raw message text
|
||||
*/
|
||||
private String message;
|
||||
|
||||
/**
|
||||
* @serial Thread ID for thread that issued logging call.
|
||||
*/
|
||||
private int threadID;
|
||||
|
||||
/**
|
||||
* @serial Event time in milliseconds since 1970
|
||||
*/
|
||||
private long millis;
|
||||
|
||||
/**
|
||||
* @serial The Throwable (if any) associated with log message
|
||||
*/
|
||||
private Throwable thrown;
|
||||
|
||||
/**
|
||||
* @serial Name of the source Logger.
|
||||
*/
|
||||
private String loggerName;
|
||||
|
||||
/**
|
||||
* @serial Resource bundle name to localized log message.
|
||||
*/
|
||||
private String resourceBundleName;
|
||||
|
||||
private transient boolean needToInferCaller;
|
||||
private transient Object parameters[];
|
||||
private transient ResourceBundle resourceBundle;
|
||||
|
||||
/**
|
||||
* Returns the default value for a new LogRecord's threadID.
|
||||
*/
|
||||
private int defaultThreadID() {
|
||||
long tid = Thread.currentThread().getId();
|
||||
if (tid < MIN_SEQUENTIAL_THREAD_ID) {
|
||||
return (int) tid;
|
||||
} else {
|
||||
Integer id = threadIds.get();
|
||||
if (id == null) {
|
||||
id = nextThreadId.getAndIncrement();
|
||||
threadIds.set(id);
|
||||
}
|
||||
return id;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct a LogRecord with the given level and message values.
|
||||
* <p>
|
||||
* The sequence property will be initialized with a new unique value.
|
||||
* These sequence values are allocated in increasing order within a VM.
|
||||
* <p>
|
||||
* The millis property will be initialized to the current time.
|
||||
* <p>
|
||||
* The thread ID property will be initialized with a unique ID for
|
||||
* the current thread.
|
||||
* <p>
|
||||
* All other properties will be initialized to "null".
|
||||
*
|
||||
* @param level a logging level value
|
||||
* @param msg the raw non-localized logging message (may be null)
|
||||
*/
|
||||
public LogRecord(Level level, String msg) {
|
||||
// Make sure level isn't null, by calling random method.
|
||||
level.getClass();
|
||||
this.level = level;
|
||||
message = msg;
|
||||
// Assign a thread ID and a unique sequence number.
|
||||
sequenceNumber = globalSequenceNumber.getAndIncrement();
|
||||
threadID = defaultThreadID();
|
||||
millis = System.currentTimeMillis();
|
||||
needToInferCaller = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the source Logger's name.
|
||||
*
|
||||
* @return source logger name (may be null)
|
||||
*/
|
||||
public String getLoggerName() {
|
||||
return loggerName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the source Logger's name.
|
||||
*
|
||||
* @param name the source logger name (may be null)
|
||||
*/
|
||||
public void setLoggerName(String name) {
|
||||
loggerName = name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the localization resource bundle
|
||||
* <p>
|
||||
* This is the ResourceBundle that should be used to localize
|
||||
* the message string before formatting it. The result may
|
||||
* be null if the message is not localizable, or if no suitable
|
||||
* ResourceBundle is available.
|
||||
* @return the localization resource bundle
|
||||
*/
|
||||
public ResourceBundle getResourceBundle() {
|
||||
return resourceBundle;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the localization resource bundle.
|
||||
*
|
||||
* @param bundle localization bundle (may be null)
|
||||
*/
|
||||
public void setResourceBundle(ResourceBundle bundle) {
|
||||
resourceBundle = bundle;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the localization resource bundle name
|
||||
* <p>
|
||||
* This is the name for the ResourceBundle that should be
|
||||
* used to localize the message string before formatting it.
|
||||
* The result may be null if the message is not localizable.
|
||||
* @return the localization resource bundle name
|
||||
*/
|
||||
public String getResourceBundleName() {
|
||||
return resourceBundleName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the localization resource bundle name.
|
||||
*
|
||||
* @param name localization bundle name (may be null)
|
||||
*/
|
||||
public void setResourceBundleName(String name) {
|
||||
resourceBundleName = name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the logging message level, for example Level.SEVERE.
|
||||
* @return the logging message level
|
||||
*/
|
||||
public Level getLevel() {
|
||||
return level;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the logging message level, for example Level.SEVERE.
|
||||
* @param level the logging message level
|
||||
*/
|
||||
public void setLevel(Level level) {
|
||||
if (level == null) {
|
||||
throw new NullPointerException();
|
||||
}
|
||||
this.level = level;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the sequence number.
|
||||
* <p>
|
||||
* Sequence numbers are normally assigned in the LogRecord
|
||||
* constructor, which assigns unique sequence numbers to
|
||||
* each new LogRecord in increasing order.
|
||||
* @return the sequence number
|
||||
*/
|
||||
public long getSequenceNumber() {
|
||||
return sequenceNumber;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the sequence number.
|
||||
* <p>
|
||||
* Sequence numbers are normally assigned in the LogRecord constructor,
|
||||
* so it should not normally be necessary to use this method.
|
||||
* @param seq the sequence number
|
||||
*/
|
||||
public void setSequenceNumber(long seq) {
|
||||
sequenceNumber = seq;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the name of the class that (allegedly) issued the logging request.
|
||||
* <p>
|
||||
* Note that this sourceClassName is not verified and may be spoofed.
|
||||
* This information may either have been provided as part of the
|
||||
* logging call, or it may have been inferred automatically by the
|
||||
* logging framework. In the latter case, the information may only
|
||||
* be approximate and may in fact describe an earlier call on the
|
||||
* stack frame.
|
||||
* <p>
|
||||
* May be null if no information could be obtained.
|
||||
*
|
||||
* @return the source class name
|
||||
*/
|
||||
public String getSourceClassName() {
|
||||
if (needToInferCaller) {
|
||||
inferCaller();
|
||||
}
|
||||
return sourceClassName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the name of the class that (allegedly) issued the logging request.
|
||||
*
|
||||
* @param sourceClassName the source class name (may be null)
|
||||
*/
|
||||
public void setSourceClassName(String sourceClassName) {
|
||||
this.sourceClassName = sourceClassName;
|
||||
needToInferCaller = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the name of the method that (allegedly) issued the logging request.
|
||||
* <p>
|
||||
* Note that this sourceMethodName is not verified and may be spoofed.
|
||||
* This information may either have been provided as part of the
|
||||
* logging call, or it may have been inferred automatically by the
|
||||
* logging framework. In the latter case, the information may only
|
||||
* be approximate and may in fact describe an earlier call on the
|
||||
* stack frame.
|
||||
* <p>
|
||||
* May be null if no information could be obtained.
|
||||
*
|
||||
* @return the source method name
|
||||
*/
|
||||
public String getSourceMethodName() {
|
||||
if (needToInferCaller) {
|
||||
inferCaller();
|
||||
}
|
||||
return sourceMethodName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the name of the method that (allegedly) issued the logging request.
|
||||
*
|
||||
* @param sourceMethodName the source method name (may be null)
|
||||
*/
|
||||
public void setSourceMethodName(String sourceMethodName) {
|
||||
this.sourceMethodName = sourceMethodName;
|
||||
needToInferCaller = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the "raw" log message, before localization or formatting.
|
||||
* <p>
|
||||
* May be null, which is equivalent to the empty string "".
|
||||
* <p>
|
||||
* This message may be either the final text or a localization key.
|
||||
* <p>
|
||||
* During formatting, if the source logger has a localization
|
||||
* ResourceBundle and if that ResourceBundle has an entry for
|
||||
* this message string, then the message string is replaced
|
||||
* with the localized value.
|
||||
*
|
||||
* @return the raw message string
|
||||
*/
|
||||
public String getMessage() {
|
||||
return message;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the "raw" log message, before localization or formatting.
|
||||
*
|
||||
* @param message the raw message string (may be null)
|
||||
*/
|
||||
public void setMessage(String message) {
|
||||
this.message = message;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the parameters to the log message.
|
||||
*
|
||||
* @return the log message parameters. May be null if
|
||||
* there are no parameters.
|
||||
*/
|
||||
public Object[] getParameters() {
|
||||
return parameters;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the parameters to the log message.
|
||||
*
|
||||
* @param parameters the log message parameters. (may be null)
|
||||
*/
|
||||
public void setParameters(Object parameters[]) {
|
||||
this.parameters = parameters;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an identifier for the thread where the message originated.
|
||||
* <p>
|
||||
* This is a thread identifier within the Java VM and may or
|
||||
* may not map to any operating system ID.
|
||||
*
|
||||
* @return thread ID
|
||||
*/
|
||||
public int getThreadID() {
|
||||
return threadID;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set an identifier for the thread where the message originated.
|
||||
* @param threadID the thread ID
|
||||
*/
|
||||
public void setThreadID(int threadID) {
|
||||
this.threadID = threadID;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get event time in milliseconds since 1970.
|
||||
*
|
||||
* @return event time in millis since 1970
|
||||
*/
|
||||
public long getMillis() {
|
||||
return millis;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set event time.
|
||||
*
|
||||
* @param millis event time in millis since 1970
|
||||
*/
|
||||
public void setMillis(long millis) {
|
||||
this.millis = millis;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get any throwable associated with the log record.
|
||||
* <p>
|
||||
* If the event involved an exception, this will be the
|
||||
* exception object. Otherwise null.
|
||||
*
|
||||
* @return a throwable
|
||||
*/
|
||||
public Throwable getThrown() {
|
||||
return thrown;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a throwable associated with the log event.
|
||||
*
|
||||
* @param thrown a throwable (may be null)
|
||||
*/
|
||||
public void setThrown(Throwable thrown) {
|
||||
this.thrown = thrown;
|
||||
}
|
||||
|
||||
private static final long serialVersionUID = 5372048053134512534L;
|
||||
|
||||
/**
|
||||
* @serialData Default fields, followed by a two byte version number
|
||||
* (major byte, followed by minor byte), followed by information on
|
||||
* the log record parameter array. If there is no parameter array,
|
||||
* then -1 is written. If there is a parameter array (possible of zero
|
||||
* length) then the array length is written as an integer, followed
|
||||
* by String values for each parameter. If a parameter is null, then
|
||||
* a null String is written. Otherwise the output of Object.toString()
|
||||
* is written.
|
||||
*/
|
||||
private void writeObject(ObjectOutputStream out) throws IOException {
|
||||
// We have to call defaultWriteObject first.
|
||||
out.defaultWriteObject();
|
||||
|
||||
// Write our version number.
|
||||
out.writeByte(1);
|
||||
out.writeByte(0);
|
||||
if (parameters == null) {
|
||||
out.writeInt(-1);
|
||||
return;
|
||||
}
|
||||
out.writeInt(parameters.length);
|
||||
// Write string values for the parameters.
|
||||
for (int i = 0; i < parameters.length; i++) {
|
||||
if (parameters[i] == null) {
|
||||
out.writeObject(null);
|
||||
} else {
|
||||
out.writeObject(parameters[i].toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void readObject(ObjectInputStream in)
|
||||
throws IOException, ClassNotFoundException {
|
||||
// We have to call defaultReadObject first.
|
||||
in.defaultReadObject();
|
||||
|
||||
// Read version number.
|
||||
byte major = in.readByte();
|
||||
byte minor = in.readByte();
|
||||
if (major != 1) {
|
||||
throw new IOException("LogRecord: bad version: " + major + "." + minor);
|
||||
}
|
||||
int len = in.readInt();
|
||||
if (len < -1) {
|
||||
throw new NegativeArraySizeException();
|
||||
} else if (len == -1) {
|
||||
parameters = null;
|
||||
} else if (len < 255) {
|
||||
parameters = new Object[len];
|
||||
for (int i = 0; i < parameters.length; i++) {
|
||||
parameters[i] = in.readObject();
|
||||
}
|
||||
} else {
|
||||
List<Object> params = new ArrayList<>(Math.min(len, 1024));
|
||||
for (int i = 0; i < len; i++) {
|
||||
params.add(in.readObject());
|
||||
}
|
||||
parameters = params.toArray(new Object[params.size()]);
|
||||
}
|
||||
// If necessary, try to regenerate the resource bundle.
|
||||
if (resourceBundleName != null) {
|
||||
try {
|
||||
// use system class loader to ensure the ResourceBundle
|
||||
// instance is a different instance than null loader uses
|
||||
final ResourceBundle bundle =
|
||||
ResourceBundle.getBundle(resourceBundleName,
|
||||
Locale.getDefault(),
|
||||
ClassLoader.getSystemClassLoader());
|
||||
resourceBundle = bundle;
|
||||
} catch (MissingResourceException ex) {
|
||||
// This is not a good place to throw an exception,
|
||||
// so we simply leave the resourceBundle null.
|
||||
resourceBundle = null;
|
||||
}
|
||||
}
|
||||
|
||||
needToInferCaller = false;
|
||||
}
|
||||
|
||||
// Private method to infer the caller's class and method names
|
||||
private void inferCaller() {
|
||||
needToInferCaller = false;
|
||||
JavaLangAccess access = SharedSecrets.getJavaLangAccess();
|
||||
Throwable throwable = new Throwable();
|
||||
int depth = access.getStackTraceDepth(throwable);
|
||||
|
||||
boolean lookingForLogger = true;
|
||||
for (int ix = 0; ix < depth; ix++) {
|
||||
// Calling getStackTraceElement directly prevents the VM
|
||||
// from paying the cost of building the entire stack frame.
|
||||
StackTraceElement frame =
|
||||
access.getStackTraceElement(throwable, ix);
|
||||
String cname = frame.getClassName();
|
||||
boolean isLoggerImpl = isLoggerImplFrame(cname);
|
||||
if (lookingForLogger) {
|
||||
// Skip all frames until we have found the first logger frame.
|
||||
if (isLoggerImpl) {
|
||||
lookingForLogger = false;
|
||||
}
|
||||
} else {
|
||||
if (!isLoggerImpl) {
|
||||
// skip reflection call
|
||||
if (!cname.startsWith("java.lang.reflect.") && !cname.startsWith("sun.reflect.")) {
|
||||
// We've found the relevant frame.
|
||||
setSourceClassName(cname);
|
||||
setSourceMethodName(frame.getMethodName());
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// We haven't found a suitable frame, so just punt. This is
|
||||
// OK as we are only committed to making a "best effort" here.
|
||||
}
|
||||
|
||||
private boolean isLoggerImplFrame(String cname) {
|
||||
// the log record could be created for a platform logger
|
||||
return (cname.equals("java.util.logging.Logger") ||
|
||||
cname.startsWith("java.util.logging.LoggingProxyImpl") ||
|
||||
cname.startsWith("sun.util.logging."));
|
||||
}
|
||||
}
|
||||
2187
jdkSrc/jdk8/java/util/logging/Logger.java
Normal file
2187
jdkSrc/jdk8/java/util/logging/Logger.java
Normal file
File diff suppressed because it is too large
Load Diff
119
jdkSrc/jdk8/java/util/logging/Logging.java
Normal file
119
jdkSrc/jdk8/java/util/logging/Logging.java
Normal file
@@ -0,0 +1,119 @@
|
||||
/*
|
||||
* Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code 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
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package java.util.logging;
|
||||
|
||||
import java.util.Enumeration;
|
||||
import java.util.List;
|
||||
import java.util.ArrayList;
|
||||
|
||||
/**
|
||||
* Logging is the implementation class of LoggingMXBean.
|
||||
*
|
||||
* The <tt>LoggingMXBean</tt> interface provides a standard
|
||||
* method for management access to the individual
|
||||
* {@code Logger} objects available at runtime.
|
||||
*
|
||||
* @author Ron Mann
|
||||
* @author Mandy Chung
|
||||
* @since 1.5
|
||||
*
|
||||
* @see javax.management
|
||||
* @see Logger
|
||||
* @see LogManager
|
||||
*/
|
||||
class Logging implements LoggingMXBean {
|
||||
|
||||
private static LogManager logManager = LogManager.getLogManager();
|
||||
|
||||
/** Constructor of Logging which is the implementation class
|
||||
* of LoggingMXBean.
|
||||
*/
|
||||
Logging() {
|
||||
}
|
||||
|
||||
public List<String> getLoggerNames() {
|
||||
Enumeration<String> loggers = logManager.getLoggerNames();
|
||||
ArrayList<String> array = new ArrayList<>();
|
||||
|
||||
for (; loggers.hasMoreElements();) {
|
||||
array.add(loggers.nextElement());
|
||||
}
|
||||
return array;
|
||||
}
|
||||
|
||||
private static String EMPTY_STRING = "";
|
||||
public String getLoggerLevel(String loggerName) {
|
||||
Logger l = logManager.getLogger(loggerName);
|
||||
if (l == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
Level level = l.getLevel();
|
||||
if (level == null) {
|
||||
return EMPTY_STRING;
|
||||
} else {
|
||||
return level.getLevelName();
|
||||
}
|
||||
}
|
||||
|
||||
public void setLoggerLevel(String loggerName, String levelName) {
|
||||
if (loggerName == null) {
|
||||
throw new NullPointerException("loggerName is null");
|
||||
}
|
||||
|
||||
Logger logger = logManager.getLogger(loggerName);
|
||||
if (logger == null) {
|
||||
throw new IllegalArgumentException("Logger " + loggerName +
|
||||
"does not exist");
|
||||
}
|
||||
|
||||
Level level = null;
|
||||
if (levelName != null) {
|
||||
// parse will throw IAE if logLevel is invalid
|
||||
level = Level.findLevel(levelName);
|
||||
if (level == null) {
|
||||
throw new IllegalArgumentException("Unknown level \"" + levelName + "\"");
|
||||
}
|
||||
}
|
||||
|
||||
logger.setLevel(level);
|
||||
}
|
||||
|
||||
public String getParentLoggerName( String loggerName ) {
|
||||
Logger l = logManager.getLogger( loggerName );
|
||||
if (l == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
Logger p = l.getParent();
|
||||
if (p == null) {
|
||||
// root logger
|
||||
return EMPTY_STRING;
|
||||
} else {
|
||||
return p.getName();
|
||||
}
|
||||
}
|
||||
}
|
||||
139
jdkSrc/jdk8/java/util/logging/LoggingMXBean.java
Normal file
139
jdkSrc/jdk8/java/util/logging/LoggingMXBean.java
Normal file
@@ -0,0 +1,139 @@
|
||||
/*
|
||||
* Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code 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
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package java.util.logging;
|
||||
|
||||
|
||||
/**
|
||||
* The management interface for the logging facility. It is recommended
|
||||
* to use the {@link java.lang.management.PlatformLoggingMXBean} management
|
||||
* interface that implements all attributes defined in this
|
||||
* {@code LoggingMXBean}. The
|
||||
* {@link java.lang.management.ManagementFactory#getPlatformMXBean(Class)
|
||||
* ManagementFactory.getPlatformMXBean} method can be used to obtain
|
||||
* the {@code PlatformLoggingMXBean} object representing the management
|
||||
* interface for logging.
|
||||
*
|
||||
* <p>There is a single global instance of the <tt>LoggingMXBean</tt>.
|
||||
* This instance is an {@link javax.management.MXBean MXBean} that
|
||||
* can be obtained by calling the {@link LogManager#getLoggingMXBean}
|
||||
* method or from the
|
||||
* {@linkplain java.lang.management.ManagementFactory#getPlatformMBeanServer
|
||||
* platform <tt>MBeanServer</tt>}.
|
||||
* <p>
|
||||
* The {@link javax.management.ObjectName ObjectName} that uniquely identifies
|
||||
* the management interface for logging within the {@code MBeanServer} is:
|
||||
* <pre>
|
||||
* {@link LogManager#LOGGING_MXBEAN_NAME java.util.logging:type=Logging}
|
||||
* </pre>
|
||||
* <p>
|
||||
* The instance registered in the platform {@code MBeanServer}
|
||||
* is also a {@link java.lang.management.PlatformLoggingMXBean}.
|
||||
*
|
||||
* @author Ron Mann
|
||||
* @author Mandy Chung
|
||||
* @since 1.5
|
||||
*
|
||||
* @see java.lang.management.PlatformLoggingMXBean
|
||||
*/
|
||||
public interface LoggingMXBean {
|
||||
|
||||
/**
|
||||
* Returns the list of currently registered logger names. This method
|
||||
* calls {@link LogManager#getLoggerNames} and returns a list
|
||||
* of the logger names.
|
||||
*
|
||||
* @return A list of <tt>String</tt> each of which is a
|
||||
* currently registered <tt>Logger</tt> name.
|
||||
*/
|
||||
public java.util.List<String> getLoggerNames();
|
||||
|
||||
/**
|
||||
* Gets the name of the log level associated with the specified logger.
|
||||
* If the specified logger does not exist, <tt>null</tt>
|
||||
* is returned.
|
||||
* This method first finds the logger of the given name and
|
||||
* then returns the name of the log level by calling:
|
||||
* <blockquote>
|
||||
* {@link Logger#getLevel Logger.getLevel()}.{@link Level#getName getName()};
|
||||
* </blockquote>
|
||||
*
|
||||
* <p>
|
||||
* If the <tt>Level</tt> of the specified logger is <tt>null</tt>,
|
||||
* which means that this logger's effective level is inherited
|
||||
* from its parent, an empty string will be returned.
|
||||
*
|
||||
* @param loggerName The name of the <tt>Logger</tt> to be retrieved.
|
||||
*
|
||||
* @return The name of the log level of the specified logger; or
|
||||
* an empty string if the log level of the specified logger
|
||||
* is <tt>null</tt>. If the specified logger does not
|
||||
* exist, <tt>null</tt> is returned.
|
||||
*
|
||||
* @see Logger#getLevel
|
||||
*/
|
||||
public String getLoggerLevel(String loggerName);
|
||||
|
||||
/**
|
||||
* Sets the specified logger to the specified new level.
|
||||
* If the <tt>levelName</tt> is not <tt>null</tt>, the level
|
||||
* of the specified logger is set to the parsed <tt>Level</tt>
|
||||
* matching the <tt>levelName</tt>.
|
||||
* If the <tt>levelName</tt> is <tt>null</tt>, the level
|
||||
* of the specified logger is set to <tt>null</tt> and
|
||||
* the effective level of the logger is inherited from
|
||||
* its nearest ancestor with a specific (non-null) level value.
|
||||
*
|
||||
* @param loggerName The name of the <tt>Logger</tt> to be set.
|
||||
* Must be non-null.
|
||||
* @param levelName The name of the level to set on the specified logger,
|
||||
* or <tt>null</tt> if setting the level to inherit
|
||||
* from its nearest ancestor.
|
||||
*
|
||||
* @throws IllegalArgumentException if the specified logger
|
||||
* does not exist, or <tt>levelName</tt> is not a valid level name.
|
||||
*
|
||||
* @throws SecurityException if a security manager exists and if
|
||||
* the caller does not have LoggingPermission("control").
|
||||
*
|
||||
* @see Logger#setLevel
|
||||
*/
|
||||
public void setLoggerLevel(String loggerName, String levelName);
|
||||
|
||||
/**
|
||||
* Returns the name of the parent for the specified logger.
|
||||
* If the specified logger does not exist, <tt>null</tt> is returned.
|
||||
* If the specified logger is the root <tt>Logger</tt> in the namespace,
|
||||
* the result will be an empty string.
|
||||
*
|
||||
* @param loggerName The name of a <tt>Logger</tt>.
|
||||
*
|
||||
* @return the name of the nearest existing parent logger;
|
||||
* an empty string if the specified logger is the root logger.
|
||||
* If the specified logger does not exist, <tt>null</tt>
|
||||
* is returned.
|
||||
*/
|
||||
public String getParentLoggerName(String loggerName);
|
||||
}
|
||||
78
jdkSrc/jdk8/java/util/logging/LoggingPermission.java
Normal file
78
jdkSrc/jdk8/java/util/logging/LoggingPermission.java
Normal file
@@ -0,0 +1,78 @@
|
||||
/*
|
||||
* Copyright (c) 2000, 2003, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code 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
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
|
||||
package java.util.logging;
|
||||
|
||||
import java.security.*;
|
||||
|
||||
/**
|
||||
* The permission which the SecurityManager will check when code
|
||||
* that is running with a SecurityManager calls one of the logging
|
||||
* control methods (such as Logger.setLevel).
|
||||
* <p>
|
||||
* Currently there is only one named LoggingPermission. This is "control"
|
||||
* and it grants the ability to control the logging configuration, for
|
||||
* example by adding or removing Handlers, by adding or removing Filters,
|
||||
* or by changing logging levels.
|
||||
* <p>
|
||||
* Programmers do not normally create LoggingPermission objects directly.
|
||||
* Instead they are created by the security policy code based on reading
|
||||
* the security policy file.
|
||||
*
|
||||
*
|
||||
* @since 1.4
|
||||
* @see java.security.BasicPermission
|
||||
* @see java.security.Permission
|
||||
* @see java.security.Permissions
|
||||
* @see java.security.PermissionCollection
|
||||
* @see java.lang.SecurityManager
|
||||
*
|
||||
*/
|
||||
|
||||
public final class LoggingPermission extends java.security.BasicPermission {
|
||||
|
||||
private static final long serialVersionUID = 63564341580231582L;
|
||||
|
||||
/**
|
||||
* Creates a new LoggingPermission object.
|
||||
*
|
||||
* @param name Permission name. Must be "control".
|
||||
* @param actions Must be either null or the empty string.
|
||||
*
|
||||
* @throws NullPointerException if <code>name</code> is <code>null</code>.
|
||||
* @throws IllegalArgumentException if <code>name</code> is empty or if
|
||||
* arguments are invalid.
|
||||
*/
|
||||
public LoggingPermission(String name, String actions) throws IllegalArgumentException {
|
||||
super(name);
|
||||
if (!name.equals("control")) {
|
||||
throw new IllegalArgumentException("name: " + name);
|
||||
}
|
||||
if (actions != null && actions.length() > 0) {
|
||||
throw new IllegalArgumentException("actions: " + actions);
|
||||
}
|
||||
}
|
||||
}
|
||||
117
jdkSrc/jdk8/java/util/logging/LoggingProxyImpl.java
Normal file
117
jdkSrc/jdk8/java/util/logging/LoggingProxyImpl.java
Normal file
@@ -0,0 +1,117 @@
|
||||
/*
|
||||
* Copyright (c) 2009, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code 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
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package java.util.logging;
|
||||
|
||||
import sun.util.logging.LoggingProxy;
|
||||
|
||||
/**
|
||||
* Implementation of LoggingProxy when java.util.logging classes exist.
|
||||
*/
|
||||
class LoggingProxyImpl implements LoggingProxy {
|
||||
static final LoggingProxy INSTANCE = new LoggingProxyImpl();
|
||||
|
||||
private LoggingProxyImpl() { }
|
||||
|
||||
@Override
|
||||
public Object getLogger(String name) {
|
||||
// always create a platform logger with the resource bundle name
|
||||
return Logger.getPlatformLogger(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getLevel(Object logger) {
|
||||
return ((Logger) logger).getLevel();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setLevel(Object logger, Object newLevel) {
|
||||
((Logger) logger).setLevel((Level) newLevel);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isLoggable(Object logger, Object level) {
|
||||
return ((Logger) logger).isLoggable((Level) level);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void log(Object logger, Object level, String msg) {
|
||||
((Logger) logger).log((Level) level, msg);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void log(Object logger, Object level, String msg, Throwable t) {
|
||||
((Logger) logger).log((Level) level, msg, t);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void log(Object logger, Object level, String msg, Object... params) {
|
||||
((Logger) logger).log((Level) level, msg, params);
|
||||
}
|
||||
|
||||
@Override
|
||||
public java.util.List<String> getLoggerNames() {
|
||||
return LogManager.getLoggingMXBean().getLoggerNames();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getLoggerLevel(String loggerName) {
|
||||
return LogManager.getLoggingMXBean().getLoggerLevel(loggerName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setLoggerLevel(String loggerName, String levelName) {
|
||||
LogManager.getLoggingMXBean().setLoggerLevel(loggerName, levelName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getParentLoggerName(String loggerName) {
|
||||
return LogManager.getLoggingMXBean().getParentLoggerName(loggerName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object parseLevel(String levelName) {
|
||||
Level level = Level.findLevel(levelName);
|
||||
if (level == null) {
|
||||
throw new IllegalArgumentException("Unknown level \"" + levelName + "\"");
|
||||
}
|
||||
return level;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getLevelName(Object level) {
|
||||
return ((Level) level).getLevelName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getLevelValue(Object level) {
|
||||
return ((Level) level).intValue();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getProperty(String key) {
|
||||
return LogManager.getLogManager().getProperty(key);
|
||||
}
|
||||
}
|
||||
292
jdkSrc/jdk8/java/util/logging/MemoryHandler.java
Normal file
292
jdkSrc/jdk8/java/util/logging/MemoryHandler.java
Normal file
@@ -0,0 +1,292 @@
|
||||
/*
|
||||
* Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code 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
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package java.util.logging;
|
||||
|
||||
/**
|
||||
* <tt>Handler</tt> that buffers requests in a circular buffer in memory.
|
||||
* <p>
|
||||
* Normally this <tt>Handler</tt> simply stores incoming <tt>LogRecords</tt>
|
||||
* into its memory buffer and discards earlier records. This buffering
|
||||
* is very cheap and avoids formatting costs. On certain trigger
|
||||
* conditions, the <tt>MemoryHandler</tt> will push out its current buffer
|
||||
* contents to a target <tt>Handler</tt>, which will typically publish
|
||||
* them to the outside world.
|
||||
* <p>
|
||||
* There are three main models for triggering a push of the buffer:
|
||||
* <ul>
|
||||
* <li>
|
||||
* An incoming <tt>LogRecord</tt> has a type that is greater than
|
||||
* a pre-defined level, the <tt>pushLevel</tt>. </li>
|
||||
* <li>
|
||||
* An external class calls the <tt>push</tt> method explicitly. </li>
|
||||
* <li>
|
||||
* A subclass overrides the <tt>log</tt> method and scans each incoming
|
||||
* <tt>LogRecord</tt> and calls <tt>push</tt> if a record matches some
|
||||
* desired criteria. </li>
|
||||
* </ul>
|
||||
* <p>
|
||||
* <b>Configuration:</b>
|
||||
* By default each <tt>MemoryHandler</tt> is initialized using the following
|
||||
* <tt>LogManager</tt> configuration properties where <tt><handler-name></tt>
|
||||
* refers to the fully-qualified class name of the handler.
|
||||
* If properties are not defined
|
||||
* (or have invalid values) then the specified default values are used.
|
||||
* If no default value is defined then a RuntimeException is thrown.
|
||||
* <ul>
|
||||
* <li> <handler-name>.level
|
||||
* specifies the level for the <tt>Handler</tt>
|
||||
* (defaults to <tt>Level.ALL</tt>). </li>
|
||||
* <li> <handler-name>.filter
|
||||
* specifies the name of a <tt>Filter</tt> class to use
|
||||
* (defaults to no <tt>Filter</tt>). </li>
|
||||
* <li> <handler-name>.size
|
||||
* defines the buffer size (defaults to 1000). </li>
|
||||
* <li> <handler-name>.push
|
||||
* defines the <tt>pushLevel</tt> (defaults to <tt>level.SEVERE</tt>). </li>
|
||||
* <li> <handler-name>.target
|
||||
* specifies the name of the target <tt>Handler </tt> class.
|
||||
* (no default). </li>
|
||||
* </ul>
|
||||
* <p>
|
||||
* For example, the properties for {@code MemoryHandler} would be:
|
||||
* <ul>
|
||||
* <li> java.util.logging.MemoryHandler.level=INFO </li>
|
||||
* <li> java.util.logging.MemoryHandler.formatter=java.util.logging.SimpleFormatter </li>
|
||||
* </ul>
|
||||
* <p>
|
||||
* For a custom handler, e.g. com.foo.MyHandler, the properties would be:
|
||||
* <ul>
|
||||
* <li> com.foo.MyHandler.level=INFO </li>
|
||||
* <li> com.foo.MyHandler.formatter=java.util.logging.SimpleFormatter </li>
|
||||
* </ul>
|
||||
* <p>
|
||||
* @since 1.4
|
||||
*/
|
||||
|
||||
public class MemoryHandler extends Handler {
|
||||
private final static int DEFAULT_SIZE = 1000;
|
||||
private volatile Level pushLevel;
|
||||
private int size;
|
||||
private Handler target;
|
||||
private LogRecord buffer[];
|
||||
int start, count;
|
||||
|
||||
// Private method to configure a MemoryHandler from LogManager
|
||||
// properties and/or default values as specified in the class
|
||||
// javadoc.
|
||||
private void configure() {
|
||||
LogManager manager = LogManager.getLogManager();
|
||||
String cname = getClass().getName();
|
||||
|
||||
pushLevel = manager.getLevelProperty(cname +".push", Level.SEVERE);
|
||||
size = manager.getIntProperty(cname + ".size", DEFAULT_SIZE);
|
||||
if (size <= 0) {
|
||||
size = DEFAULT_SIZE;
|
||||
}
|
||||
setLevel(manager.getLevelProperty(cname +".level", Level.ALL));
|
||||
setFilter(manager.getFilterProperty(cname +".filter", null));
|
||||
setFormatter(manager.getFormatterProperty(cname +".formatter", new SimpleFormatter()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a <tt>MemoryHandler</tt> and configure it based on
|
||||
* <tt>LogManager</tt> configuration properties.
|
||||
*/
|
||||
public MemoryHandler() {
|
||||
sealed = false;
|
||||
configure();
|
||||
sealed = true;
|
||||
|
||||
LogManager manager = LogManager.getLogManager();
|
||||
String handlerName = getClass().getName();
|
||||
String targetName = manager.getProperty(handlerName+".target");
|
||||
if (targetName == null) {
|
||||
throw new RuntimeException("The handler " + handlerName
|
||||
+ " does not specify a target");
|
||||
}
|
||||
Class<?> clz;
|
||||
try {
|
||||
clz = ClassLoader.getSystemClassLoader().loadClass(targetName);
|
||||
target = (Handler) clz.newInstance();
|
||||
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException e) {
|
||||
throw new RuntimeException("MemoryHandler can't load handler target \"" + targetName + "\"" , e);
|
||||
}
|
||||
init();
|
||||
}
|
||||
|
||||
// Initialize. Size is a count of LogRecords.
|
||||
private void init() {
|
||||
buffer = new LogRecord[size];
|
||||
start = 0;
|
||||
count = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a <tt>MemoryHandler</tt>.
|
||||
* <p>
|
||||
* The <tt>MemoryHandler</tt> is configured based on <tt>LogManager</tt>
|
||||
* properties (or their default values) except that the given <tt>pushLevel</tt>
|
||||
* argument and buffer size argument are used.
|
||||
*
|
||||
* @param target the Handler to which to publish output.
|
||||
* @param size the number of log records to buffer (must be greater than zero)
|
||||
* @param pushLevel message level to push on
|
||||
*
|
||||
* @throws IllegalArgumentException if {@code size is <= 0}
|
||||
*/
|
||||
public MemoryHandler(Handler target, int size, Level pushLevel) {
|
||||
if (target == null || pushLevel == null) {
|
||||
throw new NullPointerException();
|
||||
}
|
||||
if (size <= 0) {
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
sealed = false;
|
||||
configure();
|
||||
sealed = true;
|
||||
this.target = target;
|
||||
this.pushLevel = pushLevel;
|
||||
this.size = size;
|
||||
init();
|
||||
}
|
||||
|
||||
/**
|
||||
* Store a <tt>LogRecord</tt> in an internal buffer.
|
||||
* <p>
|
||||
* If there is a <tt>Filter</tt>, its <tt>isLoggable</tt>
|
||||
* method is called to check if the given log record is loggable.
|
||||
* If not we return. Otherwise the given record is copied into
|
||||
* an internal circular buffer. Then the record's level property is
|
||||
* compared with the <tt>pushLevel</tt>. If the given level is
|
||||
* greater than or equal to the <tt>pushLevel</tt> then <tt>push</tt>
|
||||
* is called to write all buffered records to the target output
|
||||
* <tt>Handler</tt>.
|
||||
*
|
||||
* @param record description of the log event. A null record is
|
||||
* silently ignored and is not published
|
||||
*/
|
||||
@Override
|
||||
public synchronized void publish(LogRecord record) {
|
||||
if (!isLoggable(record)) {
|
||||
return;
|
||||
}
|
||||
int ix = (start+count)%buffer.length;
|
||||
buffer[ix] = record;
|
||||
if (count < buffer.length) {
|
||||
count++;
|
||||
} else {
|
||||
start++;
|
||||
start %= buffer.length;
|
||||
}
|
||||
if (record.getLevel().intValue() >= pushLevel.intValue()) {
|
||||
push();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Push any buffered output to the target <tt>Handler</tt>.
|
||||
* <p>
|
||||
* The buffer is then cleared.
|
||||
*/
|
||||
public synchronized void push() {
|
||||
for (int i = 0; i < count; i++) {
|
||||
int ix = (start+i)%buffer.length;
|
||||
LogRecord record = buffer[ix];
|
||||
target.publish(record);
|
||||
}
|
||||
// Empty the buffer.
|
||||
start = 0;
|
||||
count = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Causes a flush on the target <tt>Handler</tt>.
|
||||
* <p>
|
||||
* Note that the current contents of the <tt>MemoryHandler</tt>
|
||||
* buffer are <b>not</b> written out. That requires a "push".
|
||||
*/
|
||||
@Override
|
||||
public void flush() {
|
||||
target.flush();
|
||||
}
|
||||
|
||||
/**
|
||||
* Close the <tt>Handler</tt> and free all associated resources.
|
||||
* This will also close the target <tt>Handler</tt>.
|
||||
*
|
||||
* @exception SecurityException if a security manager exists and if
|
||||
* the caller does not have <tt>LoggingPermission("control")</tt>.
|
||||
*/
|
||||
@Override
|
||||
public void close() throws SecurityException {
|
||||
target.close();
|
||||
setLevel(Level.OFF);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the <tt>pushLevel</tt>. After a <tt>LogRecord</tt> is copied
|
||||
* into our internal buffer, if its level is greater than or equal to
|
||||
* the <tt>pushLevel</tt>, then <tt>push</tt> will be called.
|
||||
*
|
||||
* @param newLevel the new value of the <tt>pushLevel</tt>
|
||||
* @exception SecurityException if a security manager exists and if
|
||||
* the caller does not have <tt>LoggingPermission("control")</tt>.
|
||||
*/
|
||||
public synchronized void setPushLevel(Level newLevel) throws SecurityException {
|
||||
if (newLevel == null) {
|
||||
throw new NullPointerException();
|
||||
}
|
||||
checkPermission();
|
||||
pushLevel = newLevel;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the <tt>pushLevel</tt>.
|
||||
*
|
||||
* @return the value of the <tt>pushLevel</tt>
|
||||
*/
|
||||
public Level getPushLevel() {
|
||||
return pushLevel;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if this <tt>Handler</tt> would actually log a given
|
||||
* <tt>LogRecord</tt> into its internal buffer.
|
||||
* <p>
|
||||
* This method checks if the <tt>LogRecord</tt> has an appropriate level and
|
||||
* whether it satisfies any <tt>Filter</tt>. However it does <b>not</b>
|
||||
* check whether the <tt>LogRecord</tt> would result in a "push" of the
|
||||
* buffer contents. It will return false if the <tt>LogRecord</tt> is null.
|
||||
* <p>
|
||||
* @param record a <tt>LogRecord</tt>
|
||||
* @return true if the <tt>LogRecord</tt> would be logged.
|
||||
*
|
||||
*/
|
||||
@Override
|
||||
public boolean isLoggable(LogRecord record) {
|
||||
return super.isLoggable(record);
|
||||
}
|
||||
}
|
||||
169
jdkSrc/jdk8/java/util/logging/SimpleFormatter.java
Normal file
169
jdkSrc/jdk8/java/util/logging/SimpleFormatter.java
Normal file
@@ -0,0 +1,169 @@
|
||||
/*
|
||||
* Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code 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
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
|
||||
package java.util.logging;
|
||||
|
||||
import java.io.*;
|
||||
import java.text.*;
|
||||
import java.util.Date;
|
||||
import sun.util.logging.LoggingSupport;
|
||||
|
||||
/**
|
||||
* Print a brief summary of the {@code LogRecord} in a human readable
|
||||
* format. The summary will typically be 1 or 2 lines.
|
||||
*
|
||||
* <p>
|
||||
* <a name="formatting">
|
||||
* <b>Configuration:</b></a>
|
||||
* The {@code SimpleFormatter} is initialized with the
|
||||
* <a href="../Formatter.html#syntax">format string</a>
|
||||
* specified in the {@code java.util.logging.SimpleFormatter.format}
|
||||
* property to {@linkplain #format format} the log messages.
|
||||
* This property can be defined
|
||||
* in the {@linkplain LogManager#getProperty logging properties}
|
||||
* configuration file
|
||||
* or as a system property. If this property is set in both
|
||||
* the logging properties and system properties,
|
||||
* the format string specified in the system property will be used.
|
||||
* If this property is not defined or the given format string
|
||||
* is {@linkplain java.util.IllegalFormatException illegal},
|
||||
* the default format is implementation-specific.
|
||||
*
|
||||
* @since 1.4
|
||||
* @see java.util.Formatter
|
||||
*/
|
||||
|
||||
public class SimpleFormatter extends Formatter {
|
||||
|
||||
// format string for printing the log record
|
||||
private static final String format = LoggingSupport.getSimpleFormat();
|
||||
private final Date dat = new Date();
|
||||
|
||||
/**
|
||||
* Format the given LogRecord.
|
||||
* <p>
|
||||
* The formatting can be customized by specifying the
|
||||
* <a href="../Formatter.html#syntax">format string</a>
|
||||
* in the <a href="#formatting">
|
||||
* {@code java.util.logging.SimpleFormatter.format}</a> property.
|
||||
* The given {@code LogRecord} will be formatted as if by calling:
|
||||
* <pre>
|
||||
* {@link String#format String.format}(format, date, source, logger, level, message, thrown);
|
||||
* </pre>
|
||||
* where the arguments are:<br>
|
||||
* <ol>
|
||||
* <li>{@code format} - the {@link java.util.Formatter
|
||||
* java.util.Formatter} format string specified in the
|
||||
* {@code java.util.logging.SimpleFormatter.format} property
|
||||
* or the default format.</li>
|
||||
* <li>{@code date} - a {@link Date} object representing
|
||||
* {@linkplain LogRecord#getMillis event time} of the log record.</li>
|
||||
* <li>{@code source} - a string representing the caller, if available;
|
||||
* otherwise, the logger's name.</li>
|
||||
* <li>{@code logger} - the logger's name.</li>
|
||||
* <li>{@code level} - the {@linkplain Level#getLocalizedName
|
||||
* log level}.</li>
|
||||
* <li>{@code message} - the formatted log message
|
||||
* returned from the {@link Formatter#formatMessage(LogRecord)}
|
||||
* method. It uses {@link java.text.MessageFormat java.text}
|
||||
* formatting and does not use the {@code java.util.Formatter
|
||||
* format} argument.</li>
|
||||
* <li>{@code thrown} - a string representing
|
||||
* the {@linkplain LogRecord#getThrown throwable}
|
||||
* associated with the log record and its backtrace
|
||||
* beginning with a newline character, if any;
|
||||
* otherwise, an empty string.</li>
|
||||
* </ol>
|
||||
*
|
||||
* <p>Some example formats:<br>
|
||||
* <ul>
|
||||
* <li> {@code java.util.logging.SimpleFormatter.format="%4$s: %5$s [%1$tc]%n"}
|
||||
* <p>This prints 1 line with the log level ({@code 4$}),
|
||||
* the log message ({@code 5$}) and the timestamp ({@code 1$}) in
|
||||
* a square bracket.
|
||||
* <pre>
|
||||
* WARNING: warning message [Tue Mar 22 13:11:31 PDT 2011]
|
||||
* </pre></li>
|
||||
* <li> {@code java.util.logging.SimpleFormatter.format="%1$tc %2$s%n%4$s: %5$s%6$s%n"}
|
||||
* <p>This prints 2 lines where the first line includes
|
||||
* the timestamp ({@code 1$}) and the source ({@code 2$});
|
||||
* the second line includes the log level ({@code 4$}) and
|
||||
* the log message ({@code 5$}) followed with the throwable
|
||||
* and its backtrace ({@code 6$}), if any:
|
||||
* <pre>
|
||||
* Tue Mar 22 13:11:31 PDT 2011 MyClass fatal
|
||||
* SEVERE: several message with an exception
|
||||
* java.lang.IllegalArgumentException: invalid argument
|
||||
* at MyClass.mash(MyClass.java:9)
|
||||
* at MyClass.crunch(MyClass.java:6)
|
||||
* at MyClass.main(MyClass.java:3)
|
||||
* </pre></li>
|
||||
* <li> {@code java.util.logging.SimpleFormatter.format="%1$tb %1$td, %1$tY %1$tl:%1$tM:%1$tS %1$Tp %2$s%n%4$s: %5$s%n"}
|
||||
* <p>This prints 2 lines similar to the example above
|
||||
* with a different date/time formatting and does not print
|
||||
* the throwable and its backtrace:
|
||||
* <pre>
|
||||
* Mar 22, 2011 1:11:31 PM MyClass fatal
|
||||
* SEVERE: several message with an exception
|
||||
* </pre></li>
|
||||
* </ul>
|
||||
* <p>This method can also be overridden in a subclass.
|
||||
* It is recommended to use the {@link Formatter#formatMessage}
|
||||
* convenience method to localize and format the message field.
|
||||
*
|
||||
* @param record the log record to be formatted.
|
||||
* @return a formatted log record
|
||||
*/
|
||||
public synchronized String format(LogRecord record) {
|
||||
dat.setTime(record.getMillis());
|
||||
String source;
|
||||
if (record.getSourceClassName() != null) {
|
||||
source = record.getSourceClassName();
|
||||
if (record.getSourceMethodName() != null) {
|
||||
source += " " + record.getSourceMethodName();
|
||||
}
|
||||
} else {
|
||||
source = record.getLoggerName();
|
||||
}
|
||||
String message = formatMessage(record);
|
||||
String throwable = "";
|
||||
if (record.getThrown() != null) {
|
||||
StringWriter sw = new StringWriter();
|
||||
PrintWriter pw = new PrintWriter(sw);
|
||||
pw.println();
|
||||
record.getThrown().printStackTrace(pw);
|
||||
pw.close();
|
||||
throwable = sw.toString();
|
||||
}
|
||||
return String.format(format,
|
||||
dat,
|
||||
source,
|
||||
record.getLoggerName(),
|
||||
record.getLevel().getLocalizedLevelName(),
|
||||
message,
|
||||
throwable);
|
||||
}
|
||||
}
|
||||
206
jdkSrc/jdk8/java/util/logging/SocketHandler.java
Normal file
206
jdkSrc/jdk8/java/util/logging/SocketHandler.java
Normal file
@@ -0,0 +1,206 @@
|
||||
/*
|
||||
* Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code 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
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
|
||||
package java.util.logging;
|
||||
|
||||
import java.io.*;
|
||||
import java.net.*;
|
||||
|
||||
/**
|
||||
* Simple network logging <tt>Handler</tt>.
|
||||
* <p>
|
||||
* <tt>LogRecords</tt> are published to a network stream connection. By default
|
||||
* the <tt>XMLFormatter</tt> class is used for formatting.
|
||||
* <p>
|
||||
* <b>Configuration:</b>
|
||||
* By default each <tt>SocketHandler</tt> is initialized using the following
|
||||
* <tt>LogManager</tt> configuration properties where <tt><handler-name></tt>
|
||||
* refers to the fully-qualified class name of the handler.
|
||||
* If properties are not defined
|
||||
* (or have invalid values) then the specified default values are used.
|
||||
* <ul>
|
||||
* <li> <handler-name>.level
|
||||
* specifies the default level for the <tt>Handler</tt>
|
||||
* (defaults to <tt>Level.ALL</tt>). </li>
|
||||
* <li> <handler-name>.filter
|
||||
* specifies the name of a <tt>Filter</tt> class to use
|
||||
* (defaults to no <tt>Filter</tt>). </li>
|
||||
* <li> <handler-name>.formatter
|
||||
* specifies the name of a <tt>Formatter</tt> class to use
|
||||
* (defaults to <tt>java.util.logging.XMLFormatter</tt>). </li>
|
||||
* <li> <handler-name>.encoding
|
||||
* the name of the character set encoding to use (defaults to
|
||||
* the default platform encoding). </li>
|
||||
* <li> <handler-name>.host
|
||||
* specifies the target host name to connect to (no default). </li>
|
||||
* <li> <handler-name>.port
|
||||
* specifies the target TCP port to use (no default). </li>
|
||||
* </ul>
|
||||
* <p>
|
||||
* For example, the properties for {@code SocketHandler} would be:
|
||||
* <ul>
|
||||
* <li> java.util.logging.SocketHandler.level=INFO </li>
|
||||
* <li> java.util.logging.SocketHandler.formatter=java.util.logging.SimpleFormatter </li>
|
||||
* </ul>
|
||||
* <p>
|
||||
* For a custom handler, e.g. com.foo.MyHandler, the properties would be:
|
||||
* <ul>
|
||||
* <li> com.foo.MyHandler.level=INFO </li>
|
||||
* <li> com.foo.MyHandler.formatter=java.util.logging.SimpleFormatter </li>
|
||||
* </ul>
|
||||
* <p>
|
||||
* The output IO stream is buffered, but is flushed after each
|
||||
* <tt>LogRecord</tt> is written.
|
||||
*
|
||||
* @since 1.4
|
||||
*/
|
||||
|
||||
public class SocketHandler extends StreamHandler {
|
||||
private Socket sock;
|
||||
private String host;
|
||||
private int port;
|
||||
|
||||
// Private method to configure a SocketHandler from LogManager
|
||||
// properties and/or default values as specified in the class
|
||||
// javadoc.
|
||||
private void configure() {
|
||||
LogManager manager = LogManager.getLogManager();
|
||||
String cname = getClass().getName();
|
||||
|
||||
setLevel(manager.getLevelProperty(cname +".level", Level.ALL));
|
||||
setFilter(manager.getFilterProperty(cname +".filter", null));
|
||||
setFormatter(manager.getFormatterProperty(cname +".formatter", new XMLFormatter()));
|
||||
try {
|
||||
setEncoding(manager.getStringProperty(cname +".encoding", null));
|
||||
} catch (Exception ex) {
|
||||
try {
|
||||
setEncoding(null);
|
||||
} catch (Exception ex2) {
|
||||
// doing a setEncoding with null should always work.
|
||||
// assert false;
|
||||
}
|
||||
}
|
||||
port = manager.getIntProperty(cname + ".port", 0);
|
||||
host = manager.getStringProperty(cname + ".host", null);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Create a <tt>SocketHandler</tt>, using only <tt>LogManager</tt> properties
|
||||
* (or their defaults).
|
||||
* @throws IllegalArgumentException if the host or port are invalid or
|
||||
* are not specified as LogManager properties.
|
||||
* @throws IOException if we are unable to connect to the target
|
||||
* host and port.
|
||||
*/
|
||||
public SocketHandler() throws IOException {
|
||||
// We are going to use the logging defaults.
|
||||
sealed = false;
|
||||
configure();
|
||||
|
||||
try {
|
||||
connect();
|
||||
} catch (IOException ix) {
|
||||
System.err.println("SocketHandler: connect failed to " + host + ":" + port);
|
||||
throw ix;
|
||||
}
|
||||
sealed = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct a <tt>SocketHandler</tt> using a specified host and port.
|
||||
*
|
||||
* The <tt>SocketHandler</tt> is configured based on <tt>LogManager</tt>
|
||||
* properties (or their default values) except that the given target host
|
||||
* and port arguments are used. If the host argument is empty, but not
|
||||
* null String then the localhost is used.
|
||||
*
|
||||
* @param host target host.
|
||||
* @param port target port.
|
||||
*
|
||||
* @throws IllegalArgumentException if the host or port are invalid.
|
||||
* @throws IOException if we are unable to connect to the target
|
||||
* host and port.
|
||||
*/
|
||||
public SocketHandler(String host, int port) throws IOException {
|
||||
sealed = false;
|
||||
configure();
|
||||
sealed = true;
|
||||
this.port = port;
|
||||
this.host = host;
|
||||
connect();
|
||||
}
|
||||
|
||||
private void connect() throws IOException {
|
||||
// Check the arguments are valid.
|
||||
if (port == 0) {
|
||||
throw new IllegalArgumentException("Bad port: " + port);
|
||||
}
|
||||
if (host == null) {
|
||||
throw new IllegalArgumentException("Null host name: " + host);
|
||||
}
|
||||
|
||||
// Try to open a new socket.
|
||||
sock = new Socket(host, port);
|
||||
OutputStream out = sock.getOutputStream();
|
||||
BufferedOutputStream bout = new BufferedOutputStream(out);
|
||||
setOutputStream(bout);
|
||||
}
|
||||
|
||||
/**
|
||||
* Close this output stream.
|
||||
*
|
||||
* @exception SecurityException if a security manager exists and if
|
||||
* the caller does not have <tt>LoggingPermission("control")</tt>.
|
||||
*/
|
||||
@Override
|
||||
public synchronized void close() throws SecurityException {
|
||||
super.close();
|
||||
if (sock != null) {
|
||||
try {
|
||||
sock.close();
|
||||
} catch (IOException ix) {
|
||||
// drop through.
|
||||
}
|
||||
}
|
||||
sock = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Format and publish a <tt>LogRecord</tt>.
|
||||
*
|
||||
* @param record description of the log event. A null record is
|
||||
* silently ignored and is not published
|
||||
*/
|
||||
@Override
|
||||
public synchronized void publish(LogRecord record) {
|
||||
if (!isLoggable(record)) {
|
||||
return;
|
||||
}
|
||||
super.publish(record);
|
||||
flush();
|
||||
}
|
||||
}
|
||||
304
jdkSrc/jdk8/java/util/logging/StreamHandler.java
Normal file
304
jdkSrc/jdk8/java/util/logging/StreamHandler.java
Normal file
@@ -0,0 +1,304 @@
|
||||
/*
|
||||
* Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code 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
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
|
||||
package java.util.logging;
|
||||
|
||||
import java.io.*;
|
||||
|
||||
/**
|
||||
* Stream based logging <tt>Handler</tt>.
|
||||
* <p>
|
||||
* This is primarily intended as a base class or support class to
|
||||
* be used in implementing other logging <tt>Handlers</tt>.
|
||||
* <p>
|
||||
* <tt>LogRecords</tt> are published to a given <tt>java.io.OutputStream</tt>.
|
||||
* <p>
|
||||
* <b>Configuration:</b>
|
||||
* By default each <tt>StreamHandler</tt> is initialized using the following
|
||||
* <tt>LogManager</tt> configuration properties where <tt><handler-name></tt>
|
||||
* refers to the fully-qualified class name of the handler.
|
||||
* If properties are not defined
|
||||
* (or have invalid values) then the specified default values are used.
|
||||
* <ul>
|
||||
* <li> <handler-name>.level
|
||||
* specifies the default level for the <tt>Handler</tt>
|
||||
* (defaults to <tt>Level.INFO</tt>). </li>
|
||||
* <li> <handler-name>.filter
|
||||
* specifies the name of a <tt>Filter</tt> class to use
|
||||
* (defaults to no <tt>Filter</tt>). </li>
|
||||
* <li> <handler-name>.formatter
|
||||
* specifies the name of a <tt>Formatter</tt> class to use
|
||||
* (defaults to <tt>java.util.logging.SimpleFormatter</tt>). </li>
|
||||
* <li> <handler-name>.encoding
|
||||
* the name of the character set encoding to use (defaults to
|
||||
* the default platform encoding). </li>
|
||||
* </ul>
|
||||
* <p>
|
||||
* For example, the properties for {@code StreamHandler} would be:
|
||||
* <ul>
|
||||
* <li> java.util.logging.StreamHandler.level=INFO </li>
|
||||
* <li> java.util.logging.StreamHandler.formatter=java.util.logging.SimpleFormatter </li>
|
||||
* </ul>
|
||||
* <p>
|
||||
* For a custom handler, e.g. com.foo.MyHandler, the properties would be:
|
||||
* <ul>
|
||||
* <li> com.foo.MyHandler.level=INFO </li>
|
||||
* <li> com.foo.MyHandler.formatter=java.util.logging.SimpleFormatter </li>
|
||||
* </ul>
|
||||
* <p>
|
||||
* @since 1.4
|
||||
*/
|
||||
|
||||
public class StreamHandler extends Handler {
|
||||
private OutputStream output;
|
||||
private boolean doneHeader;
|
||||
private volatile Writer writer;
|
||||
|
||||
// Private method to configure a StreamHandler from LogManager
|
||||
// properties and/or default values as specified in the class
|
||||
// javadoc.
|
||||
private void configure() {
|
||||
LogManager manager = LogManager.getLogManager();
|
||||
String cname = getClass().getName();
|
||||
|
||||
setLevel(manager.getLevelProperty(cname +".level", Level.INFO));
|
||||
setFilter(manager.getFilterProperty(cname +".filter", null));
|
||||
setFormatter(manager.getFormatterProperty(cname +".formatter", new SimpleFormatter()));
|
||||
try {
|
||||
setEncoding(manager.getStringProperty(cname +".encoding", null));
|
||||
} catch (Exception ex) {
|
||||
try {
|
||||
setEncoding(null);
|
||||
} catch (Exception ex2) {
|
||||
// doing a setEncoding with null should always work.
|
||||
// assert false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a <tt>StreamHandler</tt>, with no current output stream.
|
||||
*/
|
||||
public StreamHandler() {
|
||||
sealed = false;
|
||||
configure();
|
||||
sealed = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a <tt>StreamHandler</tt> with a given <tt>Formatter</tt>
|
||||
* and output stream.
|
||||
* <p>
|
||||
* @param out the target output stream
|
||||
* @param formatter Formatter to be used to format output
|
||||
*/
|
||||
public StreamHandler(OutputStream out, Formatter formatter) {
|
||||
sealed = false;
|
||||
configure();
|
||||
setFormatter(formatter);
|
||||
setOutputStream(out);
|
||||
sealed = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Change the output stream.
|
||||
* <P>
|
||||
* If there is a current output stream then the <tt>Formatter</tt>'s
|
||||
* tail string is written and the stream is flushed and closed.
|
||||
* Then the output stream is replaced with the new output stream.
|
||||
*
|
||||
* @param out New output stream. May not be null.
|
||||
* @exception SecurityException if a security manager exists and if
|
||||
* the caller does not have <tt>LoggingPermission("control")</tt>.
|
||||
*/
|
||||
protected synchronized void setOutputStream(OutputStream out) throws SecurityException {
|
||||
if (out == null) {
|
||||
throw new NullPointerException();
|
||||
}
|
||||
flushAndClose();
|
||||
output = out;
|
||||
doneHeader = false;
|
||||
String encoding = getEncoding();
|
||||
if (encoding == null) {
|
||||
writer = new OutputStreamWriter(output);
|
||||
} else {
|
||||
try {
|
||||
writer = new OutputStreamWriter(output, encoding);
|
||||
} catch (UnsupportedEncodingException ex) {
|
||||
// This shouldn't happen. The setEncoding method
|
||||
// should have validated that the encoding is OK.
|
||||
throw new Error("Unexpected exception " + ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set (or change) the character encoding used by this <tt>Handler</tt>.
|
||||
* <p>
|
||||
* The encoding should be set before any <tt>LogRecords</tt> are written
|
||||
* to the <tt>Handler</tt>.
|
||||
*
|
||||
* @param encoding The name of a supported character encoding.
|
||||
* May be null, to indicate the default platform encoding.
|
||||
* @exception SecurityException if a security manager exists and if
|
||||
* the caller does not have <tt>LoggingPermission("control")</tt>.
|
||||
* @exception UnsupportedEncodingException if the named encoding is
|
||||
* not supported.
|
||||
*/
|
||||
@Override
|
||||
public synchronized void setEncoding(String encoding)
|
||||
throws SecurityException, java.io.UnsupportedEncodingException {
|
||||
super.setEncoding(encoding);
|
||||
if (output == null) {
|
||||
return;
|
||||
}
|
||||
// Replace the current writer with a writer for the new encoding.
|
||||
flush();
|
||||
if (encoding == null) {
|
||||
writer = new OutputStreamWriter(output);
|
||||
} else {
|
||||
writer = new OutputStreamWriter(output, encoding);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Format and publish a <tt>LogRecord</tt>.
|
||||
* <p>
|
||||
* The <tt>StreamHandler</tt> first checks if there is an <tt>OutputStream</tt>
|
||||
* and if the given <tt>LogRecord</tt> has at least the required log level.
|
||||
* If not it silently returns. If so, it calls any associated
|
||||
* <tt>Filter</tt> to check if the record should be published. If so,
|
||||
* it calls its <tt>Formatter</tt> to format the record and then writes
|
||||
* the result to the current output stream.
|
||||
* <p>
|
||||
* If this is the first <tt>LogRecord</tt> to be written to a given
|
||||
* <tt>OutputStream</tt>, the <tt>Formatter</tt>'s "head" string is
|
||||
* written to the stream before the <tt>LogRecord</tt> is written.
|
||||
*
|
||||
* @param record description of the log event. A null record is
|
||||
* silently ignored and is not published
|
||||
*/
|
||||
@Override
|
||||
public synchronized void publish(LogRecord record) {
|
||||
if (!isLoggable(record)) {
|
||||
return;
|
||||
}
|
||||
String msg;
|
||||
try {
|
||||
msg = getFormatter().format(record);
|
||||
} catch (Exception ex) {
|
||||
// We don't want to throw an exception here, but we
|
||||
// report the exception to any registered ErrorManager.
|
||||
reportError(null, ex, ErrorManager.FORMAT_FAILURE);
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
if (!doneHeader) {
|
||||
writer.write(getFormatter().getHead(this));
|
||||
doneHeader = true;
|
||||
}
|
||||
writer.write(msg);
|
||||
} catch (Exception ex) {
|
||||
// We don't want to throw an exception here, but we
|
||||
// report the exception to any registered ErrorManager.
|
||||
reportError(null, ex, ErrorManager.WRITE_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Check if this <tt>Handler</tt> would actually log a given <tt>LogRecord</tt>.
|
||||
* <p>
|
||||
* This method checks if the <tt>LogRecord</tt> has an appropriate level and
|
||||
* whether it satisfies any <tt>Filter</tt>. It will also return false if
|
||||
* no output stream has been assigned yet or the LogRecord is null.
|
||||
* <p>
|
||||
* @param record a <tt>LogRecord</tt>
|
||||
* @return true if the <tt>LogRecord</tt> would be logged.
|
||||
*
|
||||
*/
|
||||
@Override
|
||||
public boolean isLoggable(LogRecord record) {
|
||||
if (writer == null || record == null) {
|
||||
return false;
|
||||
}
|
||||
return super.isLoggable(record);
|
||||
}
|
||||
|
||||
/**
|
||||
* Flush any buffered messages.
|
||||
*/
|
||||
@Override
|
||||
public synchronized void flush() {
|
||||
if (writer != null) {
|
||||
try {
|
||||
writer.flush();
|
||||
} catch (Exception ex) {
|
||||
// We don't want to throw an exception here, but we
|
||||
// report the exception to any registered ErrorManager.
|
||||
reportError(null, ex, ErrorManager.FLUSH_FAILURE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private synchronized void flushAndClose() throws SecurityException {
|
||||
checkPermission();
|
||||
if (writer != null) {
|
||||
try {
|
||||
if (!doneHeader) {
|
||||
writer.write(getFormatter().getHead(this));
|
||||
doneHeader = true;
|
||||
}
|
||||
writer.write(getFormatter().getTail(this));
|
||||
writer.flush();
|
||||
writer.close();
|
||||
} catch (Exception ex) {
|
||||
// We don't want to throw an exception here, but we
|
||||
// report the exception to any registered ErrorManager.
|
||||
reportError(null, ex, ErrorManager.CLOSE_FAILURE);
|
||||
}
|
||||
writer = null;
|
||||
output = null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Close the current output stream.
|
||||
* <p>
|
||||
* The <tt>Formatter</tt>'s "tail" string is written to the stream before it
|
||||
* is closed. In addition, if the <tt>Formatter</tt>'s "head" string has not
|
||||
* yet been written to the stream, it will be written before the
|
||||
* "tail" string.
|
||||
*
|
||||
* @exception SecurityException if a security manager exists and if
|
||||
* the caller does not have LoggingPermission("control").
|
||||
*/
|
||||
@Override
|
||||
public synchronized void close() throws SecurityException {
|
||||
flushAndClose();
|
||||
}
|
||||
}
|
||||
269
jdkSrc/jdk8/java/util/logging/XMLFormatter.java
Normal file
269
jdkSrc/jdk8/java/util/logging/XMLFormatter.java
Normal file
@@ -0,0 +1,269 @@
|
||||
/*
|
||||
* Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code 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
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
|
||||
package java.util.logging;
|
||||
|
||||
import java.io.*;
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* Format a LogRecord into a standard XML format.
|
||||
* <p>
|
||||
* The DTD specification is provided as Appendix A to the
|
||||
* Java Logging APIs specification.
|
||||
* <p>
|
||||
* The XMLFormatter can be used with arbitrary character encodings,
|
||||
* but it is recommended that it normally be used with UTF-8. The
|
||||
* character encoding can be set on the output Handler.
|
||||
*
|
||||
* @since 1.4
|
||||
*/
|
||||
|
||||
public class XMLFormatter extends Formatter {
|
||||
private LogManager manager = LogManager.getLogManager();
|
||||
|
||||
// Append a two digit number.
|
||||
private void a2(StringBuilder sb, int x) {
|
||||
if (x < 10) {
|
||||
sb.append('0');
|
||||
}
|
||||
sb.append(x);
|
||||
}
|
||||
|
||||
// Append the time and date in ISO 8601 format
|
||||
private void appendISO8601(StringBuilder sb, long millis) {
|
||||
GregorianCalendar cal = new GregorianCalendar();
|
||||
cal.setTimeInMillis(millis);
|
||||
sb.append(cal.get(Calendar.YEAR));
|
||||
sb.append('-');
|
||||
a2(sb, cal.get(Calendar.MONTH) + 1);
|
||||
sb.append('-');
|
||||
a2(sb, cal.get(Calendar.DAY_OF_MONTH));
|
||||
sb.append('T');
|
||||
a2(sb, cal.get(Calendar.HOUR_OF_DAY));
|
||||
sb.append(':');
|
||||
a2(sb, cal.get(Calendar.MINUTE));
|
||||
sb.append(':');
|
||||
a2(sb, cal.get(Calendar.SECOND));
|
||||
}
|
||||
|
||||
// Append to the given StringBuilder an escaped version of the
|
||||
// given text string where XML special characters have been escaped.
|
||||
// For a null string we append "<null>"
|
||||
private void escape(StringBuilder sb, String text) {
|
||||
if (text == null) {
|
||||
text = "<null>";
|
||||
}
|
||||
for (int i = 0; i < text.length(); i++) {
|
||||
char ch = text.charAt(i);
|
||||
if (ch == '<') {
|
||||
sb.append("<");
|
||||
} else if (ch == '>') {
|
||||
sb.append(">");
|
||||
} else if (ch == '&') {
|
||||
sb.append("&");
|
||||
} else {
|
||||
sb.append(ch);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Format the given message to XML.
|
||||
* <p>
|
||||
* This method can be overridden in a subclass.
|
||||
* It is recommended to use the {@link Formatter#formatMessage}
|
||||
* convenience method to localize and format the message field.
|
||||
*
|
||||
* @param record the log record to be formatted.
|
||||
* @return a formatted log record
|
||||
*/
|
||||
public String format(LogRecord record) {
|
||||
StringBuilder sb = new StringBuilder(500);
|
||||
sb.append("<record>\n");
|
||||
|
||||
sb.append(" <date>");
|
||||
appendISO8601(sb, record.getMillis());
|
||||
sb.append("</date>\n");
|
||||
|
||||
sb.append(" <millis>");
|
||||
sb.append(record.getMillis());
|
||||
sb.append("</millis>\n");
|
||||
|
||||
sb.append(" <sequence>");
|
||||
sb.append(record.getSequenceNumber());
|
||||
sb.append("</sequence>\n");
|
||||
|
||||
String name = record.getLoggerName();
|
||||
if (name != null) {
|
||||
sb.append(" <logger>");
|
||||
escape(sb, name);
|
||||
sb.append("</logger>\n");
|
||||
}
|
||||
|
||||
sb.append(" <level>");
|
||||
escape(sb, record.getLevel().toString());
|
||||
sb.append("</level>\n");
|
||||
|
||||
if (record.getSourceClassName() != null) {
|
||||
sb.append(" <class>");
|
||||
escape(sb, record.getSourceClassName());
|
||||
sb.append("</class>\n");
|
||||
}
|
||||
|
||||
if (record.getSourceMethodName() != null) {
|
||||
sb.append(" <method>");
|
||||
escape(sb, record.getSourceMethodName());
|
||||
sb.append("</method>\n");
|
||||
}
|
||||
|
||||
sb.append(" <thread>");
|
||||
sb.append(record.getThreadID());
|
||||
sb.append("</thread>\n");
|
||||
|
||||
if (record.getMessage() != null) {
|
||||
// Format the message string and its accompanying parameters.
|
||||
String message = formatMessage(record);
|
||||
sb.append(" <message>");
|
||||
escape(sb, message);
|
||||
sb.append("</message>");
|
||||
sb.append("\n");
|
||||
}
|
||||
|
||||
// If the message is being localized, output the key, resource
|
||||
// bundle name, and params.
|
||||
ResourceBundle bundle = record.getResourceBundle();
|
||||
try {
|
||||
if (bundle != null && bundle.getString(record.getMessage()) != null) {
|
||||
sb.append(" <key>");
|
||||
escape(sb, record.getMessage());
|
||||
sb.append("</key>\n");
|
||||
sb.append(" <catalog>");
|
||||
escape(sb, record.getResourceBundleName());
|
||||
sb.append("</catalog>\n");
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
// The message is not in the catalog. Drop through.
|
||||
}
|
||||
|
||||
Object parameters[] = record.getParameters();
|
||||
// Check to see if the parameter was not a messagetext format
|
||||
// or was not null or empty
|
||||
if ( parameters != null && parameters.length != 0
|
||||
&& record.getMessage().indexOf("{") == -1 ) {
|
||||
for (int i = 0; i < parameters.length; i++) {
|
||||
sb.append(" <param>");
|
||||
try {
|
||||
escape(sb, parameters[i].toString());
|
||||
} catch (Exception ex) {
|
||||
sb.append("???");
|
||||
}
|
||||
sb.append("</param>\n");
|
||||
}
|
||||
}
|
||||
|
||||
if (record.getThrown() != null) {
|
||||
// Report on the state of the throwable.
|
||||
Throwable th = record.getThrown();
|
||||
sb.append(" <exception>\n");
|
||||
sb.append(" <message>");
|
||||
escape(sb, th.toString());
|
||||
sb.append("</message>\n");
|
||||
StackTraceElement trace[] = th.getStackTrace();
|
||||
for (int i = 0; i < trace.length; i++) {
|
||||
StackTraceElement frame = trace[i];
|
||||
sb.append(" <frame>\n");
|
||||
sb.append(" <class>");
|
||||
escape(sb, frame.getClassName());
|
||||
sb.append("</class>\n");
|
||||
sb.append(" <method>");
|
||||
escape(sb, frame.getMethodName());
|
||||
sb.append("</method>\n");
|
||||
// Check for a line number.
|
||||
if (frame.getLineNumber() >= 0) {
|
||||
sb.append(" <line>");
|
||||
sb.append(frame.getLineNumber());
|
||||
sb.append("</line>\n");
|
||||
}
|
||||
sb.append(" </frame>\n");
|
||||
}
|
||||
sb.append(" </exception>\n");
|
||||
}
|
||||
|
||||
sb.append("</record>\n");
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the header string for a set of XML formatted records.
|
||||
*
|
||||
* @param h The target handler (can be null)
|
||||
* @return a valid XML string
|
||||
*/
|
||||
public String getHead(Handler h) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
String encoding;
|
||||
sb.append("<?xml version=\"1.0\"");
|
||||
|
||||
if (h != null) {
|
||||
encoding = h.getEncoding();
|
||||
} else {
|
||||
encoding = null;
|
||||
}
|
||||
|
||||
if (encoding == null) {
|
||||
// Figure out the default encoding.
|
||||
encoding = java.nio.charset.Charset.defaultCharset().name();
|
||||
}
|
||||
// Try to map the encoding name to a canonical name.
|
||||
try {
|
||||
Charset cs = Charset.forName(encoding);
|
||||
encoding = cs.name();
|
||||
} catch (Exception ex) {
|
||||
// We hit problems finding a canonical name.
|
||||
// Just use the raw encoding name.
|
||||
}
|
||||
|
||||
sb.append(" encoding=\"");
|
||||
sb.append(encoding);
|
||||
sb.append("\"");
|
||||
sb.append(" standalone=\"no\"?>\n");
|
||||
sb.append("<!DOCTYPE log SYSTEM \"logger.dtd\">\n");
|
||||
sb.append("<log>\n");
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the tail string for a set of XML formatted records.
|
||||
*
|
||||
* @param h The target handler (can be null)
|
||||
* @return a valid XML string
|
||||
*/
|
||||
public String getTail(Handler h) {
|
||||
return "</log>\n";
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user