8187443: Forest Consolidation: Move files to unified layout

Reviewed-by: darcy, ihse
This commit is contained in:
Erik Joelsson 2017-09-12 19:03:39 +02:00
parent 270fe13182
commit 3789983e89
56923 changed files with 3 additions and 15727 deletions

View file

@ -0,0 +1,108 @@
/*
* 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 {@code Handler} publishes log records to {@code System.err}.
* By default the {@code SimpleFormatter} is used to generate brief summaries.
* <p>
* <b>Configuration:</b>
* By default each {@code ConsoleHandler} is initialized using the following
* {@code LogManager} 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> &lt;handler-name&gt;.level
* specifies the default level for the {@code Handler}
* (defaults to {@code Level.INFO}). </li>
* <li> &lt;handler-name&gt;.filter
* specifies the name of a {@code Filter} class to use
* (defaults to no {@code Filter}). </li>
* <li> &lt;handler-name&gt;.formatter
* specifies the name of a {@code Formatter} class to use
* (defaults to {@code java.util.logging.SimpleFormatter}). </li>
* <li> &lt;handler-name&gt;.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>
*
* @since 1.4
*/
public class ConsoleHandler extends StreamHandler {
/**
* Create a {@code ConsoleHandler} for {@code System.err}.
* <p>
* The {@code ConsoleHandler} is configured based on
* {@code LogManager} properties (or their default values).
*
*/
public ConsoleHandler() {
// configure with specific defaults for ConsoleHandler
super(Level.INFO, new SimpleFormatter(), null);
setOutputStreamPrivileged(System.err);
}
/**
* Publish a {@code LogRecord}.
* <p>
* The logging request was made initially to a {@code Logger} object,
* which initialized the {@code LogRecord} and forwarded it here.
*
* @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 {@code StreamHandler.close} to do a flush but not
* to close the output stream. That is, we do <b>not</b>
* close {@code System.err}.
*/
@Override
public void close() {
flush();
}
}

View 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();
}
}
}

View file

@ -0,0 +1,786 @@
/*
* 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 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.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 {@code Handler}.
* <p>
* The {@code FileHandler} 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 {@code XMLFormatter} class is used for formatting.
* <p>
* <b>Configuration:</b>
* By default each {@code FileHandler} is initialized using the following
* {@code LogManager} 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> &lt;handler-name&gt;.level
* specifies the default level for the {@code Handler}
* (defaults to {@code Level.ALL}). </li>
* <li> &lt;handler-name&gt;.filter
* specifies the name of a {@code Filter} class to use
* (defaults to no {@code Filter}). </li>
* <li> &lt;handler-name&gt;.formatter
* specifies the name of a {@code Formatter} class to use
* (defaults to {@code java.util.logging.XMLFormatter}) </li>
* <li> &lt;handler-name&gt;.encoding
* the name of the character set encoding to use (defaults to
* the default platform encoding). </li>
* <li> &lt;handler-name&gt;.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> &lt;handler-name&gt;.count
* specifies how many output files to cycle through (defaults to 1). </li>
* <li> &lt;handler-name&gt;.pattern
* specifies a pattern for generating the output file name. See
* below for details. (Defaults to "%h/java%u.log"). </li>
* <li> &lt;handler-name&gt;.append
* specifies whether the FileHandler should append onto
* any existing files (defaults to false). </li>
* <li> &lt;handler-name&gt;.maxLocks
* specifies the maximum number of concurrent locks held by
* FileHandler (defaults to 100). </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 {@code FileHandler}
* 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 {@code FileHandler} 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 long limit; // zero => no limit.
private int count;
private String pattern;
private String lockFileName;
private FileChannel lockFileChannel;
private File files[];
private static final int MAX_LOCKS = 100;
private int maxLocks = MAX_LOCKS;
private static final Set<String> locks = new HashSet<>();
/**
* 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 static final class MeteredStream extends OutputStream {
final OutputStream out;
long written;
MeteredStream(OutputStream out, long 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 {
long len = 0;
if (append) {
len = 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.getLongProperty(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()));
// Initialize maxLocks from the logging.properties file.
// If invalid/no property is provided 100 will be used as a default value.
maxLocks = manager.getIntProperty(cname + ".maxLocks", MAX_LOCKS);
if(maxLocks <= 0) {
maxLocks = MAX_LOCKS;
}
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 {@code FileHandler}. This will be configured
* entirely from {@code LogManager} properties (or their default values).
*
* @exception IOException if there are IO problems opening the files.
* @exception SecurityException if a security manager exists and if
* the caller does not have {@code LoggingPermission("control"))}.
* @exception NullPointerException if pattern property is an empty String.
*/
public FileHandler() throws IOException, SecurityException {
checkPermission();
configure();
// pattern will have been set by configure. check that it's not
// empty.
if (pattern.isEmpty()) {
throw new NullPointerException();
}
openFiles();
}
/**
* Initialize a {@code FileHandler} to write to the given filename.
* <p>
* The {@code FileHandler} is configured based on {@code LogManager}
* 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 {@code LoggingPermission("control")}.
* @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 {@code FileHandler} to write to the given filename,
* with optional append.
* <p>
* The {@code FileHandler} is configured based on {@code LogManager}
* 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 {@code append} 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 {@code LoggingPermission("control")}.
* @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 {@code FileHandler} 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 {@code FileHandler} is configured based on {@code LogManager}
* 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 {@code LoggingPermission("control")}.
* @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 {@code FileHandler} 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 {@code FileHandler} is configured based on {@code LogManager}
* 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
* {@code append} 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 {@code LoggingPermission("control")}.
* @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 {
this(pattern, (long)limit, count, append);
}
/**
* Initialize a {@code FileHandler} 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 {@code FileHandler} is configured based on {@code LogManager}
* 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
* {@code append} 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 {@code LoggingPermission("control")}.
* @exception IllegalArgumentException if {@code limit < 0}, or {@code count < 1}.
* @exception IllegalArgumentException if pattern is an empty string
*
* @since 9
*
*/
public FileHandler(String pattern, long limit, int count, boolean append)
throws IOException {
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;
}
// All constructors check that pattern is neither null nor empty.
assert pattern != null : "pattern should not be null";
assert !pattern.isEmpty() : "pattern should not be empty";
// 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);
}
// 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 (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 (jdk.internal.misc.VM.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 {@code LogRecord}.
*
* @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 || meter.written < 0)) {
// 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 {@code LoggingPermission("control")}.
*/
@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;
}
}
}

View 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);
}

View file

@ -0,0 +1,151 @@
/*
* 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;
/**
* 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 "{{@literal<digit>}"
* where {@literal <digit>} is in [0-9],
* java.text.MessageFormat is used to format the string.
* <li>Otherwise no formatting is performed.
* </ul>
*
* @param record the log record containing the raw message
* @return a localized and formatted message
*/
public String formatMessage(LogRecord record) {
String format = record.getMessage();
java.util.ResourceBundle catalog = record.getResourceBundle();
if (catalog != null) {
try {
format = catalog.getString(format);
} catch (java.util.MissingResourceException ex) {
// Drop through. Use record message as format
}
}
// 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 use indexOf
// and charAt to look for that pattern.
int index = -1;
int fence = format.length() - 1;
while ((index = format.indexOf('{', index+1)) > -1) {
if (index >= fence) break;
char digit = format.charAt(index+1);
if (digit >= '0' & digit <= '9') {
return java.text.MessageFormat.format(format, parameters);
}
}
return format;
} catch (Exception ex) {
// Formatting failed: use localized format string.
return format;
}
}
}

View file

