/* * Copyright (c) 2003, 2008, 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 { /** * <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.Lines 1–500 of 808. Load more
/* * Copyright (c) 2003, 2008, 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 { /** * <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.