feat(jdk8): move files to new folder to avoid resources compiled.
This commit is contained in:
456
jdkSrc/jdk8/sun/rmi/runtime/Log.java
Normal file
456
jdkSrc/jdk8/sun/rmi/runtime/Log.java
Normal file
@@ -0,0 +1,456 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package sun.rmi.runtime;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.PrintStream;
|
||||
import java.io.OutputStream;
|
||||
import java.rmi.server.LogStream;
|
||||
import java.util.logging.ConsoleHandler;
|
||||
import java.util.logging.Handler;
|
||||
import java.util.logging.Formatter;
|
||||
import java.util.logging.SimpleFormatter;
|
||||
import java.util.logging.StreamHandler;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
import java.util.logging.LogManager;
|
||||
import java.util.logging.LogRecord;
|
||||
import java.util.logging.StreamHandler;
|
||||
import java.util.Map;
|
||||
import java.util.HashMap;
|
||||
|
||||
/**
|
||||
* Utility which provides an abstract "logger" like RMI internal API
|
||||
* which can be directed to use one of two types of logging
|
||||
* infrastructure: the java.util.logging API or the
|
||||
* java.rmi.server.LogStream API. The default behavior is to use the
|
||||
* java.util.logging API. The LogStream API may be used instead by
|
||||
* setting the system property sun.rmi.log.useOld to true.
|
||||
*
|
||||
* For backwards compatibility, supports the RMI system logging
|
||||
* properties which pre-1.4 comprised the only way to configure RMI
|
||||
* logging. If the java.util.logging API is used and RMI system log
|
||||
* properties are set, the system properties override initial RMI
|
||||
* logger values as appropriate. If the java.util.logging API is
|
||||
* turned off, pre-1.4 logging behavior is used.
|
||||
*
|
||||
* @author Laird Dornin
|
||||
* @since 1.4
|
||||
*/
|
||||
@SuppressWarnings("deprecation")
|
||||
public abstract class Log {
|
||||
|
||||
/** Logger re-definition of old RMI log values */
|
||||
public static final Level BRIEF = Level.FINE;
|
||||
public static final Level VERBOSE = Level.FINER;
|
||||
|
||||
/* selects log implementation */
|
||||
private static final LogFactory logFactory;
|
||||
static {
|
||||
boolean useOld =
|
||||
Boolean.valueOf(java.security.AccessController.
|
||||
doPrivileged(new sun.security.action.GetPropertyAction(
|
||||
"sun.rmi.log.useOld"))).booleanValue();
|
||||
|
||||
/* set factory to select the logging facility to use */
|
||||
logFactory = (useOld ? (LogFactory) new LogStreamLogFactory() :
|
||||
(LogFactory) new LoggerLogFactory());
|
||||
}
|
||||
|
||||
/** "logger like" API to be used by RMI implementation */
|
||||
public abstract boolean isLoggable(Level level);
|
||||
public abstract void log(Level level, String message);
|
||||
public abstract void log(Level level, String message, Throwable thrown);
|
||||
|
||||
/** get and set the RMI server call output stream */
|
||||
public abstract void setOutputStream(OutputStream stream);
|
||||
public abstract PrintStream getPrintStream();
|
||||
|
||||
/** factory interface enables Logger and LogStream implementations */
|
||||
private static interface LogFactory {
|
||||
Log createLog(String loggerName, String oldLogName, Level level);
|
||||
}
|
||||
|
||||
/* access log objects */
|
||||
|
||||
/**
|
||||
* Access log for a tri-state system property.
|
||||
*
|
||||
* Need to first convert override value to a log level, taking
|
||||
* care to interpret a range of values between BRIEF, VERBOSE and
|
||||
* SILENT.
|
||||
*
|
||||
* An override < 0 is interpreted to mean that the logging
|
||||
* configuration should not be overridden. The level passed to the
|
||||
* factories createLog method will be null in this case.
|
||||
*
|
||||
* Note that if oldLogName is null and old logging is on, the
|
||||
* returned LogStreamLog will ignore the override parameter - the
|
||||
* log will never log messages. This permits new logs that only
|
||||
* write to Loggers to do nothing when old logging is active.
|
||||
*
|
||||
* Do not call getLog multiple times on the same logger name.
|
||||
* Since this is an internal API, no checks are made to ensure
|
||||
* that multiple logs do not exist for the same logger.
|
||||
*/
|
||||
public static Log getLog(String loggerName, String oldLogName,
|
||||
int override)
|
||||
{
|
||||
Level level;
|
||||
|
||||
if (override < 0) {
|
||||
level = null;
|
||||
} else if (override == LogStream.SILENT) {
|
||||
level = Level.OFF;
|
||||
} else if ((override > LogStream.SILENT) &&
|
||||
(override <= LogStream.BRIEF)) {
|
||||
level = BRIEF;
|
||||
} else if ((override > LogStream.BRIEF) &&
|
||||
(override <= LogStream.VERBOSE))
|
||||
{
|
||||
level = VERBOSE;
|
||||
} else {
|
||||
level = Level.FINEST;
|
||||
}
|
||||
return logFactory.createLog(loggerName, oldLogName, level);
|
||||
}
|
||||
|
||||
/**
|
||||
* Access logs associated with boolean properties
|
||||
*
|
||||
* Do not call getLog multiple times on the same logger name.
|
||||
* Since this is an internal API, no checks are made to ensure
|
||||
* that multiple logs do not exist for the same logger.
|
||||
*/
|
||||
public static Log getLog(String loggerName, String oldLogName,
|
||||
boolean override)
|
||||
{
|
||||
Level level = (override ? VERBOSE : null);
|
||||
return logFactory.createLog(loggerName, oldLogName, level);
|
||||
}
|
||||
|
||||
/**
|
||||
* Factory to create Log objects which deliver log messages to the
|
||||
* java.util.logging API.
|
||||
*/
|
||||
private static class LoggerLogFactory implements LogFactory {
|
||||
LoggerLogFactory() {}
|
||||
|
||||
/*
|
||||
* Accessor to obtain an arbitrary RMI logger with name
|
||||
* loggerName. If the level of the logger is greater than the
|
||||
* level for the system property with name, the logger level
|
||||
* will be set to the value of system property.
|
||||
*/
|
||||
public Log createLog(final String loggerName, String oldLogName,
|
||||
final Level level)
|
||||
{
|
||||
Logger logger = Logger.getLogger(loggerName);
|
||||
return new LoggerLog(logger, level);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Class specialized to log messages to the java.util.logging API
|
||||
*/
|
||||
private static class LoggerLog extends Log {
|
||||
|
||||
/* alternate console handler for RMI loggers */
|
||||
private static final Handler alternateConsole =
|
||||
java.security.AccessController.doPrivileged(
|
||||
new java.security.PrivilegedAction<Handler>() {
|
||||
public Handler run() {
|
||||
InternalStreamHandler alternate =
|
||||
new InternalStreamHandler(System.err);
|
||||
alternate.setLevel(Level.ALL);
|
||||
return alternate;
|
||||
}
|
||||
});
|
||||
|
||||
/** handler to which messages are copied */
|
||||
private InternalStreamHandler copyHandler = null;
|
||||
|
||||
/* logger to which log messages are written */
|
||||
private final Logger logger;
|
||||
|
||||
/* used as return value of RemoteServer.getLog */
|
||||
private LoggerPrintStream loggerSandwich;
|
||||
|
||||
/** creates a Log which will delegate to the given logger */
|
||||
private LoggerLog(final Logger logger, final Level level) {
|
||||
this.logger = logger;
|
||||
|
||||
if (level != null){
|
||||
java.security.AccessController.doPrivileged(
|
||||
new java.security.PrivilegedAction<Void>() {
|
||||
public Void run() {
|
||||
if (!logger.isLoggable(level)) {
|
||||
logger.setLevel(level);
|
||||
}
|
||||
logger.addHandler(alternateConsole);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isLoggable(Level level) {
|
||||
return logger.isLoggable(level);
|
||||
}
|
||||
|
||||
public void log(Level level, String message) {
|
||||
if (isLoggable(level)) {
|
||||
String[] source = getSource();
|
||||
logger.logp(level, source[0], source[1],
|
||||
Thread.currentThread().getName() + ": " + message);
|
||||
}
|
||||
}
|
||||
|
||||
public void log(Level level, String message, Throwable thrown) {
|
||||
if (isLoggable(level)) {
|
||||
String[] source = getSource();
|
||||
logger.logp(level, source[0], source[1],
|
||||
Thread.currentThread().getName() + ": " +
|
||||
message, thrown);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the output stream associated with the RMI server call
|
||||
* logger.
|
||||
*
|
||||
* Calling code needs LoggingPermission "control".
|
||||
*/
|
||||
public synchronized void setOutputStream(OutputStream out) {
|
||||
if (out != null) {
|
||||
if (!logger.isLoggable(VERBOSE)) {
|
||||
logger.setLevel(VERBOSE);
|
||||
}
|
||||
copyHandler = new InternalStreamHandler(out);
|
||||
copyHandler.setLevel(Log.VERBOSE);
|
||||
logger.addHandler(copyHandler);
|
||||
} else {
|
||||
/* ensure that messages are not logged */
|
||||
if (copyHandler != null) {
|
||||
logger.removeHandler(copyHandler);
|
||||
}
|
||||
copyHandler = null;
|
||||
}
|
||||
}
|
||||
|
||||
public synchronized PrintStream getPrintStream() {
|
||||
if (loggerSandwich == null) {
|
||||
loggerSandwich = new LoggerPrintStream(logger);
|
||||
}
|
||||
return loggerSandwich;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Subclass of StreamHandler for redirecting log output. flush
|
||||
* must be called in the publish and close methods.
|
||||
*/
|
||||
private static class InternalStreamHandler extends StreamHandler {
|
||||
InternalStreamHandler(OutputStream out) {
|
||||
super(out, new SimpleFormatter());
|
||||
}
|
||||
|
||||
public void publish(LogRecord record) {
|
||||
super.publish(record);
|
||||
flush();
|
||||
}
|
||||
|
||||
public void close() {
|
||||
flush();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* PrintStream which forwards log messages to the logger. Class
|
||||
* is needed to maintain backwards compatibility with
|
||||
* RemoteServer.{set|get}Log().
|
||||
*/
|
||||
private static class LoggerPrintStream extends PrintStream {
|
||||
|
||||
/** logger where output of this log is sent */
|
||||
private final Logger logger;
|
||||
|
||||
/** record the last character written to this stream */
|
||||
private int last = -1;
|
||||
|
||||
/** stream used for buffering lines */
|
||||
private final ByteArrayOutputStream bufOut;
|
||||
|
||||
private LoggerPrintStream(Logger logger)
|
||||
{
|
||||
super(new ByteArrayOutputStream());
|
||||
bufOut = (ByteArrayOutputStream) super.out;
|
||||
this.logger = logger;
|
||||
}
|
||||
|
||||
public void write(int b) {
|
||||
if ((last == '\r') && (b == '\n')) {
|
||||
last = -1;
|
||||
return;
|
||||
} else if ((b == '\n') || (b == '\r')) {
|
||||
try {
|
||||
/* write the converted bytes of the log message */
|
||||
String message =
|
||||
Thread.currentThread().getName() + ": " +
|
||||
bufOut.toString();
|
||||
logger.logp(Level.INFO, "LogStream", "print", message);
|
||||
} finally {
|
||||
bufOut.reset();
|
||||
}
|
||||
} else {
|
||||
super.write(b);
|
||||
}
|
||||
last = b;
|
||||
}
|
||||
|
||||
public void write(byte b[], int off, int len) {
|
||||
if (len < 0) {
|
||||
throw new ArrayIndexOutOfBoundsException(len);
|
||||
}
|
||||
for (int i = 0; i < len; i++) {
|
||||
write(b[off + i]);
|
||||
}
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return "RMI";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Factory to create Log objects which deliver log messages to the
|
||||
* java.rmi.server.LogStream API
|
||||
*/
|
||||
private static class LogStreamLogFactory implements LogFactory {
|
||||
LogStreamLogFactory() {}
|
||||
|
||||
/* create a new LogStreamLog for the specified log */
|
||||
public Log createLog(String loggerName, String oldLogName,
|
||||
Level level)
|
||||
{
|
||||
LogStream stream = null;
|
||||
if (oldLogName != null) {
|
||||
stream = LogStream.log(oldLogName);
|
||||
}
|
||||
return new LogStreamLog(stream, level);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Class specialized to log messages to the
|
||||
* java.rmi.server.LogStream API
|
||||
*/
|
||||
private static class LogStreamLog extends Log {
|
||||
/** Log stream to which log messages are written */
|
||||
private final LogStream stream;
|
||||
|
||||
/** the level of the log as set by associated property */
|
||||
private int levelValue = Level.OFF.intValue();
|
||||
|
||||
private LogStreamLog(LogStream stream, Level level) {
|
||||
if ((stream != null) && (level != null)) {
|
||||
/* if the stream or level is null, don't log any
|
||||
* messages
|
||||
*/
|
||||
levelValue = level.intValue();
|
||||
}
|
||||
this.stream = stream;
|
||||
}
|
||||
|
||||
public synchronized boolean isLoggable(Level level) {
|
||||
return (level.intValue() >= levelValue);
|
||||
}
|
||||
|
||||
public void log(Level messageLevel, String message) {
|
||||
if (isLoggable(messageLevel)) {
|
||||
String[] source = getSource();
|
||||
stream.println(unqualifiedName(source[0]) +
|
||||
"." + source[1] + ": " + message);
|
||||
}
|
||||
}
|
||||
|
||||
public void log(Level level, String message, Throwable thrown) {
|
||||
if (isLoggable(level)) {
|
||||
/*
|
||||
* keep output contiguous and maintain the contract of
|
||||
* RemoteServer.getLog
|
||||
*/
|
||||
synchronized (stream) {
|
||||
String[] source = getSource();
|
||||
stream.println(unqualifiedName(source[0]) + "." +
|
||||
source[1] + ": " + message);
|
||||
thrown.printStackTrace(stream);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public PrintStream getPrintStream() {
|
||||
return stream;
|
||||
}
|
||||
|
||||
public synchronized void setOutputStream(OutputStream out) {
|
||||
if (out != null) {
|
||||
if (VERBOSE.intValue() < levelValue) {
|
||||
levelValue = VERBOSE.intValue();
|
||||
}
|
||||
stream.setOutputStream(out);
|
||||
} else {
|
||||
/* ensure that messages are not logged */
|
||||
levelValue = Level.OFF.intValue();
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Mimic old log messages that only contain unqualified names.
|
||||
*/
|
||||
private static String unqualifiedName(String name) {
|
||||
int lastDot = name.lastIndexOf(".");
|
||||
if (lastDot >= 0) {
|
||||
name = name.substring(lastDot + 1);
|
||||
}
|
||||
name = name.replace('$', '.');
|
||||
return name;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtain class and method names of code calling a log method.
|
||||
*/
|
||||
private static String[] getSource() {
|
||||
StackTraceElement[] trace = (new Exception()).getStackTrace();
|
||||
return new String[] {
|
||||
trace[3].getClassName(),
|
||||
trace[3].getMethodName()
|
||||
};
|
||||
}
|
||||
}
|
||||
138
jdkSrc/jdk8/sun/rmi/runtime/NewThreadAction.java
Normal file
138
jdkSrc/jdk8/sun/rmi/runtime/NewThreadAction.java
Normal file
@@ -0,0 +1,138 @@
|
||||
/*
|
||||
* Copyright (c) 2000, 2005, 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.rmi.runtime;
|
||||
|
||||
import java.security.AccessController;
|
||||
import java.security.PrivilegedAction;
|
||||
import sun.security.util.SecurityConstants;
|
||||
|
||||
/**
|
||||
* A PrivilegedAction for creating a new thread conveniently with an
|
||||
* AccessController.doPrivileged construct.
|
||||
*
|
||||
* All constructors allow the choice of the Runnable for the new
|
||||
* thread to execute, the name of the new thread (which will be
|
||||
* prefixed with "RMI "), and whether or not it will be a daemon
|
||||
* thread.
|
||||
*
|
||||
* The new thread may be created in the system thread group (the root
|
||||
* of the thread group tree) or an internally created non-system
|
||||
* thread group, as specified at construction of this class.
|
||||
*
|
||||
* The new thread will have the system class loader as its initial
|
||||
* context class loader (that is, its context class loader will NOT be
|
||||
* inherited from the current thread).
|
||||
*
|
||||
* @author Peter Jones
|
||||
**/
|
||||
public final class NewThreadAction implements PrivilegedAction<Thread> {
|
||||
|
||||
/** cached reference to the system (root) thread group */
|
||||
static final ThreadGroup systemThreadGroup =
|
||||
AccessController.doPrivileged(new PrivilegedAction<ThreadGroup>() {
|
||||
public ThreadGroup run() {
|
||||
ThreadGroup group = Thread.currentThread().getThreadGroup();
|
||||
ThreadGroup parent;
|
||||
while ((parent = group.getParent()) != null) {
|
||||
group = parent;
|
||||
}
|
||||
return group;
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* special child of the system thread group for running tasks that
|
||||
* may execute user code, so that the security policy for threads in
|
||||
* the system thread group will not apply
|
||||
*/
|
||||
static final ThreadGroup userThreadGroup =
|
||||
AccessController.doPrivileged(new PrivilegedAction<ThreadGroup>() {
|
||||
public ThreadGroup run() {
|
||||
return new ThreadGroup(systemThreadGroup, "RMI Runtime");
|
||||
}
|
||||
});
|
||||
|
||||
private final ThreadGroup group;
|
||||
private final Runnable runnable;
|
||||
private final String name;
|
||||
private final boolean daemon;
|
||||
|
||||
NewThreadAction(ThreadGroup group, Runnable runnable,
|
||||
String name, boolean daemon)
|
||||
{
|
||||
this.group = group;
|
||||
this.runnable = runnable;
|
||||
this.name = name;
|
||||
this.daemon = daemon;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an action that will create a new thread in the
|
||||
* system thread group.
|
||||
*
|
||||
* @param runnable the Runnable for the new thread to execute
|
||||
*
|
||||
* @param name the name of the new thread
|
||||
*
|
||||
* @param daemon if true, new thread will be a daemon thread;
|
||||
* if false, new thread will not be a daemon thread
|
||||
*/
|
||||
public NewThreadAction(Runnable runnable, String name, boolean daemon) {
|
||||
this(systemThreadGroup, runnable, name, daemon);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an action that will create a new thread.
|
||||
*
|
||||
* @param runnable the Runnable for the new thread to execute
|
||||
*
|
||||
* @param name the name of the new thread
|
||||
*
|
||||
* @param daemon if true, new thread will be a daemon thread;
|
||||
* if false, new thread will not be a daemon thread
|
||||
*
|
||||
* @param user if true, thread will be created in a non-system
|
||||
* thread group; if false, thread will be created in the system
|
||||
* thread group
|
||||
*/
|
||||
public NewThreadAction(Runnable runnable, String name, boolean daemon,
|
||||
boolean user)
|
||||
{
|
||||
this(user ? userThreadGroup : systemThreadGroup,
|
||||
runnable, name, daemon);
|
||||
}
|
||||
|
||||
public Thread run() {
|
||||
SecurityManager sm = System.getSecurityManager();
|
||||
if (sm != null) {
|
||||
sm.checkPermission(SecurityConstants.GET_CLASSLOADER_PERMISSION);
|
||||
}
|
||||
Thread t = new Thread(group, runnable, "RMI " + name);
|
||||
t.setContextClassLoader(ClassLoader.getSystemClassLoader());
|
||||
t.setDaemon(daemon);
|
||||
return t;
|
||||
}
|
||||
}
|
||||
131
jdkSrc/jdk8/sun/rmi/runtime/RuntimeUtil.java
Normal file
131
jdkSrc/jdk8/sun/rmi/runtime/RuntimeUtil.java
Normal file
@@ -0,0 +1,131 @@
|
||||
/*
|
||||
* Copyright (c) 2005, 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.rmi.runtime;
|
||||
|
||||
import java.security.AccessController;
|
||||
import java.security.Permission;
|
||||
import java.security.PrivilegedAction;
|
||||
import java.util.concurrent.ScheduledThreadPoolExecutor;
|
||||
import java.util.concurrent.ThreadFactory;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.logging.Level;
|
||||
import sun.security.action.GetIntegerAction;
|
||||
|
||||
/**
|
||||
* RMI runtime implementation utilities.
|
||||
*
|
||||
* There is a single instance of this class, which can be obtained
|
||||
* with a GetInstanceAction. Getting the instance requires
|
||||
* RuntimePermission("sun.rmi.runtime.RuntimeUtil.getInstance")
|
||||
* because the public methods of this class expose security-sensitive
|
||||
* capabilities.
|
||||
*
|
||||
* @author Peter Jones
|
||||
**/
|
||||
public final class RuntimeUtil {
|
||||
|
||||
/** runtime package log */
|
||||
private static final Log runtimeLog =
|
||||
Log.getLog("sun.rmi.runtime", null, false);
|
||||
|
||||
/** number of scheduler threads */
|
||||
private static final int schedulerThreads = // default 1
|
||||
AccessController.doPrivileged(
|
||||
new GetIntegerAction("sun.rmi.runtime.schedulerThreads", 1));
|
||||
|
||||
/** permission required to get instance */
|
||||
private static final Permission GET_INSTANCE_PERMISSION =
|
||||
new RuntimePermission("sun.rmi.runtime.RuntimeUtil.getInstance");
|
||||
|
||||
/** the singleton instance of this class */
|
||||
private static final RuntimeUtil instance = new RuntimeUtil();
|
||||
|
||||
/** thread pool for scheduling delayed tasks */
|
||||
private final ScheduledThreadPoolExecutor scheduler;
|
||||
|
||||
private RuntimeUtil() {
|
||||
scheduler = new ScheduledThreadPoolExecutor(
|
||||
schedulerThreads,
|
||||
new ThreadFactory() {
|
||||
private final AtomicInteger count = new AtomicInteger(0);
|
||||
public Thread newThread(Runnable runnable) {
|
||||
try {
|
||||
return AccessController.doPrivileged(
|
||||
new NewThreadAction(runnable,
|
||||
"Scheduler(" + count.getAndIncrement() + ")",
|
||||
true));
|
||||
} catch (Throwable t) {
|
||||
runtimeLog.log(Level.WARNING,
|
||||
"scheduler thread factory throws", t);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
});
|
||||
/*
|
||||
* We would like to allow the scheduler's threads to terminate
|
||||
* if possible, but a bug in DelayQueue.poll can cause code
|
||||
* like this to result in a busy loop:
|
||||
*/
|
||||
// stpe.setKeepAliveTime(10, TimeUnit.MINUTES);
|
||||
// stpe.allowCoreThreadTimeOut(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* A PrivilegedAction for getting the RuntimeUtil instance.
|
||||
**/
|
||||
public static class GetInstanceAction
|
||||
implements PrivilegedAction<RuntimeUtil>
|
||||
{
|
||||
/**
|
||||
* Creates an action that returns the RuntimeUtil instance.
|
||||
**/
|
||||
public GetInstanceAction() {
|
||||
}
|
||||
|
||||
public RuntimeUtil run() {
|
||||
return getInstance();
|
||||
}
|
||||
}
|
||||
|
||||
private static RuntimeUtil getInstance() {
|
||||
SecurityManager sm = System.getSecurityManager();
|
||||
if (sm != null) {
|
||||
sm.checkPermission(GET_INSTANCE_PERMISSION);
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the shared thread pool for scheduling delayed tasks.
|
||||
*
|
||||
* Note that the returned pool has limited concurrency, so
|
||||
* submitted tasks should be short-lived and should not block.
|
||||
**/
|
||||
public ScheduledThreadPoolExecutor getScheduler() {
|
||||
return scheduler;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user