@ -0,0 +1,354 @@
/*
* 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.util.Objects;
import java.io.UnsupportedEncodingException;
import java.security.AccessController;
import java.security.PrivilegedAction;
/**
* A {@code Handler} object takes log messages from a {@code Logger} 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 {@code Handler} can be disabled by doing a {@code setLevel(Level.OFF)}
* and can be re-enabled by doing a {@code setLevel} with an appropriate level.
* <p>
* {@code Handler} classes typically use {@code LogManager} properties to set
* default values for the {@code Handler}'s {@code Filter}, {@code Formatter},
* and {@code Level}. See the specific documentation for each concrete
* {@code Handler} 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;
/**
* Default constructor. The resulting {@code Handler} has a log
* level of {@code Level.ALL}, no {@code Formatter}, and no
* {@code Filter}. A default {@code ErrorManager} instance is installed
* as the {@code ErrorManager}.
*/
protected Handler() {
}
/**
* Package-private constructor for chaining from subclass constructors
* that wish to configure the handler with specific default and/or
* specified values.
*
* @param defaultLevel a default {@link Level} to configure if one is
* not found in LogManager configuration properties
* @param defaultFormatter a default {@link Formatter} to configure if one is
* not specified by {@code specifiedFormatter} parameter
* nor found in LogManager configuration properties
* @param specifiedFormatter if not null, this is the formatter to configure
*/
Handler(Level defaultLevel, Formatter defaultFormatter,
Formatter specifiedFormatter) {
LogManager manager = LogManager.getLogManager();
String cname = getClass().getName();
final Level level = manager.getLevelProperty(cname + ".level", defaultLevel);
final Filter filter = manager.getFilterProperty(cname + ".filter", null);
final Formatter formatter = specifiedFormatter == null
? manager.getFormatterProperty(cname + ".formatter", defaultFormatter)
: specifiedFormatter;
final String encoding = manager.getStringProperty(cname + ".encoding", null);
AccessController.doPrivileged(new PrivilegedAction<Void>() {
@Override
public Void run() {
setLevel(level);
setFilter(filter);
setFormatter(formatter);
try {
setEncoding(encoding);
} catch (Exception ex) {
try {
setEncoding(null);
} catch (Exception ex2) {
// doing a setEncoding with null should always work.
// assert false;
}
}
return null;
}
}, null, LogManager.controlPermission);
}
/**
* Publish a {@code LogRecord}.
* <p>
* The logging request was made initially to a {@code Logger} object,
* which initialized the {@code LogRecord} and forwarded it here.
* <p>
* The {@code Handler} 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 {@code Handler} and free all associated resources.
* <p>
* The close method will perform a {@code flush} and then close the
* {@code Handler}. After close has been called this {@code Handler}
* 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 {@code LoggingPermission("control")}.
*/
public abstract void close() throws SecurityException;
/**
* Set a {@code Formatter}. This {@code Formatter} will be used
* to format {@code LogRecords} for this {@code Handler}.
* <p>
* Some {@code Handlers} may not use {@code Formatters}, in
* which case the {@code Formatter} will be remembered, but not used.
*
* @param newFormatter the {@code Formatter} to use (may not be null)
* @exception SecurityException if a security manager exists and if
* the caller does not have {@code LoggingPermission("control")}.
*/
public synchronized void setFormatter(Formatter newFormatter) throws SecurityException {
checkPermission();
formatter = Objects.requireNonNull(newFormatter);
}
/**
* Return the {@code Formatter} for this {@code Handler}.
* @return the {@code Formatter} (may be null).
*/
public Formatter getFormatter() {
return formatter;
}
/**
* Set the character encoding used by this {@code Handler}.
* <p>
* The encoding should be set before any {@code LogRecords} are written
* to the {@code Handler}.
*
* @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 {@code LoggingPermission("control")}.
* @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 {@code Handler}.
*
* @return The encoding name. May be null, which indicates the
* default encoding should be used.
*/
public String getEncoding() {
return encoding;
}
/**
* Set a {@code Filter} to control output on this {@code Handler}.
* <P>
* For each call of {@code publish} the {@code Handler} will call
* this {@code Filter} (if it is non-null) to check if the
* {@code LogRecord} should be published or discarded.
*
* @param newFilter a {@code Filter} object (may be null)
* @exception SecurityException if a security manager exists and if
* the caller does not have {@code LoggingPermission("control")}.
*/
public synchronized void setFilter(Filter newFilter) throws SecurityException {
checkPermission();
filter = newFilter;
}
/**
* Get the current {@code Filter} for this {@code Handler}.
*
* @return a {@code Filter} 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 {@code LoggingPermission("control")}.
*/
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 {@code LoggingPermission("control")}.
*/
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 {@code Handler}. 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
* {@code Handlers}.
*
* @param newLevel the new value for the log level
* @exception SecurityException if a security manager exists and if
* the caller does not have {@code LoggingPermission("control")}.
*/
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 {@code Handler}. Message levels lower
* than this level will be discarded.
* @return the level of messages being logged.
*/
public Level getLevel() {
return logLevel;
}
/**
* Check if this {@code Handler} would actually log a given {@code LogRecord}.
* <p>
* This method checks if the {@code LogRecord} has an appropriate
* {@code Level} and whether it satisfies any {@code Filter}. It also
* may make other {@code Handler} specific checks that might prevent a
* handler from logging the {@code LogRecord}. It will return false if
* the {@code LogRecord} is null.
*
* @param record a {@code LogRecord}
* @return true if the {@code LogRecord} 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.
// We check that the caller has appropriate security privileges
// to update Handler state and if not throw a SecurityException.
void checkPermission() throws SecurityException {
manager.checkPermission();
}
}

View file

@ -0,0 +1,710 @@
/*
* 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.lang.ref.Reference;
import java.lang.ref.ReferenceQueue;
import java.lang.ref.WeakReference;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Optional;
import java.util.ResourceBundle;
import java.util.function.Function;
import jdk.internal.loader.ClassLoaderValue;
import jdk.internal.misc.JavaUtilResourceBundleAccess;
import jdk.internal.misc.SharedSecrets;
/**
* 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";
// Calling SharedSecrets.getJavaUtilResourceBundleAccess()
// forces the initialization of ResourceBundle.class, which
// can be too early if the VM has not finished booting yet.
private static final class RbAccess {
static final JavaUtilResourceBundleAccess RB_ACCESS =
SharedSecrets.getJavaUtilResourceBundleAccess();
}
/**
* @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);
private static final Level[] standardLevels = {
OFF, SEVERE, WARNING, INFO, CONFIG, FINE, FINER, FINEST, ALL
};
/**
* 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.
*
* @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) {
// Resource bundle should be loaded from the defining module
// or its defining class loader, if it's unnamed module,
// of this Level instance that can be a custom Level subclass;
Module module = this.getClass().getModule();
ResourceBundle rb = RbAccess.RB_ACCESS.getBundle(resourceBundleName,
newLocale, module);
final String localizedName = rb.getString(name);
final boolean isDefaultBundle = defaultBundle.equals(resourceBundleName);
if (!isDefaultBundle) return localizedName;
// 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();
}
Optional<Level> level;
// Look for a known Level with the given non-localized name.
level = KnownLevel.findByName(name, KnownLevel::mirrored);
if (level.isPresent()) {
return level.get();
}
// 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, KnownLevel::mirrored);
if (!level.isPresent()) {
// add new Level
Level levelObject = new Level(name, x);
// There's no need to use a reachability fence here because
// KnownLevel keeps a strong reference on the level when
// level.getClass() == Level.class.
return KnownLevel.findByValue(x, KnownLevel::mirrored).get();
}
} catch (NumberFormatException ex) {
// Not an integer.
// Drop through.
}
level = KnownLevel.findByLocalizedLevelName(name,
KnownLevel::mirrored);
if (level.isPresent()) {
return level.get();
}
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() {
Optional<Level> level = KnownLevel.matches(this);
if (level.isPresent()) {
return level.get();
}
// Woops. Whoever sent us this object knows
// about a new log level. Add it to our list.
return new Level(this.name, this.value, this.resourceBundleName);
}
/**
* 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();
Optional<Level> level;
// Look for a known Level with the given non-localized name.
level = KnownLevel.findByName(name, KnownLevel::referent);
if (level.isPresent()) {
return level.get();
}
// 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, KnownLevel::referent);
if (level.isPresent()) {
return level.get();
}
// add new Level.
Level levelObject = new Level(name, x);
// There's no need to use a reachability fence here because
// KnownLevel keeps a strong reference on the level when
// level.getClass() == Level.class.
return KnownLevel.findByValue(x, KnownLevel::referent).get();
} 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, KnownLevel::referent);
if (level .isPresent()) {
return level.get();
}
// 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 extends WeakReference<Level> {
private static Map<String, List<KnownLevel>> nameToLevels = new HashMap<>();
private static Map<Integer, List<KnownLevel>> intToLevels = new HashMap<>();
private static final ReferenceQueue<Level> QUEUE = new ReferenceQueue<>();
// CUSTOM_LEVEL_CLV is used to register custom level instances with
// their defining class loader, so that they are garbage collected
// if and only if their class loader is no longer strongly
// referenced.
private static final ClassLoaderValue<List<Level>> CUSTOM_LEVEL_CLV =
new ClassLoaderValue<>();
final Level mirroredLevel; // mirror of the custom Level
KnownLevel(Level l) {
super(l, QUEUE);
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);
}
}
Optional<Level> mirrored() {
return Optional.of(mirroredLevel);
}
Optional<Level> referent() {
return Optional.ofNullable(get());
}
private void remove() {
Optional.ofNullable(nameToLevels.get(mirroredLevel.name))
.ifPresent((x) -> x.remove(this));
Optional.ofNullable(intToLevels.get(mirroredLevel.value))
.ifPresent((x) -> x.remove(this));
}
// Remove all stale KnownLevel instances
static synchronized void purge() {
Reference<? extends Level> ref;
while ((ref = QUEUE.poll()) != null) {
if (ref instanceof KnownLevel) {
((KnownLevel)ref).remove();
}
}
}
private static void registerWithClassLoader(Level customLevel) {
PrivilegedAction<ClassLoader> pa =
() -> customLevel.getClass().getClassLoader();
PrivilegedAction<String> pn = customLevel.getClass()::getName;
final String name = AccessController.doPrivileged(pn);
final ClassLoader cl = AccessController.doPrivileged(pa);
CUSTOM_LEVEL_CLV.computeIfAbsent(cl, (c, v) -> new ArrayList<>())
.add(customLevel);
}
static synchronized void add(Level l) {
purge();
// 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);
// keep the custom level reachable from its class loader
// This will ensure that custom level values are not GC'ed
// until there class loader is GC'ed.
if (o.mirroredLevel != l) {
registerWithClassLoader(l);
}
}
// Returns a KnownLevel with the given non-localized name.
static synchronized Optional<Level> findByName(String name,
Function<KnownLevel, Optional<Level>> selector) {
purge();
return nameToLevels.getOrDefault(name, Collections.emptyList())
.stream()
.map(selector)
.flatMap(Optional::stream)
.findFirst();
}
// Returns a KnownLevel with the given value.
static synchronized Optional<Level> findByValue(int value,
Function<KnownLevel, Optional<Level>> selector) {
purge();
return intToLevels.getOrDefault(value, Collections.emptyList())
.stream()
.map(selector)
.flatMap(Optional::stream)
.findFirst();
}
// 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 Optional<Level> findByLocalizedLevelName(String name,
Function<KnownLevel, Optional<Level>> selector) {
purge();
return nameToLevels.values().stream()
.flatMap(List::stream)
.map(selector)
.flatMap(Optional::stream)
.filter(l -> name.equals(l.getLocalizedLevelName()))
.findFirst();
}
static synchronized Optional<Level> matches(Level l) {
purge();
List<KnownLevel> list = nameToLevels.get(l.name);
if (list != null) {
for (KnownLevel ref : list) {
Level levelObject = ref.get();
if (levelObject == null) continue;
Level other = ref.mirroredLevel;
Class<? extends Level> type = levelObject.getClass();
if (l.value == other.value &&
(l.resourceBundleName == other.resourceBundleName ||
(l.resourceBundleName != null &&
l.resourceBundleName.equals(other.resourceBundleName)))) {
if (type == l.getClass()) {
return Optional.of(levelObject);
}
}
}
}
return Optional.empty();
}
}
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,742 @@
/*
* Copyright (c) 2000, 2015, 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.time.Instant;
import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong;
import java.io.*;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.time.Clock;
import java.util.function.Predicate;
import static jdk.internal.logger.SurrogateLogger.isFilteredFrame;
/**
* 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<>();
/**
* Logging message level
*/
private Level level;
/**
* Sequence number
*/
private long sequenceNumber;
/**
* Class that issued logging call
*/
private String sourceClassName;
/**
* Method that issued logging call
*/
private String sourceMethodName;
/**
* Non-localized raw message text
*/
private String message;
/**
* Thread ID for thread that issued logging call.
*/
private int threadID;
/**
* The Throwable (if any) associated with log message
*/
private Throwable thrown;
/**
* Name of the source Logger.
*/
private String loggerName;
/**
* Resource bundle name to localized log message.
*/
private String resourceBundleName;
/**
* Event time.
* @since 9
*/
private Instant instant;
/**
* @serialField level Level Logging message level
* @serialField sequenceNumber long Sequence number
* @serialField sourceClassName String Class that issued logging call
* @serialField sourceMethodName String Method that issued logging call
* @serialField message String Non-localized raw message text
* @serialField threadID int Thread ID for thread that issued logging call
* @serialField millis long Truncated event time in milliseconds since 1970
* - calculated as getInstant().toEpochMilli().
* The event time instant can be reconstructed using
* <code>Instant.ofEpochSecond(millis/1000, (millis % 1000) * 1000_000 + nanoAdjustment)</code>
* @serialField nanoAdjustment int Nanoseconds adjustment to the millisecond of
* event time - calculated as getInstant().getNano() % 1000_000
* The event time instant can be reconstructed using
* <code>Instant.ofEpochSecond(millis/1000, (millis % 1000) * 1000_000 + nanoAdjustment)</code>
* <p>
* Since: 9
* @serialField thrown Throwable The Throwable (if any) associated with log
* message
* @serialField loggerName String Name of the source Logger
* @serialField resourceBundleName String Resource bundle name to localized
* log message
*/
private static final ObjectStreamField[] serialPersistentFields =
new ObjectStreamField[] {
new ObjectStreamField("level", Level.class),
new ObjectStreamField("sequenceNumber", long.class),
new ObjectStreamField("sourceClassName", String.class),
new ObjectStreamField("sourceMethodName", String.class),
new ObjectStreamField("message", String.class),
new ObjectStreamField("threadID", int.class),
new ObjectStreamField("millis", long.class),
new ObjectStreamField("nanoAdjustment", int.class),
new ObjectStreamField("thrown", Throwable.class),
new ObjectStreamField("loggerName", String.class),
new ObjectStreamField("resourceBundleName", String.class),
};
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>
* Since JDK 9, the event time is represented by an {@link Instant}.
* The instant property will be initialized to the {@linkplain
* Instant#now() current instant}, using the best available
* {@linkplain Clock#systemUTC() clock} on the system.
* <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)
* @see java.time.Clock#systemUTC()
*/
public LogRecord(Level level, String msg) {
this.level = Objects.requireNonNull(level);
message = msg;
// Assign a thread ID and a unique sequence number.
sequenceNumber = globalSequenceNumber.getAndIncrement();
threadID = defaultThreadID();
instant = Instant.now();
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 truncated event time in milliseconds since 1970.
*
* @return truncated event time in millis since 1970
*
* @implSpec This is equivalent to calling
* {@link #getInstant() getInstant().toEpochMilli()}.
*
* @apiNote To get the full nanosecond resolution event time,
* use {@link #getInstant()}.
*
* @see #getInstant()
*/
public long getMillis() {
return instant.toEpochMilli();
}
/**
* Set event time.
*
* @param millis event time in millis since 1970.
*
* @implSpec This is equivalent to calling
* {@link #setInstant(java.time.Instant)
* setInstant(Instant.ofEpochMilli(millis))}.
*
* @deprecated LogRecord maintains timestamps with nanosecond resolution,
* using {@link Instant} values. For this reason,
* {@link #setInstant(java.time.Instant) setInstant()}
* should be used in preference to {@code setMillis()}.
*
* @see #setInstant(java.time.Instant)
*/
@Deprecated
public void setMillis(long millis) {
this.instant = Instant.ofEpochMilli(millis);
}
/**
* Gets the instant that the event occurred.
*
* @return the instant that the event occurred.
*
* @since 9
*/
public Instant getInstant() {
return instant;
}
/**
* Sets the instant that the event occurred.
* <p>
* If the given {@code instant} represents a point on the time-line too
* far in the future or past to fit in a {@code long} milliseconds and
* nanoseconds adjustment, then an {@code ArithmeticException} will be
* thrown.
*
* @param instant the instant that the event occurred.
*
* @throws NullPointerException if {@code instant} is null.
* @throws ArithmeticException if numeric overflow would occur while
* calling {@link Instant#toEpochMilli() instant.toEpochMilli()}.
*
* @since 9
*/
public void setInstant(Instant instant) {
instant.toEpochMilli();
this.instant = instant;
}
/**
* 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 Serialized 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 write serialized fields first.
ObjectOutputStream.PutField pf = out.putFields();
pf.put("level", level);
pf.put("sequenceNumber", sequenceNumber);
pf.put("sourceClassName", sourceClassName);
pf.put("sourceMethodName", sourceMethodName);
pf.put("message", message);
pf.put("threadID", threadID);
pf.put("millis", instant.toEpochMilli());
pf.put("nanoAdjustment", instant.getNano() % 1000_000);
pf.put("thrown", thrown);
pf.put("loggerName", loggerName);
pf.put("resourceBundleName", resourceBundleName);
out.writeFields();
// 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 (Object parameter : parameters) {
out.writeObject(Objects.toString(parameter, null));
}
}
private void readObject(ObjectInputStream in)
throws IOException, ClassNotFoundException {
// We have to read serialized fields first.
ObjectInputStream.GetField gf = in.readFields();
level = (Level) gf.get("level", null);
sequenceNumber = gf.get("sequenceNumber", 0L);
sourceClassName = (String) gf.get("sourceClassName", null);
sourceMethodName = (String) gf.get("sourceMethodName", null);
message = (String) gf.get("message", null);
threadID = gf.get("threadID", 0);
long millis = gf.get("millis", 0L);
int nanoOfMilli = gf.get("nanoAdjustment", 0);
instant = Instant.ofEpochSecond(
millis / 1000L, (millis % 1000L) * 1000_000L + nanoOfMilli);
thrown = (Throwable) gf.get("thrown", null);
loggerName = (String) gf.get("loggerName", null);
resourceBundleName = (String) gf.get("resourceBundleName", null);
// 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
//
// Note:
// For testing purposes - it is possible to customize the process
// by which LogRecord will infer the source class name and source method name
// when analyzing the call stack.
// <p>
// The system property {@code jdk.logger.packages} can define a comma separated
// list of strings corresponding to additional package name prefixes that
// should be ignored when trying to infer the source caller class name.
// Those stack frames whose {@linkplain StackTraceElement#getClassName()
// declaring class name} start with one such prefix will be ignored.
// <p>
// This is primarily useful when providing utility logging classes wrapping
// a logger instance, as it makes it possible to instruct LogRecord to skip
// those utility frames when inferring the caller source class name.
// <p>
// The {@code jdk.logger.packages} system property is consulted only once.
// <p>
// This property is not standard, implementation specific, and yet
// undocumented (and thus subject to changes without notice).
//
private void inferCaller() {
needToInferCaller = false;
// Skip all frames until we have found the first logger frame.
Optional<StackWalker.StackFrame> frame = new CallerFinder().get();
frame.ifPresent(f -> {
setSourceClassName(f.getClassName());
setSourceMethodName(f.getMethodName());
});
// We haven't found a suitable frame, so just punt. This is
// OK as we are only committed to making a "best effort" here.
}
/*
* CallerFinder is a stateful predicate.
*/
static final class CallerFinder implements Predicate<StackWalker.StackFrame> {
private static final StackWalker WALKER;
static {
final PrivilegedAction<StackWalker> action =
() -> StackWalker.getInstance(StackWalker.Option.RETAIN_CLASS_REFERENCE);
WALKER = AccessController.doPrivileged(action);
}
/**
* Returns StackFrame of the caller's frame.
* @return StackFrame of the caller's frame.
*/
Optional<StackWalker.StackFrame> get() {
return WALKER.walk((s) -> s.filter(this).findFirst());
}
private boolean lookingForLogger = true;
/**
* Returns true if we have found the caller's frame, false if the frame
* must be skipped.
*
* @param t The frame info.
* @return true if we have found the caller's frame, false if the frame
* must be skipped.
*/
@Override
public boolean test(StackWalker.StackFrame t) {
final String cname = t.getClassName();
// We should skip all frames until we have found the logger,
// because these frames could be frames introduced by e.g. custom
// sub classes of Handler.
if (lookingForLogger) {
// the log record could be created for a platform logger
lookingForLogger = !isLoggerImplFrame(cname);
return false;
}
// Continue walking until we've found the relevant calling frame.
// Skips logging/logger infrastructure.
return !isFilteredFrame(t);
}
private boolean isLoggerImplFrame(String cname) {
return (cname.equals("java.util.logging.Logger") ||
cname.startsWith("sun.util.logging.PlatformLogger"));
}
}
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,131 @@
/*
* 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 {@code LoggingMXBean} 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
*/
@SuppressWarnings("deprecation") // implements LoggingMXBean
final class Logging implements LoggingMXBean {
private static LogManager logManager = LogManager.getLogManager();
/** Constructor of Logging which is the implementation class
* of LoggingMXBean.
*/
private Logging() {
}
@Override
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 = "";
@Override
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();
}
}
@Override
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);
}
@Override
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();
}
}
static Logging getInstance() {
return INSTANCE;
}
private static final Logging INSTANCE = new Logging();
}

