feat(jdk8): move files to new folder to avoid resources compiled.
This commit is contained in:
783
jdkSrc/jdk8/com/sun/jmx/remote/util/EnvHelp.java
Normal file
783
jdkSrc/jdk8/com/sun/jmx/remote/util/EnvHelp.java
Normal file
@@ -0,0 +1,783 @@
|
||||
|
||||
/*
|
||||
* Copyright (c) 2003, 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 com.sun.jmx.remote.util;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.ObjectOutputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.Hashtable;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import java.util.SortedMap;
|
||||
import java.util.SortedSet;
|
||||
import java.util.StringTokenizer;
|
||||
import java.util.TreeMap;
|
||||
import java.util.TreeSet;
|
||||
|
||||
import java.security.AccessController;
|
||||
|
||||
import javax.management.ObjectName;
|
||||
import javax.management.MBeanServer;
|
||||
import javax.management.InstanceNotFoundException;
|
||||
import javax.management.remote.JMXConnectorFactory;
|
||||
import javax.management.remote.JMXConnectorServerFactory;
|
||||
import com.sun.jmx.mbeanserver.GetPropertyAction;
|
||||
import com.sun.jmx.remote.security.NotificationAccessController;
|
||||
import javax.management.remote.JMXConnector;
|
||||
import javax.management.remote.JMXConnectorServer;
|
||||
|
||||
public class EnvHelp {
|
||||
|
||||
/**
|
||||
* Name of the attribute that specifies a list of class names acceptable
|
||||
* as parameters to the {@link RMIServer#newClient(java.lang.Object) RMIServer.newClient()}
|
||||
* remote method call.
|
||||
* <p>
|
||||
* This list of classes should correspond to the transitive closure of the
|
||||
* credentials class (or classes) used by the installed {@linkplain JMXAuthenticator}
|
||||
* associated with the {@linkplain RMIServer} implementation.
|
||||
* <p>
|
||||
* If the attribute is not set, or is null, then any class is
|
||||
* deemed acceptable.
|
||||
*/
|
||||
public static final String CREDENTIAL_TYPES =
|
||||
"jmx.remote.rmi.server.credential.types";
|
||||
|
||||
/**
|
||||
* <p>Name of the attribute that specifies a default class loader
|
||||
* object.
|
||||
* The value associated with this attribute is a ClassLoader object</p>
|
||||
*/
|
||||
private static final String DEFAULT_CLASS_LOADER =
|
||||
JMXConnectorFactory.DEFAULT_CLASS_LOADER;
|
||||
|
||||
/**
|
||||
* <p>Name of the attribute that specifies a default class loader
|
||||
* ObjectName.
|
||||
* The value associated with this attribute is an ObjectName object</p>
|
||||
*/
|
||||
private static final String DEFAULT_CLASS_LOADER_NAME =
|
||||
JMXConnectorServerFactory.DEFAULT_CLASS_LOADER_NAME;
|
||||
|
||||
/**
|
||||
* Get the Connector Server default class loader.
|
||||
* <p>
|
||||
* Returns:
|
||||
* <p>
|
||||
* <ul>
|
||||
* <li>
|
||||
* The ClassLoader object found in <var>env</var> for
|
||||
* <code>jmx.remote.default.class.loader</code>, if any.
|
||||
* </li>
|
||||
* <li>
|
||||
* The ClassLoader pointed to by the ObjectName found in
|
||||
* <var>env</var> for <code>jmx.remote.default.class.loader.name</code>,
|
||||
* and registered in <var>mbs</var> if any.
|
||||
* </li>
|
||||
* <li>
|
||||
* The current thread's context classloader otherwise.
|
||||
* </li>
|
||||
* </ul>
|
||||
*
|
||||
* @param env Environment attributes.
|
||||
* @param mbs The MBeanServer for which the connector server provides
|
||||
* remote access.
|
||||
*
|
||||
* @return the connector server's default class loader.
|
||||
*
|
||||
* @exception IllegalArgumentException if one of the following is true:
|
||||
* <ul>
|
||||
* <li>both
|
||||
* <code>jmx.remote.default.class.loader</code> and
|
||||
* <code>jmx.remote.default.class.loader.name</code> are specified,
|
||||
* </li>
|
||||
* <li>or
|
||||
* <code>jmx.remote.default.class.loader</code> is not
|
||||
* an instance of {@link ClassLoader},
|
||||
* </li>
|
||||
* <li>or
|
||||
* <code>jmx.remote.default.class.loader.name</code> is not
|
||||
* an instance of {@link ObjectName},
|
||||
* </li>
|
||||
* <li>or
|
||||
* <code>jmx.remote.default.class.loader.name</code> is specified
|
||||
* but <var>mbs</var> is null.
|
||||
* </li>
|
||||
* @exception InstanceNotFoundException if
|
||||
* <code>jmx.remote.default.class.loader.name</code> is specified
|
||||
* and the ClassLoader MBean is not found in <var>mbs</var>.
|
||||
*/
|
||||
public static ClassLoader resolveServerClassLoader(Map<String, ?> env,
|
||||
MBeanServer mbs)
|
||||
throws InstanceNotFoundException {
|
||||
|
||||
if (env == null)
|
||||
return Thread.currentThread().getContextClassLoader();
|
||||
|
||||
Object loader = env.get(DEFAULT_CLASS_LOADER);
|
||||
Object name = env.get(DEFAULT_CLASS_LOADER_NAME);
|
||||
|
||||
if (loader != null && name != null) {
|
||||
final String msg = "Only one of " +
|
||||
DEFAULT_CLASS_LOADER + " or " +
|
||||
DEFAULT_CLASS_LOADER_NAME +
|
||||
" should be specified.";
|
||||
throw new IllegalArgumentException(msg);
|
||||
}
|
||||
|
||||
if (loader == null && name == null)
|
||||
return Thread.currentThread().getContextClassLoader();
|
||||
|
||||
if (loader != null) {
|
||||
if (loader instanceof ClassLoader) {
|
||||
return (ClassLoader) loader;
|
||||
} else {
|
||||
final String msg =
|
||||
"ClassLoader object is not an instance of " +
|
||||
ClassLoader.class.getName() + " : " +
|
||||
loader.getClass().getName();
|
||||
throw new IllegalArgumentException(msg);
|
||||
}
|
||||
}
|
||||
|
||||
ObjectName on;
|
||||
if (name instanceof ObjectName) {
|
||||
on = (ObjectName) name;
|
||||
} else {
|
||||
final String msg =
|
||||
"ClassLoader name is not an instance of " +
|
||||
ObjectName.class.getName() + " : " +
|
||||
name.getClass().getName();
|
||||
throw new IllegalArgumentException(msg);
|
||||
}
|
||||
|
||||
if (mbs == null)
|
||||
throw new IllegalArgumentException("Null MBeanServer object");
|
||||
|
||||
return mbs.getClassLoader(on);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Connector Client default class loader.
|
||||
* <p>
|
||||
* Returns:
|
||||
* <p>
|
||||
* <ul>
|
||||
* <li>
|
||||
* The ClassLoader object found in <var>env</var> for
|
||||
* <code>jmx.remote.default.class.loader</code>, if any.
|
||||
* </li>
|
||||
* <li>The <tt>Thread.currentThread().getContextClassLoader()</tt>
|
||||
* otherwise.
|
||||
* </li>
|
||||
* </ul>
|
||||
* <p>
|
||||
* Usually a Connector Client will call
|
||||
* <pre>
|
||||
* ClassLoader dcl = EnvHelp.resolveClientClassLoader(env);
|
||||
* </pre>
|
||||
* in its <code>connect(Map env)</code> method.
|
||||
*
|
||||
* @return The connector client default class loader.
|
||||
*
|
||||
* @exception IllegalArgumentException if
|
||||
* <code>jmx.remote.default.class.loader</code> is specified
|
||||
* and is not an instance of {@link ClassLoader}.
|
||||
*/
|
||||
public static ClassLoader resolveClientClassLoader(Map<String, ?> env) {
|
||||
|
||||
if (env == null)
|
||||
return Thread.currentThread().getContextClassLoader();
|
||||
|
||||
Object loader = env.get(DEFAULT_CLASS_LOADER);
|
||||
|
||||
if (loader == null)
|
||||
return Thread.currentThread().getContextClassLoader();
|
||||
|
||||
if (loader instanceof ClassLoader) {
|
||||
return (ClassLoader) loader;
|
||||
} else {
|
||||
final String msg =
|
||||
"ClassLoader object is not an instance of " +
|
||||
ClassLoader.class.getName() + " : " +
|
||||
loader.getClass().getName();
|
||||
throw new IllegalArgumentException(msg);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the cause field of a {@code Throwable} object.
|
||||
*
|
||||
* @param throwable The {@code Throwable} on which the cause is set.
|
||||
* @param cause The cause to set on the supplied {@code Throwable}.
|
||||
* @return the {@code Throwable} with the cause field initialized.
|
||||
*/
|
||||
public static <T extends Throwable> T initCause(T throwable,
|
||||
Throwable cause) {
|
||||
throwable.initCause(cause);
|
||||
return throwable;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the cause field of a {@code Throwable} object.
|
||||
* The cause field can be got only if <var>t</var> has an
|
||||
* {@link Throwable#getCause()} method (JDK Version >= 1.4)
|
||||
* @param t {@code Throwable} on which the cause must be set.
|
||||
* @return the cause if getCause() succeeded and the got value is not
|
||||
* null, otherwise return the <var>t</var>.
|
||||
*/
|
||||
public static Throwable getCause(Throwable t) {
|
||||
Throwable ret = t;
|
||||
|
||||
try {
|
||||
java.lang.reflect.Method getCause =
|
||||
t.getClass().getMethod("getCause", (Class<?>[]) null);
|
||||
ret = (Throwable)getCause.invoke(t, (Object[]) null);
|
||||
|
||||
} catch (Exception e) {
|
||||
// OK.
|
||||
// it must be older than 1.4.
|
||||
}
|
||||
return (ret != null) ? ret: t;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* <p>Name of the attribute that specifies the size of a notification
|
||||
* buffer for a connector server. The default value is 1000.
|
||||
*/
|
||||
public static final String BUFFER_SIZE_PROPERTY =
|
||||
"jmx.remote.x.notification.buffer.size";
|
||||
|
||||
|
||||
/**
|
||||
* Returns the size of a notification buffer for a connector server.
|
||||
* The default value is 1000.
|
||||
*/
|
||||
public static int getNotifBufferSize(Map<String, ?> env) {
|
||||
int defaultQueueSize = 1000; // default value
|
||||
|
||||
// keep it for the compability for the fix:
|
||||
// 6174229: Environment parameter should be notification.buffer.size
|
||||
// instead of buffer.size
|
||||
final String oldP = "jmx.remote.x.buffer.size";
|
||||
|
||||
// the default value re-specified in the system
|
||||
try {
|
||||
GetPropertyAction act = new GetPropertyAction(BUFFER_SIZE_PROPERTY);
|
||||
String s = AccessController.doPrivileged(act);
|
||||
if (s != null) {
|
||||
defaultQueueSize = Integer.parseInt(s);
|
||||
} else { // try the old one
|
||||
act = new GetPropertyAction(oldP);
|
||||
s = AccessController.doPrivileged(act);
|
||||
if (s != null) {
|
||||
defaultQueueSize = Integer.parseInt(s);
|
||||
}
|
||||
}
|
||||
} catch (RuntimeException e) {
|
||||
logger.warning("getNotifBufferSize",
|
||||
"Can't use System property "+
|
||||
BUFFER_SIZE_PROPERTY+ ": " + e);
|
||||
logger.debug("getNotifBufferSize", e);
|
||||
}
|
||||
|
||||
int queueSize = defaultQueueSize;
|
||||
|
||||
try {
|
||||
if (env.containsKey(BUFFER_SIZE_PROPERTY)) {
|
||||
queueSize = (int)EnvHelp.getIntegerAttribute(env,BUFFER_SIZE_PROPERTY,
|
||||
defaultQueueSize,0,
|
||||
Integer.MAX_VALUE);
|
||||
} else { // try the old one
|
||||
queueSize = (int)EnvHelp.getIntegerAttribute(env,oldP,
|
||||
defaultQueueSize,0,
|
||||
Integer.MAX_VALUE);
|
||||
}
|
||||
} catch (RuntimeException e) {
|
||||
logger.warning("getNotifBufferSize",
|
||||
"Can't determine queuesize (using default): "+
|
||||
e);
|
||||
logger.debug("getNotifBufferSize", e);
|
||||
}
|
||||
|
||||
return queueSize;
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Name of the attribute that specifies the maximum number of
|
||||
* notifications that a client will fetch from its server.. The
|
||||
* value associated with this attribute should be an
|
||||
* <code>Integer</code> object. The default value is 1000.</p>
|
||||
*/
|
||||
public static final String MAX_FETCH_NOTIFS =
|
||||
"jmx.remote.x.notification.fetch.max";
|
||||
|
||||
/**
|
||||
* Returns the maximum notification number which a client will
|
||||
* fetch every time.
|
||||
*/
|
||||
public static int getMaxFetchNotifNumber(Map<String, ?> env) {
|
||||
return (int) getIntegerAttribute(env, MAX_FETCH_NOTIFS, 1000, 1,
|
||||
Integer.MAX_VALUE);
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Name of the attribute that specifies the timeout for a
|
||||
* client to fetch notifications from its server. The value
|
||||
* associated with this attribute should be a <code>Long</code>
|
||||
* object. The default value is 60000 milliseconds.</p>
|
||||
*/
|
||||
public static final String FETCH_TIMEOUT =
|
||||
"jmx.remote.x.notification.fetch.timeout";
|
||||
|
||||
/**
|
||||
* Returns the timeout for a client to fetch notifications.
|
||||
*/
|
||||
public static long getFetchTimeout(Map<String, ?> env) {
|
||||
return getIntegerAttribute(env, FETCH_TIMEOUT, 60000L, 0,
|
||||
Long.MAX_VALUE);
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Name of the attribute that specifies an object that will check
|
||||
* accesses to add/removeNotificationListener and also attempts to
|
||||
* receive notifications. The value associated with this attribute
|
||||
* should be a <code>NotificationAccessController</code> object.
|
||||
* The default value is null.</p>
|
||||
* This field is not public because of its com.sun dependency.
|
||||
*/
|
||||
public static final String NOTIF_ACCESS_CONTROLLER =
|
||||
"com.sun.jmx.remote.notification.access.controller";
|
||||
|
||||
public static NotificationAccessController getNotificationAccessController(
|
||||
Map<String, ?> env) {
|
||||
return (env == null) ? null :
|
||||
(NotificationAccessController) env.get(NOTIF_ACCESS_CONTROLLER);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an integer-valued attribute with name <code>name</code>
|
||||
* from <code>env</code>. If <code>env</code> is null, or does
|
||||
* not contain an entry for <code>name</code>, return
|
||||
* <code>defaultValue</code>. The value may be a Number, or it
|
||||
* may be a String that is parsable as a long. It must be at
|
||||
* least <code>minValue</code> and at most<code>maxValue</code>.
|
||||
*
|
||||
* @throws IllegalArgumentException if <code>env</code> contains
|
||||
* an entry for <code>name</code> but it does not meet the
|
||||
* constraints above.
|
||||
*/
|
||||
public static long getIntegerAttribute(Map<String, ?> env, String name,
|
||||
long defaultValue, long minValue,
|
||||
long maxValue) {
|
||||
final Object o;
|
||||
|
||||
if (env == null || (o = env.get(name)) == null)
|
||||
return defaultValue;
|
||||
|
||||
final long result;
|
||||
|
||||
if (o instanceof Number)
|
||||
result = ((Number) o).longValue();
|
||||
else if (o instanceof String) {
|
||||
result = Long.parseLong((String) o);
|
||||
/* May throw a NumberFormatException, which is an
|
||||
IllegalArgumentException. */
|
||||
} else {
|
||||
final String msg =
|
||||
"Attribute " + name + " value must be Integer or String: " + o;
|
||||
throw new IllegalArgumentException(msg);
|
||||
}
|
||||
|
||||
if (result < minValue) {
|
||||
final String msg =
|
||||
"Attribute " + name + " value must be at least " + minValue +
|
||||
": " + result;
|
||||
throw new IllegalArgumentException(msg);
|
||||
}
|
||||
|
||||
if (result > maxValue) {
|
||||
final String msg =
|
||||
"Attribute " + name + " value must be at most " + maxValue +
|
||||
": " + result;
|
||||
throw new IllegalArgumentException(msg);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public static final String DEFAULT_ORB="java.naming.corba.orb";
|
||||
|
||||
/* Check that all attributes have a key that is a String.
|
||||
Could make further checks, e.g. appropriate types for attributes. */
|
||||
public static void checkAttributes(Map<?, ?> attributes) {
|
||||
for (Object key : attributes.keySet()) {
|
||||
if (!(key instanceof String)) {
|
||||
final String msg =
|
||||
"Attributes contain key that is not a string: " + key;
|
||||
throw new IllegalArgumentException(msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Return a writable map containing only those attributes that are
|
||||
serializable, and that are not hidden by
|
||||
jmx.remote.x.hidden.attributes or the default list of hidden
|
||||
attributes. */
|
||||
public static <V> Map<String, V> filterAttributes(Map<String, V> attributes) {
|
||||
if (logger.traceOn()) {
|
||||
logger.trace("filterAttributes", "starts");
|
||||
}
|
||||
|
||||
SortedMap<String, V> map = new TreeMap<String, V>(attributes);
|
||||
purgeUnserializable(map.values());
|
||||
hideAttributes(map);
|
||||
return map;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove from the given Collection any element that is not a
|
||||
* serializable object.
|
||||
*/
|
||||
private static void purgeUnserializable(Collection<?> objects) {
|
||||
logger.trace("purgeUnserializable", "starts");
|
||||
ObjectOutputStream oos = null;
|
||||
int i = 0;
|
||||
for (Iterator<?> it = objects.iterator(); it.hasNext(); i++) {
|
||||
Object v = it.next();
|
||||
|
||||
if (v == null || v instanceof String) {
|
||||
if (logger.traceOn()) {
|
||||
logger.trace("purgeUnserializable",
|
||||
"Value trivially serializable: " + v);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
try {
|
||||
if (oos == null)
|
||||
oos = new ObjectOutputStream(new SinkOutputStream());
|
||||
oos.writeObject(v);
|
||||
if (logger.traceOn()) {
|
||||
logger.trace("purgeUnserializable",
|
||||
"Value serializable: " + v);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
if (logger.traceOn()) {
|
||||
logger.trace("purgeUnserializable",
|
||||
"Value not serializable: " + v + ": " +
|
||||
e);
|
||||
}
|
||||
it.remove();
|
||||
oos = null; // ObjectOutputStream invalid after exception
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The value of this attribute, if present, is a string specifying
|
||||
* what other attributes should not appear in
|
||||
* JMXConnectorServer.getAttributes(). It is a space-separated
|
||||
* list of attribute patterns, where each pattern is either an
|
||||
* attribute name, or an attribute prefix followed by a "*"
|
||||
* character. The "*" has no special significance anywhere except
|
||||
* at the end of a pattern. By default, this list is added to the
|
||||
* list defined by {@link #DEFAULT_HIDDEN_ATTRIBUTES} (which
|
||||
* uses the same format). If the value of this attribute begins
|
||||
* with an "=", then the remainder of the string defines the
|
||||
* complete list of attribute patterns.
|
||||
*/
|
||||
public static final String HIDDEN_ATTRIBUTES =
|
||||
"jmx.remote.x.hidden.attributes";
|
||||
|
||||
/**
|
||||
* Default list of attributes not to show.
|
||||
* @see #HIDDEN_ATTRIBUTES
|
||||
*/
|
||||
/* This list is copied directly from the spec, plus
|
||||
java.naming.security.*. Most of the attributes here would have
|
||||
been eliminated from the map anyway because they are typically
|
||||
not serializable. But just in case they are, we list them here
|
||||
to conform to the spec. */
|
||||
public static final String DEFAULT_HIDDEN_ATTRIBUTES =
|
||||
"java.naming.security.* " +
|
||||
"jmx.remote.authenticator " +
|
||||
"jmx.remote.context " +
|
||||
"jmx.remote.default.class.loader " +
|
||||
"jmx.remote.message.connection.server " +
|
||||
"jmx.remote.object.wrapping " +
|
||||
"jmx.remote.rmi.client.socket.factory " +
|
||||
"jmx.remote.rmi.server.socket.factory " +
|
||||
"jmx.remote.sasl.callback.handler " +
|
||||
"jmx.remote.tls.socket.factory " +
|
||||
"jmx.remote.x.access.file " +
|
||||
"jmx.remote.x.password.file ";
|
||||
|
||||
private static final SortedSet<String> defaultHiddenStrings =
|
||||
new TreeSet<String>();
|
||||
private static final SortedSet<String> defaultHiddenPrefixes =
|
||||
new TreeSet<String>();
|
||||
|
||||
private static void hideAttributes(SortedMap<String, ?> map) {
|
||||
if (map.isEmpty())
|
||||
return;
|
||||
|
||||
final SortedSet<String> hiddenStrings;
|
||||
final SortedSet<String> hiddenPrefixes;
|
||||
|
||||
String hide = (String) map.get(HIDDEN_ATTRIBUTES);
|
||||
if (hide != null) {
|
||||
if (hide.startsWith("="))
|
||||
hide = hide.substring(1);
|
||||
else
|
||||
hide += " " + DEFAULT_HIDDEN_ATTRIBUTES;
|
||||
hiddenStrings = new TreeSet<String>();
|
||||
hiddenPrefixes = new TreeSet<String>();
|
||||
parseHiddenAttributes(hide, hiddenStrings, hiddenPrefixes);
|
||||
} else {
|
||||
hide = DEFAULT_HIDDEN_ATTRIBUTES;
|
||||
synchronized (defaultHiddenStrings) {
|
||||
if (defaultHiddenStrings.isEmpty()) {
|
||||
parseHiddenAttributes(hide,
|
||||
defaultHiddenStrings,
|
||||
defaultHiddenPrefixes);
|
||||
}
|
||||
hiddenStrings = defaultHiddenStrings;
|
||||
hiddenPrefixes = defaultHiddenPrefixes;
|
||||
}
|
||||
}
|
||||
|
||||
/* Construct a string that is greater than any key in the map.
|
||||
Setting a string-to-match or a prefix-to-match to this string
|
||||
guarantees that we will never call next() on the corresponding
|
||||
iterator. */
|
||||
String sentinelKey = map.lastKey() + "X";
|
||||
Iterator<String> keyIterator = map.keySet().iterator();
|
||||
Iterator<String> stringIterator = hiddenStrings.iterator();
|
||||
Iterator<String> prefixIterator = hiddenPrefixes.iterator();
|
||||
|
||||
String nextString;
|
||||
if (stringIterator.hasNext())
|
||||
nextString = stringIterator.next();
|
||||
else
|
||||
nextString = sentinelKey;
|
||||
String nextPrefix;
|
||||
if (prefixIterator.hasNext())
|
||||
nextPrefix = prefixIterator.next();
|
||||
else
|
||||
nextPrefix = sentinelKey;
|
||||
|
||||
/* Read each key in sorted order and, if it matches a string
|
||||
or prefix, remove it. */
|
||||
keys:
|
||||
while (keyIterator.hasNext()) {
|
||||
String key = keyIterator.next();
|
||||
|
||||
/* Continue through string-match values until we find one
|
||||
that is either greater than the current key, or equal
|
||||
to it. In the latter case, remove the key. */
|
||||
int cmp = +1;
|
||||
while ((cmp = nextString.compareTo(key)) < 0) {
|
||||
if (stringIterator.hasNext())
|
||||
nextString = stringIterator.next();
|
||||
else
|
||||
nextString = sentinelKey;
|
||||
}
|
||||
if (cmp == 0) {
|
||||
keyIterator.remove();
|
||||
continue keys;
|
||||
}
|
||||
|
||||
/* Continue through the prefix values until we find one
|
||||
that is either greater than the current key, or a
|
||||
prefix of it. In the latter case, remove the key. */
|
||||
while (nextPrefix.compareTo(key) <= 0) {
|
||||
if (key.startsWith(nextPrefix)) {
|
||||
keyIterator.remove();
|
||||
continue keys;
|
||||
}
|
||||
if (prefixIterator.hasNext())
|
||||
nextPrefix = prefixIterator.next();
|
||||
else
|
||||
nextPrefix = sentinelKey;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void parseHiddenAttributes(String hide,
|
||||
SortedSet<String> hiddenStrings,
|
||||
SortedSet<String> hiddenPrefixes) {
|
||||
final StringTokenizer tok = new StringTokenizer(hide);
|
||||
while (tok.hasMoreTokens()) {
|
||||
String s = tok.nextToken();
|
||||
if (s.endsWith("*"))
|
||||
hiddenPrefixes.add(s.substring(0, s.length() - 1));
|
||||
else
|
||||
hiddenStrings.add(s);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Name of the attribute that specifies the timeout to keep a
|
||||
* server side connection after answering last client request.
|
||||
* The default value is 120000 milliseconds.</p>
|
||||
*/
|
||||
public static final String SERVER_CONNECTION_TIMEOUT =
|
||||
"jmx.remote.x.server.connection.timeout";
|
||||
|
||||
/**
|
||||
* Returns the server side connection timeout.
|
||||
*/
|
||||
public static long getServerConnectionTimeout(Map<String, ?> env) {
|
||||
return getIntegerAttribute(env, SERVER_CONNECTION_TIMEOUT, 120000L,
|
||||
0, Long.MAX_VALUE);
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Name of the attribute that specifies the period in
|
||||
* millisecond for a client to check its connection. The default
|
||||
* value is 60000 milliseconds.</p>
|
||||
*/
|
||||
public static final String CLIENT_CONNECTION_CHECK_PERIOD =
|
||||
"jmx.remote.x.client.connection.check.period";
|
||||
|
||||
/**
|
||||
* Returns the client connection check period.
|
||||
*/
|
||||
public static long getConnectionCheckPeriod(Map<String, ?> env) {
|
||||
return getIntegerAttribute(env, CLIENT_CONNECTION_CHECK_PERIOD, 60000L,
|
||||
0, Long.MAX_VALUE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Computes a boolean value from a string value retrieved from a
|
||||
* property in the given map.
|
||||
*
|
||||
* @param stringBoolean the string value that must be converted
|
||||
* into a boolean value.
|
||||
*
|
||||
* @return
|
||||
* <ul>
|
||||
* <li>{@code false} if {@code stringBoolean} is {@code null}</li>
|
||||
* <li>{@code false} if
|
||||
* {@code stringBoolean.equalsIgnoreCase("false")}
|
||||
* is {@code true}</li>
|
||||
* <li>{@code true} if
|
||||
* {@code stringBoolean.equalsIgnoreCase("true")}
|
||||
* is {@code true}</li>
|
||||
* </ul>
|
||||
*
|
||||
* @throws IllegalArgumentException if
|
||||
* {@code ((String)env.get(prop)).equalsIgnoreCase("false")} and
|
||||
* {@code ((String)env.get(prop)).equalsIgnoreCase("true")} are
|
||||
* {@code false}.
|
||||
*/
|
||||
public static boolean computeBooleanFromString(String stringBoolean) {
|
||||
// returns a default value of 'false' if no property is found...
|
||||
return computeBooleanFromString(stringBoolean,false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Computes a boolean value from a string value retrieved from a
|
||||
* property in the given map.
|
||||
*
|
||||
* @param stringBoolean the string value that must be converted
|
||||
* into a boolean value.
|
||||
* @param defaultValue a default value to return in case no property
|
||||
* was defined.
|
||||
*
|
||||
* @return
|
||||
* <ul>
|
||||
* <li>{@code defaultValue} if {@code stringBoolean}
|
||||
* is {@code null}</li>
|
||||
* <li>{@code false} if
|
||||
* {@code stringBoolean.equalsIgnoreCase("false")}
|
||||
* is {@code true}</li>
|
||||
* <li>{@code true} if
|
||||
* {@code stringBoolean.equalsIgnoreCase("true")}
|
||||
* is {@code true}</li>
|
||||
* </ul>
|
||||
*
|
||||
* @throws IllegalArgumentException if
|
||||
* {@code ((String)env.get(prop)).equalsIgnoreCase("false")} and
|
||||
* {@code ((String)env.get(prop)).equalsIgnoreCase("true")} are
|
||||
* {@code false}.
|
||||
*/
|
||||
public static boolean computeBooleanFromString( String stringBoolean, boolean defaultValue) {
|
||||
if (stringBoolean == null)
|
||||
return defaultValue;
|
||||
else if (stringBoolean.equalsIgnoreCase("true"))
|
||||
return true;
|
||||
else if (stringBoolean.equalsIgnoreCase("false"))
|
||||
return false;
|
||||
else
|
||||
throw new IllegalArgumentException(
|
||||
"Property value must be \"true\" or \"false\" instead of \"" +
|
||||
stringBoolean + "\"");
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a map into a valid hash table, i.e.
|
||||
* it removes all the 'null' values from the map.
|
||||
*/
|
||||
public static <K, V> Hashtable<K, V> mapToHashtable(Map<K, V> map) {
|
||||
HashMap<K, V> m = new HashMap<K, V>(map);
|
||||
if (m.containsKey(null)) m.remove(null);
|
||||
for (Iterator<?> i = m.values().iterator(); i.hasNext(); )
|
||||
if (i.next() == null) i.remove();
|
||||
return new Hashtable<K, V>(m);
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Name of the attribute that specifies whether a connector server
|
||||
* should not prevent the VM from exiting
|
||||
*/
|
||||
public static final String JMX_SERVER_DAEMON = "jmx.remote.x.daemon";
|
||||
|
||||
/**
|
||||
* Returns true if {@value SERVER_DAEMON} is specified in the {@code env}
|
||||
* as a key and its value is a String and it is equal to true ignoring case.
|
||||
*
|
||||
* @param env
|
||||
* @return
|
||||
*/
|
||||
public static boolean isServerDaemon(Map<String, ?> env) {
|
||||
return (env != null) &&
|
||||
("true".equalsIgnoreCase((String)env.get(JMX_SERVER_DAEMON)));
|
||||
}
|
||||
|
||||
private static final class SinkOutputStream extends OutputStream {
|
||||
public void write(byte[] b, int off, int len) {}
|
||||
public void write(int b) {}
|
||||
}
|
||||
|
||||
private static final ClassLogger logger =
|
||||
new ClassLogger("javax.management.remote.misc", "EnvHelp");
|
||||
}
|
||||
Reference in New Issue
Block a user