View file

@ -0,0 +1,133 @@
/*
* 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.
*
* {@link java.lang.management.PlatformLoggingMXBean
* java.lang.management.PlatformLoggingMXBean} is the management interface
* for logging facility registered in the {@link
* java.lang.management.ManagementFactory#getPlatformMBeanServer()
* platform MBeanServer}.
* It is recommended to use the {@code PlatformLoggingMXBean} obtained via
* the {@link java.lang.management.ManagementFactory#getPlatformMXBean(Class)
* ManagementFactory.getPlatformMXBean(PlatformLoggingMXBean.class)} method.
*
* @deprecated {@code LoggingMXBean} is no longer a {@link
* java.lang.management.PlatformManagedObject platform MXBean} and is replaced
* with {@link java.lang.management.PlatformLoggingMXBean}.
* It will not register in the platform {@code MBeanServer}.
* Use {@code ManagementFactory.getPlatformMXBean(PlatformLoggingMXBean.class)}
* instead.
*
* @author Ron Mann
* @author Mandy Chung
* @since 1.5
*
* @see java.lang.management.PlatformLoggingMXBean
*/
@Deprecated(since="9")
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 {@code String} each of which is a
* currently registered {@code Logger} 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, {@code null}
* 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 {@code Level} of the specified logger is {@code null},
* 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 {@code Logger} 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 {@code null}. If the specified logger does not
* exist, {@code null} is returned.
*
* @see Logger#getLevel
*/
public String getLoggerLevel(String loggerName);
/**
* Sets the specified logger to the specified new level.
* If the {@code levelName} is not {@code null}, the level
* of the specified logger is set to the parsed {@code Level}
* matching the {@code levelName}.
* If the {@code levelName} is {@code null}, the level
* of the specified logger is set to {@code null} 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 {@code Logger} to be set.
* Must be non-null.
* @param levelName The name of the level to set on the specified logger,
* or {@code null} if setting the level to inherit
* from its nearest ancestor.
*
* @throws IllegalArgumentException if the specified logger
* does not exist, or {@code levelName} 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, {@code null} is returned.
* If the specified logger is the root {@code Logger} in the namespace,
* the result will be an empty string.
*
* @param loggerName The name of a {@code Logger}.
*
* @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, {@code null}
* is returned.
*/
public String getParentLoggerName(String loggerName);
}

View 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);
}
}
}

View file

@ -0,0 +1,281 @@
/*
* 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;
/**
* {@code Handler} that buffers requests in a circular buffer in memory.
* <p>
* Normally this {@code Handler} simply stores incoming {@code LogRecords}
* into its memory buffer and discards earlier records. This buffering
* is very cheap and avoids formatting costs. On certain trigger
* conditions, the {@code MemoryHandler} will push out its current buffer
* contents to a target {@code Handler}, 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 {@code LogRecord} has a type that is greater than
* a pre-defined level, the {@code pushLevel}. </li>
* <li>
* An external class calls the {@code push} method explicitly. </li>
* <li>
* A subclass overrides the {@code log} method and scans each incoming
* {@code LogRecord} and calls {@code push} if a record matches some
* desired criteria. </li>
* </ul>
* <p>
* <b>Configuration:</b>
* By default each {@code MemoryHandler} is initialized using the following
* {@code LogManager} 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.
* If no default value is defined then a RuntimeException is thrown.
* <ul>
* <li> &lt;handler-name&gt;.level
* specifies the level for the {@code Handler}
* (defaults to {@code Level.ALL}). </li>
* <li> &lt;handler-name&gt;.filter
* specifies the name of a {@code Filter} class to use
* (defaults to no {@code Filter}). </li>
* <li> &lt;handler-name&gt;.size
* defines the buffer size (defaults to 1000). </li>
* <li> &lt;handler-name&gt;.push
* defines the {@code pushLevel} (defaults to {@code level.SEVERE}). </li>
* <li> &lt;handler-name&gt;.target
* specifies the name of the target {@code Handler } 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>
*
* @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;
/**
* Create a {@code MemoryHandler} and configure it based on
* {@code LogManager} configuration properties.
*/
public MemoryHandler() {
// configure with specific defaults for MemoryHandler
super(Level.ALL, new SimpleFormatter(), null);
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;
}
String targetName = manager.getProperty(cname+".target");
if (targetName == null) {
throw new RuntimeException("The handler " + cname
+ " does not specify a target");
}
Class<?> clz;
try {
clz = ClassLoader.getSystemClassLoader().loadClass(targetName);
@SuppressWarnings("deprecation")
Object o = clz.newInstance();
target = (Handler) o;
} 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 {@code MemoryHandler}.
* <p>
* The {@code MemoryHandler} is configured based on {@code LogManager}
* properties (or their default values) except that the given {@code pushLevel}
* 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) {
// configure with specific defaults for MemoryHandler
super(Level.ALL, new SimpleFormatter(), null);
if (target == null || pushLevel == null) {
throw new NullPointerException();
}
if (size <= 0) {
throw new IllegalArgumentException();
}
this.target = target;
this.pushLevel = pushLevel;
this.size = size;
init();
}
/**
* Store a {@code LogRecord} in an internal buffer.
* <p>
* If there is a {@code Filter}, its {@code isLoggable}
* 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 {@code pushLevel}. If the given level is
* greater than or equal to the {@code pushLevel} then {@code push}
* is called to write all buffered records to the target output
* {@code Handler}.
*
* @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 {@code Handler}.
* <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 {@code Handler}.
* <p>
* Note that the current contents of the {@code MemoryHandler}
* buffer are <b>not</b> written out. That requires a "push".
*/
@Override
public void flush() {
target.flush();
}
/**
* Close the {@code Handler} and free all associated resources.
* This will also close the target {@code Handler}.
*
* @exception SecurityException if a security manager exists and if
* the caller does not have {@code LoggingPermission("control")}.
*/
@Override
public void close() throws SecurityException {
target.close();
setLevel(Level.OFF);
}
/**
* Set the {@code pushLevel}. After a {@code LogRecord} is copied
* into our internal buffer, if its level is greater than or equal to
* the {@code pushLevel}, then {@code push} will be called.
*
* @param newLevel the new value of the {@code pushLevel}
* @exception SecurityException if a security manager exists and if
* the caller does not have {@code LoggingPermission("control")}.
*/
public synchronized void setPushLevel(Level newLevel) throws SecurityException {
if (newLevel == null) {
throw new NullPointerException();
}
checkPermission();
pushLevel = newLevel;
}
/**
* Get the {@code pushLevel}.
*
* @return the value of the {@code pushLevel}
*/
public Level getPushLevel() {
return pushLevel;
}
/**
* Check if this {@code Handler} would actually log a given
* {@code LogRecord} into its internal buffer.
* <p>
* This method checks if the {@code LogRecord} has an appropriate level and
* whether it satisfies any {@code Filter}. However it does <b>not</b>
* check whether the {@code LogRecord} would result in a "push" of the
* buffer contents. It will return false if the {@code LogRecord} is null.
*
* @param record a {@code LogRecord}
* @return true if the {@code LogRecord} would be logged.
*
*/
@Override
public boolean isLoggable(LogRecord record) {
return super.isLoggable(record);
}
}

View file

@ -0,0 +1,186 @@
/*
* 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.io.*;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import jdk.internal.logger.SurrogateLogger;
/**
* Print a brief summary of the {@code LogRecord} in a human readable
* format. The summary will typically be 1 or 2 lines.
*
* <p>
* <a id="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(LogRecord) 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
static String getLoggingProperty(String name) {
return LogManager.getLogManager().getProperty(name);
}
private final String format =
SurrogateLogger.getSimpleFormat(SimpleFormatter::getLoggingProperty);
/**
* 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 ZonedDateTime} object representing
* {@linkplain LogRecord#getInstant() event time} of the log record
* in the {@link ZoneId#systemDefault()} system time zone.</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>
* <li> {@code java.util.logging.SimpleFormatter.format="%1$tb %1$td, %1$tY %1$tl:%1$tM:%1$tS.%1$tN %1$Tp %2$s%n%4$s: %5$s%6$s%n"}
* <p>Since JDK 9, {@code java.util.logging} uses {@link
* java.time.Clock#systemUTC() java.time} to create more precise time
* stamps.
* The format above can be used to add a {@code .%1$tN} to the
* date/time formatting so that nanoseconds will also be printed:
* <pre>
* Feb 06, 2015 5:33:10.279216000 PM example.Main main
* INFO: This is a test
* </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
*/
@Override
public String format(LogRecord record) {
ZonedDateTime zdt = ZonedDateTime.ofInstant(
record.getInstant(), ZoneId.systemDefault());
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,
zdt,
source,
record.getLoggerName(),
record.getLevel().getLocalizedLevelName(),
message,
throwable);
}
}

View file

@ -0,0 +1,185 @@
/*
* 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 {@code Handler}.
* <p>
* {@code LogRecords} are published to a network stream connection. By default
* the {@code XMLFormatter} class is used for formatting.
* <p>
* <b>Configuration:</b>
* By default each {@code SocketHandler} is initialized using the following
* {@code LogManager} 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> &lt;handler-name&gt;.level
* specifies the default level for the {@code Handler}
* (defaults to {@code Level.ALL}). </li>
* <li> &lt;handler-name&gt;.filter
* specifies the name of a {@code Filter} class to use
* (defaults to no {@code Filter}). </li>
* <li> &lt;handler-name&gt;.formatter
* specifies the name of a {@code Formatter} class to use
* (defaults to {@code java.util.logging.XMLFormatter}). </li>
* <li> &lt;handler-name&gt;.encoding
* the name of the character set encoding to use (defaults to
* the default platform encoding). </li>
* <li> &lt;handler-name&gt;.host
* specifies the target host name to connect to (no default). </li>
* <li> &lt;handler-name&gt;.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
* {@code LogRecord} is written.
*
* @since 1.4
*/
public class SocketHandler extends StreamHandler {
private Socket sock;
private String host;
private int port;
/**
* Create a {@code SocketHandler}, using only {@code LogManager} 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 {
// configure with specific defaults for SocketHandler
super(Level.ALL, new XMLFormatter(), null);
LogManager manager = LogManager.getLogManager();
String cname = getClass().getName();
port = manager.getIntProperty(cname + ".port", 0);
host = manager.getStringProperty(cname + ".host", null);
try {
connect();
} catch (IOException ix) {
System.err.println("SocketHandler: connect failed to " + host + ":" + port);
throw ix;
}
}
/**
* Construct a {@code SocketHandler} using a specified host and port.
*
* The {@code SocketHandler} is configured based on {@code LogManager}
* 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 {
// configure with specific defaults for SocketHandler
super(Level.ALL, new XMLFormatter(), null);
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);
setOutputStreamPrivileged(bout);
}
/**
* Close this output stream.
*
* @exception SecurityException if a security manager exists and if
* the caller does not have {@code LoggingPermission("control")}.
*/
@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 {@code LogRecord}.
*
* @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();
}
}

View 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.*;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.Objects;
/**
* Stream based logging {@code Handler}.
* <p>
* This is primarily intended as a base class or support class to
* be used in implementing other logging {@code Handlers}.
* <p>
* {@code LogRecords} are published to a given {@code java.io.OutputStream}.
* <p>
* <b>Configuration:</b>
* By default each {@code StreamHandler} is initialized using the following
* {@code LogManager} 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> &lt;handler-name&gt;.level
* specifies the default level for the {@code Handler}
* (defaults to {@code Level.INFO}). </li>
* <li> &lt;handler-name&gt;.filter
* specifies the name of a {@code Filter} class to use
* (defaults to no {@code Filter}). </li>
* <li> &lt;handler-name&gt;.formatter
* specifies the name of a {@code Formatter} class to use
* (defaults to {@code java.util.logging.SimpleFormatter}). </li>
* <li> &lt;handler-name&gt;.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>
*
* @since 1.4
*/
public class StreamHandler extends Handler {
private OutputStream output;
private boolean doneHeader;
private volatile Writer writer;
/**
* Create a {@code StreamHandler}, with no current output stream.
*/
public StreamHandler() {
// configure with specific defaults for StreamHandler
super(Level.INFO, new SimpleFormatter(), null);
}
/**
* Create a {@code StreamHandler} with a given {@code Formatter}
* and output stream.
*
* @param out the target output stream
* @param formatter Formatter to be used to format output
*/
public StreamHandler(OutputStream out, Formatter formatter) {
// configure with default level but use specified formatter
super(Level.INFO, null, Objects.requireNonNull(formatter));
setOutputStreamPrivileged(out);
}
/**
* @see Handler#Handler(Level, Formatter, Formatter)
*/
StreamHandler(Level defaultLevel,
Formatter defaultFormatter,
Formatter specifiedFormatter) {
super(defaultLevel, defaultFormatter, specifiedFormatter);
}
/**
* Change the output stream.
* <P>
* If there is a current output stream then the {@code Formatter}'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 {@code LoggingPermission("control")}.
*/
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 {@code Handler}.
* <p>
* The encoding should be set before any {@code LogRecords} are written
* to the {@code Handler}.
*
* @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 {@code LoggingPermission("control")}.
* @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 {@code LogRecord}.
* <p>
* The {@code StreamHandler} first checks if there is an {@code OutputStream}
* and if the given {@code LogRecord} has at least the required log level.
* If not it silently returns. If so, it calls any associated
* {@code Filter} to check if the record should be published. If so,
* it calls its {@code Formatter} to format the record and then writes
* the result to the current output stream.
* <p>
* If this is the first {@code LogRecord} to be written to a given
* {@code OutputStream}, the {@code Formatter}'s "head" string is
* written to the stream before the {@code LogRecord} 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 {@code Handler} would actually log a given {@code LogRecord}.
* <p>
* This method checks if the {@code LogRecord} has an appropriate level and
* whether it satisfies any {@code Filter}. It will also return false if
* no output stream has been assigned yet or the LogRecord is null.
*
* @param record a {@code LogRecord}
* @return true if the {@code LogRecord} 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 {@code Formatter}'s "tail" string is written to the stream before it
* is closed. In addition, if the {@code Formatter}'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();
}
// Package-private support for setting OutputStream
// with elevated privilege.
final void setOutputStreamPrivileged(final OutputStream out) {
AccessController.doPrivileged(new PrivilegedAction<Void>() {
@Override
public Void run() {
setOutputStream(out);
return null;
}
}, null, LogManager.controlPermission);
}
}

View file

@ -0,0 +1,348 @@
/*
* Copyright (c) 2000, 2015, 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.nio.charset.Charset;
import java.time.Instant;
import java.time.format.DateTimeFormatter;
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.
*
* @implSpec Since JDK 9, instances of {@linkplain LogRecord} contain
* an {@link LogRecord#getInstant() Instant} which can have nanoseconds below
* the millisecond resolution.
* The DTD specification has been updated to allow for an optional
* {@code <nanos>} element. By default, the XMLFormatter will compute the
* nanosecond adjustment below the millisecond resolution (using
* {@code LogRecord.getInstant().getNano() % 1000_000}) - and if this is not 0,
* this adjustment value will be printed in the new {@code <nanos>} element.
* The event instant can then be reconstructed using
* {@code Instant.ofEpochSecond(millis/1000L, (millis % 1000L) * 1000_000L + nanos)}
* where {@code millis} and {@code nanos} represent the numbers serialized in
* the {@code <millis>} and {@code <nanos>} elements, respectively.
* <br>
* The {@code <date>} element will now contain the whole instant as formatted
* by the {@link DateTimeFormatter#ISO_INSTANT DateTimeFormatter.ISO_INSTANT}
* formatter.
* <p>
* For compatibility with old parsers, XMLFormatters can
* be configured to revert to the old format by specifying a
* {@code <xml-formatter-fully-qualified-class-name>.useInstant = false}
* {@linkplain LogManager#getProperty(java.lang.String) property} in the
* logging configuration. When {@code useInstant} is {@code false}, the old
* formatting will be preserved. When {@code useInstant} is {@code true}
* (the default), the {@code <nanos>} element will be printed and the
* {@code <date>} element will contain the {@linkplain
* DateTimeFormatter#ISO_INSTANT formatted} instant.
* <p>
* For instance, in order to configure plain instances of XMLFormatter to omit
* the new {@code <nano>} element,
* {@code java.util.logging.XMLFormatter.useInstant = false} can be specified
* in the logging configuration.
*
* @since 1.4
*/
public class XMLFormatter extends Formatter {
private final LogManager manager = LogManager.getLogManager();
private final boolean useInstant;
/**
* Creates a new instance of XMLFormatter.
*
* @implSpec
* Since JDK 9, the XMLFormatter will print out the record {@linkplain
* LogRecord#getInstant() event time} as an Instant. This instant
* has the best resolution available on the system. The {@code <date>}
* element will contain the instant as formatted by the {@link
* DateTimeFormatter#ISO_INSTANT}.
* In addition, an optional {@code <nanos>} element containing a
* nanosecond adjustment will be printed if the instant contains some
* nanoseconds below the millisecond resolution.
* <p>
* This new behavior can be turned off, and the old formatting restored,
* by specifying a property in the {@linkplain
* LogManager#getProperty(java.lang.String) logging configuration}.
* If {@code LogManager.getLogManager().getProperty(
* this.getClass().getName()+".useInstant")} is {@code "false"} or
* {@code "0"}, the old formatting will be restored.
*/
public XMLFormatter() {
useInstant = (manager == null)
|| manager.getBooleanProperty(
this.getClass().getName()+".useInstant", true);
}
// 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("&lt;");
} else if (ch == '>') {
sb.append("&gt;");
} else if (ch == '&') {
sb.append("&amp;");
} 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
*/
@Override
public String format(LogRecord record) {
StringBuilder sb = new StringBuilder(500);
sb.append("<record>\n");
final Instant instant = record.getInstant();
sb.append(" <date>");
if (useInstant) {
// If useInstant is true - we will print the instant in the
// date field, using the ISO_INSTANT formatter.
DateTimeFormatter.ISO_INSTANT.formatTo(instant, sb);
} else {
// If useInstant is false - we will keep the 'old' formating
appendISO8601(sb, instant.toEpochMilli());
}
sb.append("</date>\n");
sb.append(" <millis>");
sb.append(instant.toEpochMilli());
sb.append("</millis>\n");
final int nanoAdjustment = instant.getNano() % 1000_000;
if (useInstant && nanoAdjustment != 0) {
sb.append(" <nanos>");
sb.append(nanoAdjustment);
sb.append("</nanos>\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 (Object parameter : parameters) {
sb.append(" <param>");
try {
escape(sb, parameter.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 (StackTraceElement frame : trace) {
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
*/
@Override
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
*/
@Override
public String getTail(Handler h) {
return "</log>\n";
}
}

View file

@ -0,0 +1,127 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
<html>
<head>
<!--
Copyright (c) 2001, 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.
-->
</head>
<body bgcolor="white">
<P>
Provides the classes and interfaces of
the Java&trade; 2 platform's core logging facilities.
The central goal of the logging APIs is to support maintaining and servicing
software at customer sites.
<P>
There are four main target uses of the logs:
</P>
<OL>
<LI> <I>Problem diagnosis by end users and system administrators</I>.
This consists of simple logging of common problems that can be fixed
or tracked locally, such as running out of resources, security failures,
and simple configuration errors.
<LI> <I>Problem diagnosis by field service engineers</I>. The logging information
used by field service engineers may be considerably more complex and
verbose than that required by system administrators. Typically such information
will require extra logging within particular subsystems.
<LI> <I>Problem diagnosis by the development organization</I>.
When a problem occurs in the field, it may be necessary to return the captured logging
information to the original development team for diagnosis. This logging
information may be extremely detailed and fairly inscrutable. Such information might include
detailed tracing on the internal execution of particular subsystems.
<LI> <I>Problem diagnosis by developers</I>. The Logging APIs may also be
used to help debug an application under development. This may
include logging information generated by the target application
as well as logging information generated by lower-level libraries.
Note however that while this use is perfectly reasonable,
the logging APIs are not intended to replace the normal debugging
and profiling tools that may already exist in the development environment.
</OL>
<p>
The key elements of this package include:
<UL>
<LI> <I>Logger</I>: The main entity on which applications make
logging calls. A Logger object is used to log messages
for a specific system or application
component.
<LI> <I>LogRecord</I>: Used to pass logging requests between the logging
framework and individual log handlers.
<LI> <I>Handler</I>: Exports LogRecord objects to a variety of destinations
including memory, output streams, consoles, files, and sockets.
A variety of Handler subclasses exist for this purpose. Additional Handlers
may be developed by third parties and delivered on top of the core platform.
<LI> <I>Level</I>: Defines a set of standard logging levels that can be used
to control logging output. Programs can be configured to output logging
for some levels while ignoring output for others.
<LI> <I>Filter</I>: Provides fine-grained control over what gets logged,
beyond the control provided by log levels. The logging APIs support a general-purpose
filter mechanism that allows application code to attach arbitrary filters to
control logging output.
<LI> <I>Formatter</I>: Provides support for formatting LogRecord objects. This
package includes two formatters, SimpleFormatter and
XMLFormatter, for formatting log records in plain text
or XML respectively. As with Handlers, additional Formatters
may be developed by third parties.
</UL>
<P>
The Logging APIs offer both static and dynamic configuration control.
Static control enables field service staff to set up a particular configuration and then re-launch the
application with the new logging settings. Dynamic control allows for updates to the
logging configuration within a currently running program. The APIs also allow for logging to be
enabled or disabled for different functional areas of the system. For example,
a field service engineer might be interested in tracing all AWT events, but might have no interest in
socket events or memory management.
</P>
<h2>Null Pointers</h2>
<p>
In general, unless otherwise noted in the javadoc, methods and
constructors will throw NullPointerException if passed a null argument.
The one broad exception to this rule is that the logging convenience
methods in the Logger class (the config, entering, exiting, fine, finer, finest,
log, logp, logrb, severe, throwing, and warning methods)
will accept null values
for all arguments except for the initial Level argument (if any).
<H2>Related Documentation</H2>
<P>
For an overview of control flow,
please refer to the
{@extLink logging_overview Java Logging Overview}
</P>
<!-- Put @see and @since tags down here. -->
@since 1.4
</body>
</html>

View file

@ -0,0 +1,38 @@
/*
* Copyright (c) 2014, 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.
*/
/**
* Defines the Java Logging API.
*
* @moduleGraph
* @since 9
*/
module java.logging {
exports java.util.logging;
provides jdk.internal.logger.DefaultLoggerFinder with
sun.util.logging.internal.LoggingProviderImpl;
}

View file

@ -0,0 +1,131 @@
/*
* Copyright (c) 2009, 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 sun.net.www.protocol.http.logging;
import java.util.logging.LogRecord;
import java.util.regex.*;
/**
* A Formatter to make the HTTP logs a bit more palatable to the developer
* looking at them. The idea is to present the HTTP events in such a way that
* commands and headers are easily spotted (i.e. on separate lines).
* @author jccollet
*/
public class HttpLogFormatter extends java.util.logging.SimpleFormatter {
// Pattern for MessageHeader data. Mostly pairs within curly brackets
private static volatile Pattern pattern = null;
// Pattern for Cookies
private static volatile Pattern cpattern = null;
public HttpLogFormatter() {
if (pattern == null) {
pattern = Pattern.compile("\\{[^\\}]*\\}");
cpattern = Pattern.compile("[^,\\] ]{2,}");
}
}
@Override
public String format(LogRecord record) {
String sourceClassName = record.getSourceClassName();
if (sourceClassName == null ||
!(sourceClassName.startsWith("sun.net.www.protocol.http") ||
sourceClassName.startsWith("sun.net.www.http"))) {
return super.format(record);
}
String src = record.getMessage();
StringBuilder buf = new StringBuilder("HTTP: ");
if (src.startsWith("sun.net.www.MessageHeader@")) {
// MessageHeader logs are composed of pairs within curly brackets
// Let's extract them to make it more readable. That way we get one
// header pair (name, value) per line. A lot easier to read.
Matcher match = pattern.matcher(src);
while (match.find()) {
int i = match.start();
int j = match.end();
String s = src.substring(i + 1, j - 1);
if (s.startsWith("null: ")) {
s = s.substring(6);
}
if (s.endsWith(": null")) {
s = s.substring(0, s.length() - 6);
}
buf.append("\t").append(s).append("\n");
}
} else if (src.startsWith("Cookies retrieved: {")) {
// This comes from the Cookie handler, let's clean up the format a bit
String s = src.substring(20);
buf.append("Cookies from handler:\n");
while (s.length() >= 7) {
if (s.startsWith("Cookie=[")) {
String s2 = s.substring(8);
int c = s2.indexOf("Cookie2=[");
if (c > 0) {
s2 = s2.substring(0, c-1);
s = s2.substring(c);
} else {
s = "";
}
if (s2.length() < 4) {
continue;
}
Matcher m = cpattern.matcher(s2);
while (m.find()) {
int i = m.start();
int j = m.end();
if (i >= 0) {
String cookie = s2.substring(i + 1, j > 0 ? j - 1 : s2.length() - 1);
buf.append("\t").append(cookie).append("\n");
}
}
}
if (s.startsWith("Cookie2=[")) {
String s2 = s.substring(9);
int c = s2.indexOf("Cookie=[");
if (c > 0) {
s2 = s2.substring(0, c-1);
s = s2.substring(c);
} else {
s = "";
}
Matcher m = cpattern.matcher(s2);
while (m.find()) {
int i = m.start();
int j = m.end();
if (i >= 0) {
String cookie = s2.substring(i+1, j > 0 ? j-1 : s2.length() - 1);
buf.append("\t").append(cookie).append("\n");
}
}
}
}
} else {
// Anything else we let as is.
buf.append(src).append("\n");
}
return buf.toString();
}
}

View file

@ -0,0 +1,465 @@
/*
* Copyright (c) 2015, 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 sun.util.logging.internal;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.ResourceBundle;
import java.util.function.Supplier;
import java.lang.System.LoggerFinder;
import java.lang.System.Logger;
import java.util.Objects;
import java.util.logging.LogManager;
import jdk.internal.logger.DefaultLoggerFinder;
import java.util.logging.LoggingPermission;
import sun.util.logging.PlatformLogger;
import sun.util.logging.PlatformLogger.ConfigurableBridge.LoggerConfiguration;
/**
* This {@code LoggingProviderImpl} is the JDK internal implementation of the
* {@link jdk.internal.logger.DefaultLoggerFinder} which is used by
* the default implementation of the {@link Logger}
* when no {@link LoggerFinder} is found
* and {@code java.util.logging} is present.
* When {@code java.util.logging} is present, the {@code LoggingProviderImpl}
* is {@linkplain java.util.ServiceLoader#loadInstalled(Class) installed} as
* an internal service provider, making it possible to use {@code java.util.logging}
* as the backend for loggers returned by the default LoggerFinder implementation.
* <p>
* This implementation of {@link DefaultLoggerFinder} returns instances of
* {@link java.lang.System.Logger} which
* delegate to a wrapped instance of {@link java.util.logging.Logger
* java.util.logging.Logger}.
* <br>
* Loggers returned by this class can therefore be configured by accessing
* their wrapped implementation through the regular {@code java.util.logging}
* APIs - such as {@link java.util.logging.LogManager java.util.logging.LogManager}
* and {@link java.util.logging.Logger java.util.logging.Logger}.
*
* @apiNote Programmers are not expected to call this class directly.
* Instead they should rely on the static methods defined by
* {@link java.lang.System java.lang.System}.
* <p>
* To replace this default
* {@code java.util.logging} backend, an application is expected to install
* its own {@link java.lang.System.LoggerFinder}.
*
* @see java.lang.System.Logger
* @see java.lang.System.LoggerFinder
* @see sun.util.logging.PlatformLogger.Bridge
* @see java.lang.System
* @see jdk.internal.logger
* @see jdk.internal.logger
*
*/
public final class LoggingProviderImpl extends DefaultLoggerFinder {
static final RuntimePermission LOGGERFINDER_PERMISSION =
new RuntimePermission("loggerFinder");
private static final LoggingPermission LOGGING_CONTROL_PERMISSION =
new LoggingPermission("control", null);
/**
* Creates a new instance of LoggingProviderImpl.
* @throws SecurityException if the calling code does not have the
* {@code RuntimePermission("loggerFinder")}.
*/
public LoggingProviderImpl() {
}
/**
* A logger that delegates to a java.util.logging.Logger delegate.
*/
static final class JULWrapper extends LoggerConfiguration
implements System.Logger, PlatformLogger.Bridge,
PlatformLogger.ConfigurableBridge {
private static final java.util.logging.Level[] spi2JulLevelMapping = {
java.util.logging.Level.ALL, // mapped from ALL
java.util.logging.Level.FINER, // mapped from TRACE
java.util.logging.Level.FINE, // mapped from DEBUG
java.util.logging.Level.INFO, // mapped from INFO
java.util.logging.Level.WARNING, // mapped from WARNING
java.util.logging.Level.SEVERE, // mapped from ERROR
java.util.logging.Level.OFF // mapped from OFF
};
private static final java.util.logging.Level[] platform2JulLevelMapping = {
java.util.logging.Level.ALL, // mapped from ALL
java.util.logging.Level.FINEST, // mapped from FINEST
java.util.logging.Level.FINER, // mapped from FINER
java.util.logging.Level.FINE, // mapped from FINE
java.util.logging.Level.CONFIG, // mapped from CONFIG
java.util.logging.Level.INFO, // mapped from INFO
java.util.logging.Level.WARNING, // mapped from WARNING
java.util.logging.Level.SEVERE, // mapped from SEVERE
java.util.logging.Level.OFF // mapped from OFF
};
private final java.util.logging.Logger julLogger;
private JULWrapper(java.util.logging.Logger logger) {
this.julLogger = logger;
}
@Override
public String getName() {
return julLogger.getName();
}
@Override
public void log(sun.util.logging.PlatformLogger.Level level, String msg, Throwable throwable) {
julLogger.log(toJUL(level), msg, throwable);
}
@Override
public void log(sun.util.logging.PlatformLogger.Level level, String format, Object... params) {
julLogger.log(toJUL(level), format, params);
}
@Override
public void log(sun.util.logging.PlatformLogger.Level level, String msg) {
julLogger.log(toJUL(level), msg);
}
@Override
public void log(sun.util.logging.PlatformLogger.Level level, Supplier<String> msgSuppier) {
julLogger.log(toJUL(level), msgSuppier);
}
@Override
public void log(sun.util.logging.PlatformLogger.Level level, Throwable thrown, Supplier<String> msgSuppier) {
julLogger.log(toJUL(level), thrown, msgSuppier);
}
@Override
public void logrb(sun.util.logging.PlatformLogger.Level level, ResourceBundle bundle, String key, Throwable throwable) {
julLogger.logrb(toJUL(level), bundle, key, throwable);
}
@Override
public void logrb(sun.util.logging.PlatformLogger.Level level, ResourceBundle bundle, String key, Object... params) {
julLogger.logrb(toJUL(level), bundle, key, params);
}
@Override
public void logp(sun.util.logging.PlatformLogger.Level level, String sourceClass, String sourceMethod, String msg) {
julLogger.logp(toJUL(level), sourceClass, sourceMethod, msg);
}
@Override
public void logp(sun.util.logging.PlatformLogger.Level level, String sourceClass, String sourceMethod,
Supplier<String> msgSupplier) {
julLogger.logp(toJUL(level), sourceClass, sourceMethod, msgSupplier);
}
@Override
public void logp(sun.util.logging.PlatformLogger.Level level, String sourceClass, String sourceMethod,
String msg, Object... params) {
julLogger.logp(toJUL(level), sourceClass, sourceMethod, msg, params);
}
@Override
public void logp(sun.util.logging.PlatformLogger.Level level, String sourceClass, String sourceMethod,
String msg, Throwable thrown) {
julLogger.logp(toJUL(level), sourceClass, sourceMethod, msg, thrown);
}
@Override
public void logp(sun.util.logging.PlatformLogger.Level level, String sourceClass, String sourceMethod,
Throwable thrown, Supplier<String> msgSupplier) {
julLogger.logp(toJUL(level), sourceClass, sourceMethod,
thrown, msgSupplier);
}
@Override
public void logrb(sun.util.logging.PlatformLogger.Level level, String sourceClass, String sourceMethod,
ResourceBundle bundle, String key, Object... params) {
julLogger.logrb(toJUL(level), sourceClass, sourceMethod,
bundle, key, params);
}
@Override
public void logrb(sun.util.logging.PlatformLogger.Level level, String sourceClass, String sourceMethod,
ResourceBundle bundle, String key, Throwable thrown) {
julLogger.logrb(toJUL(level), sourceClass, sourceMethod,
bundle, key, thrown);
}
@Override
public boolean isLoggable(sun.util.logging.PlatformLogger.Level level) {
return julLogger.isLoggable(toJUL(level));
}
// -----------------------------------------------------------------
// Generic methods taking a Level as parameter
// -----------------------------------------------------------------
@Override
public boolean isLoggable(Level level) {
return julLogger.isLoggable(toJUL(level));
}
@Override
public void log(Level level, String msg) {
julLogger.log(toJUL(level), msg);
}
@Override
public void log(Level level,
Supplier<String> msgSupplier) {
// We need to check for null here to satisfy the contract
// of System.Logger - because the underlying implementation
// of julLogger will check for it only if the level is
// loggable
Objects.requireNonNull(msgSupplier);
julLogger.log(toJUL(level), msgSupplier);
}
@Override
public void log(Level level, Object obj) {
// We need to check for null here to satisfy the contract
// of System.Logger - because the underlying implementation
// of julLogger will check for it only if the level is
// loggable
Objects.requireNonNull(obj);
julLogger.log(toJUL(level), () -> obj.toString());
}
@Override
public void log(Level level,
String msg, Throwable thrown) {
julLogger.log(toJUL(level), msg, thrown);
}
@Override
public void log(Level level, Supplier<String> msgSupplier,
Throwable thrown) {
// We need to check for null here to satisfy the contract
// of System.Logger - because the underlying implementation
// of julLogger will check for it only if the level is
// loggable
Objects.requireNonNull(msgSupplier);
julLogger.log(toJUL(level), thrown, msgSupplier);
}
@Override
public void log(Level level,
String format, Object... params) {
julLogger.log(toJUL(level), format, params);
}
@Override
public void log(Level level, ResourceBundle bundle,
String key, Throwable thrown) {
julLogger.logrb(toJUL(level), bundle, key, thrown);
}
@Override
public void log(Level level, ResourceBundle bundle,
String format, Object... params) {
julLogger.logrb(toJUL(level), bundle, format, params);
}
static java.util.logging.Level toJUL(Level level) {
if (level == null) return null;
assert level.ordinal() < spi2JulLevelMapping.length;
return spi2JulLevelMapping[level.ordinal()];
}
// ---------------------------------------------------------
// Methods from PlatformLogger.Bridge
// ---------------------------------------------------------
@Override
public boolean isEnabled() {
return julLogger.getLevel() != java.util.logging.Level.OFF;
}
@Override
public PlatformLogger.Level getPlatformLevel() {
final java.util.logging.Level javaLevel = julLogger.getLevel();
if (javaLevel == null) return null;
try {
return PlatformLogger.Level.valueOf(javaLevel.getName());
} catch (IllegalArgumentException e) {
return PlatformLogger.Level.valueOf(javaLevel.intValue());
}
}
@Override
public void setPlatformLevel(PlatformLogger.Level level) {
// null is allowed here
julLogger.setLevel(toJUL(level));
}
@Override
public LoggerConfiguration getLoggerConfiguration() {
return this;
}
static java.util.logging.Level toJUL(PlatformLogger.Level level) {
// The caller will throw if null is invalid in its context.
// There's at least one case where a null level is valid.
if (level == null) return null;
assert level.ordinal() < platform2JulLevelMapping.length;
return platform2JulLevelMapping[level.ordinal()];
}
@Override
public boolean equals(Object obj) {
return (obj instanceof JULWrapper)
&& obj.getClass() == this.getClass()
&& ((JULWrapper)obj).julLogger == this.julLogger;
}
@Override
public int hashCode() {
return julLogger.hashCode();
}
// A JULWrapper is just a stateless thin shell over a JUL logger - so
// for a given JUL logger, we could always return the same wrapper.
//
// This is an optimization which may - or may not - be worth the
// trouble: if many classes use the same logger, and if each class
// keeps a reference to that logger, then caching the wrapper will
// be worthwhile. Otherwise, if each logger is only referred once,
// then the cache will eat up more memory than would be necessary...
//
// Here is an example of how we could implement JULWrapper.of(...)
// if we wanted to create at most one wrapper instance for each logger
// instance:
//
// static final WeakHashMap<JULWrapper, WeakReference<JULWrapper>>
// wrappers = new WeakHashMap<>();
//
// static JULWrapper of(java.util.logging.Logger logger) {
//
// // First access without synchronizing
// final JULWrapper candidate = new JULWrapper(logger);
// WeakReference<JULWrapper> ref = wrappers.get(candidate);
// JULWrapper found = ref.get();
//
// // OK - we found it - lets return it.
// if (found != null) return found;
//
// // Not found. Need to synchronize.
// synchronized (wrappers) {
// ref = wrappers.get(candidate);
// found = ref.get();
// if (found == null) {
// wrappers.put(candidate, new WeakReference<>(candidate));
// found = candidate;
// }
// }
// assert found != null;
// return found;
// }
//
// But given that it may end up eating more memory in the nominal case
// (where each class that does logging has its own logger with the
// class name as logger name and stashes that logger away in a static
// field, thus making the cache redundant - as only one wrapper will
// ever be created anyway) - then we will simply return a new wrapper
// for each invocation of JULWrapper.of(...) - which may
// still prove more efficient in terms of memory consumption...
//
static JULWrapper of(java.util.logging.Logger logger) {
return new JULWrapper(logger);
}
}
/**
* Creates a java.util.logging.Logger for the given module.
* @param name the logger name.
* @param module the module for which the logger should be created.
* @return a Logger suitable for use in the given module.
*/
private static java.util.logging.Logger demandJULLoggerFor(final String name,
Module module) {
final LogManager manager = LogManager.getLogManager();
final SecurityManager sm = System.getSecurityManager();
if (sm == null) {
return logManagerAccess.demandLoggerFor(manager, name, module);
} else {
final PrivilegedAction<java.util.logging.Logger> pa =
() -> logManagerAccess.demandLoggerFor(manager, name, module);
return AccessController.doPrivileged(pa, null, LOGGING_CONTROL_PERMISSION);
}
}
/**
* {@inheritDoc}
*
* @apiNote The logger returned by this method can be configured through
* its {@linkplain java.util.logging.LogManager#getLogger(String)
* corresponding java.util.logging.Logger backend}.
*
* @return {@inheritDoc}
* @throws SecurityException if the calling code doesn't have the
* {@code RuntimePermission("loggerFinder")}.
*/
@Override
protected Logger demandLoggerFor(String name, Module module) {
final SecurityManager sm = System.getSecurityManager();
if (sm != null) {
sm.checkPermission(LOGGERFINDER_PERMISSION);
}
return JULWrapper.of(demandJULLoggerFor(name,module));
}
public static interface LogManagerAccess {
java.util.logging.Logger demandLoggerFor(LogManager manager,
String name, Module module);
}
// Hook for tests
public static LogManagerAccess getLogManagerAccess() {
final SecurityManager sm = System.getSecurityManager();
if (sm != null) {
sm.checkPermission(LOGGING_CONTROL_PERMISSION);
}
// Triggers initialization of accessJulLogger if not set.
if (logManagerAccess == null) LogManager.getLogManager();
return logManagerAccess;
}
private static volatile LogManagerAccess logManagerAccess;
public static void setLogManagerAccess(LogManagerAccess accesLoggers) {
final SecurityManager sm = System.getSecurityManager();
if (sm != null) {
sm.checkPermission(LOGGING_CONTROL_PERMISSION);
}
logManagerAccess = accesLoggers;
}
}

View file

@ -0,0 +1,55 @@
/*
* Copyright (c) 2015, 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.
*/
/**
* <p>
* <b>[JDK INTERNAL]</b>
* The {@code sun.util.logging.internal} package defines an internal
* implementation of the {@link jdk.internal.logger.DefaultLoggerFinder} which
* provides an extension of the {@link java.lang.System.Logger System.Logger}
* interface making it easy to bridge from {@link java.util.logging};
* the JDK default implementation of the LoggerFinder will return loggers
* implementing this extension when {@code java.util.logging} is present.
* </p>
* <p>
* When {@code java.util.logging} is present, Logger instances returned by
* the JDK default implementation of the LoggerFinder
* wrap an instance of {@link java.util.logging.Logger java.util.logging.Logger}
* and implement the {@link
* sun.util.logging.PlatformLogger.Bridge PlatformLogger.Bridge}
* extension, overriding all the methods defined in
* that extension in order to call the corresponding methods on their wrapped
* {@linkplain java.util.logging.Logger backend Logger} instance.
* <p>
* <br>
* @see java.lang.System.LoggerFinder
* @see java.lang.System.Logger
* @see sun.util.logging.PlatformLogger
* @see sun.util.logging.PlatformLogger.Bridge
* @see jdk.internal.logger
*
* @since 9
*/
package sun.util.logging.internal;

View file

@ -0,0 +1,46 @@
#
# Copyright (c) 2001, 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.
#
# Localizations for Level names. For the US locale
# these are the same as the non-localized level name.
# The following ALL CAPS words should be translated.
ALL=All
# The following ALL CAPS words should be translated.
SEVERE=Severe
# The following ALL CAPS words should be translated.
WARNING=Warning
# The following ALL CAPS words should be translated.
INFO=Info
# The following ALL CAPS words should be translated.
CONFIG= Config
# The following ALL CAPS words should be translated.
FINE=Fine
# The following ALL CAPS words should be translated.
FINER=Finer
# The following ALL CAPS words should be translated.
FINEST=Finest
# The following ALL CAPS words should be translated.
OFF=Off

View file

@ -0,0 +1,46 @@
#
# Copyright (c) 2001, 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.
#
# Localizations for Level names. For the US locale
# these are the same as the non-localized level name.
# The following ALL CAPS words should be translated.
ALL=Alle
# The following ALL CAPS words should be translated.
SEVERE=Schwerwiegend
# The following ALL CAPS words should be translated.
WARNING=Warnung
# The following ALL CAPS words should be translated.
INFO=Information
# The following ALL CAPS words should be translated.
CONFIG= Konfiguration
# The following ALL CAPS words should be translated.
FINE=Fein
# The following ALL CAPS words should be translated.
FINER=Feiner
# The following ALL CAPS words should be translated.
FINEST=Am feinsten
# The following ALL CAPS words should be translated.
OFF=Deaktiviert

View file

@ -0,0 +1,46 @@
#
# Copyright (c) 2001, 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.
#
# Localizations for Level names. For the US locale
# these are the same as the non-localized level name.
# The following ALL CAPS words should be translated.
ALL=Todo
# The following ALL CAPS words should be translated.
SEVERE=Grave
# The following ALL CAPS words should be translated.
WARNING=Advertencia
# The following ALL CAPS words should be translated.
INFO=Informaci\u00F3n
# The following ALL CAPS words should be translated.
CONFIG= Configurar
# The following ALL CAPS words should be translated.
FINE=Detallado
# The following ALL CAPS words should be translated.
FINER=Muy Detallado
# The following ALL CAPS words should be translated.
FINEST=M\u00E1s Detallado
# The following ALL CAPS words should be translated.
OFF=Desactivado

View file

@ -0,0 +1,46 @@
#
# Copyright (c) 2001, 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.
#
# Localizations for Level names. For the US locale
# these are the same as the non-localized level name.
# The following ALL CAPS words should be translated.
ALL=Tout
# The following ALL CAPS words should be translated.
SEVERE=Grave
# The following ALL CAPS words should be translated.
WARNING=Avertissement
# The following ALL CAPS words should be translated.
INFO=Infos
# The following ALL CAPS words should be translated.
CONFIG= Config
# The following ALL CAPS words should be translated.
FINE=Pr\u00E9cis
# The following ALL CAPS words should be translated.
FINER=Plus pr\u00E9cis
# The following ALL CAPS words should be translated.
FINEST=Le plus pr\u00E9cis
# The following ALL CAPS words should be translated.
OFF=D\u00E9sactiv\u00E9

View file

@ -0,0 +1,46 @@
#
# Copyright (c) 2001, 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.
#
# Localizations for Level names. For the US locale
# these are the same as the non-localized level name.
# The following ALL CAPS words should be translated.
ALL=Tutto
# The following ALL CAPS words should be translated.
SEVERE=Grave
# The following ALL CAPS words should be translated.
WARNING=Avvertenza
# The following ALL CAPS words should be translated.
INFO=Informazioni
# The following ALL CAPS words should be translated.
CONFIG= Configurazione
# The following ALL CAPS words should be translated.
FINE=Buono
# The following ALL CAPS words should be translated.
FINER=Migliore
# The following ALL CAPS words should be translated.
FINEST=Ottimale
# The following ALL CAPS words should be translated.
OFF=Non attivo

View file

@ -0,0 +1,46 @@
#
# Copyright (c) 2001, 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.
#
# Localizations for Level names. For the US locale
# these are the same as the non-localized level name.
# The following ALL CAPS words should be translated.
ALL=\u3059\u3079\u3066
# The following ALL CAPS words should be translated.
SEVERE=\u91CD\u5927
# The following ALL CAPS words should be translated.
WARNING=\u8B66\u544A
# The following ALL CAPS words should be translated.
INFO=\u60C5\u5831
# The following ALL CAPS words should be translated.
CONFIG= \u69CB\u6210
# The following ALL CAPS words should be translated.
FINE=\u666E\u901A
# The following ALL CAPS words should be translated.
FINER=\u8A73\u7D30
# The following ALL CAPS words should be translated.
FINEST=\u6700\u3082\u8A73\u7D30
# The following ALL CAPS words should be translated.
OFF=\u30AA\u30D5

View file

@ -0,0 +1,46 @@
#
# Copyright (c) 2001, 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.
#
# Localizations for Level names. For the US locale
# these are the same as the non-localized level name.
# The following ALL CAPS words should be translated.
ALL=\uBAA8\uB450
# The following ALL CAPS words should be translated.
SEVERE=\uC2EC\uAC01
# The following ALL CAPS words should be translated.
WARNING=\uACBD\uACE0
# The following ALL CAPS words should be translated.
INFO=\uC815\uBCF4
# The following ALL CAPS words should be translated.
CONFIG= \uAD6C\uC131
# The following ALL CAPS words should be translated.
FINE=\uBBF8\uC138
# The following ALL CAPS words should be translated.
FINER=\uBCF4\uB2E4 \uBBF8\uC138
# The following ALL CAPS words should be translated.
FINEST=\uAC00\uC7A5 \uBBF8\uC138
# The following ALL CAPS words should be translated.
OFF=\uD574\uC81C

View file

@ -0,0 +1,46 @@
#
# Copyright (c) 2001, 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.
#
# Localizations for Level names. For the US locale
# these are the same as the non-localized level name.
# The following ALL CAPS words should be translated.
ALL=Tudo
# The following ALL CAPS words should be translated.
SEVERE=Grave
# The following ALL CAPS words should be translated.
WARNING=Advert\u00EAncia
# The following ALL CAPS words should be translated.
INFO=Informa\u00E7\u00F5es
# The following ALL CAPS words should be translated.
CONFIG= Configura\u00E7\u00E3o
# The following ALL CAPS words should be translated.
FINE=Detalhado
# The following ALL CAPS words should be translated.
FINER=Mais Detalhado
# The following ALL CAPS words should be translated.
FINEST=O Mais Detalhado
# The following ALL CAPS words should be translated.
OFF=Desativado

View file

@ -0,0 +1,46 @@
#
# Copyright (c) 2001, 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.
#
# Localizations for Level names. For the US locale
# these are the same as the non-localized level name.
# The following ALL CAPS words should be translated.
ALL=Alla
# The following ALL CAPS words should be translated.
SEVERE=Allvarlig
# The following ALL CAPS words should be translated.
WARNING=Varning
# The following ALL CAPS words should be translated.
INFO=Info
# The following ALL CAPS words should be translated.
CONFIG= Konfig
# The following ALL CAPS words should be translated.
FINE=Fin
# The following ALL CAPS words should be translated.
FINER=Finare
# The following ALL CAPS words should be translated.
FINEST=Finaste
# The following ALL CAPS words should be translated.
OFF=Av

View file

@ -0,0 +1,46 @@
#
# Copyright (c) 2001, 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.
#
# Localizations for Level names. For the US locale
# these are the same as the non-localized level name.
# The following ALL CAPS words should be translated.
ALL=\u5168\u90E8
# The following ALL CAPS words should be translated.
SEVERE=\u4E25\u91CD
# The following ALL CAPS words should be translated.
WARNING=\u8B66\u544A
# The following ALL CAPS words should be translated.
INFO=\u4FE1\u606F
# The following ALL CAPS words should be translated.
CONFIG= \u914D\u7F6E
# The following ALL CAPS words should be translated.
FINE=\u8BE6\u7EC6
# The following ALL CAPS words should be translated.
FINER=\u8F83\u8BE6\u7EC6
# The following ALL CAPS words should be translated.
FINEST=\u975E\u5E38\u8BE6\u7EC6
# The following ALL CAPS words should be translated.
OFF=\u7981\u7528

View file

@ -0,0 +1,46 @@
#
# Copyright (c) 2001, 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.
#
# Localizations for Level names. For the US locale
# these are the same as the non-localized level name.
# The following ALL CAPS words should be translated.
ALL=\u6240\u6709
# The following ALL CAPS words should be translated.
SEVERE=\u56B4\u91CD
# The following ALL CAPS words should be translated.
WARNING=\u8B66\u544A
# The following ALL CAPS words should be translated.
INFO=\u8CC7\u8A0A
# The following ALL CAPS words should be translated.
CONFIG= \u7D44\u614B
# The following ALL CAPS words should be translated.
FINE=\u8A73\u7D30
# The following ALL CAPS words should be translated.
FINER=\u8F03\u8A73\u7D30
# The following ALL CAPS words should be translated.
FINEST=\u6700\u8A73\u7D30
# The following ALL CAPS words should be translated.
OFF=\u95DC\u9589

View file

@ -0,0 +1,63 @@
############################################################
# Default Logging Configuration File
#
# You can use a different file by specifying a filename
# with the java.util.logging.config.file system property.
# For example java -Djava.util.logging.config.file=myfile
############################################################
############################################################
# Global properties
############################################################
# "handlers" specifies a comma separated list of log Handler
# classes. These handlers will be installed during VM startup.
# Note that these classes must be on the system classpath.
# By default we only configure a ConsoleHandler, which will only
# show messages at the INFO and above levels.
handlers= java.util.logging.ConsoleHandler
# To also add the FileHandler, use the following line instead.
#handlers= java.util.logging.FileHandler, java.util.logging.ConsoleHandler
# Default global logging level.
# This specifies which kinds of events are logged across
# all loggers. For any given facility this global level
# can be overriden by a facility specific level
# Note that the ConsoleHandler also has a separate level
# setting to limit messages printed to the console.
.level= INFO
############################################################
# Handler specific properties.
# Describes specific configuration info for Handlers.
############################################################
# default file output is in user's home directory.
java.util.logging.FileHandler.pattern = %h/java%u.log
java.util.logging.FileHandler.limit = 50000
java.util.logging.FileHandler.count = 1
# Default number of locks FileHandler can obtain synchronously.
# This specifies maximum number of attempts to obtain lock file by FileHandler
# implemented by incrementing the unique field %u as per FileHandler API documentation.
java.util.logging.FileHandler.maxLocks = 100
java.util.logging.FileHandler.formatter = java.util.logging.XMLFormatter
# Limit the message that are printed on the console to INFO and above.
java.util.logging.ConsoleHandler.level = INFO
java.util.logging.ConsoleHandler.formatter = java.util.logging.SimpleFormatter
# Example to customize the SimpleFormatter output format
# to print one-line log message like this:
# <level>: <log message> [<date/time>]
#
# java.util.logging.SimpleFormatter.format=%4$s: %5$s [%1$tc]%n
############################################################
# Facility specific properties.
# Provides extra control for each logger.
############################################################
# For example, set the com.xyz.foo logger to only log SEVERE
# messages:
com.xyz.foo.level = SEVERE