feat(jdk8): move files to new folder to avoid resources compiled.
This commit is contained in:
232
jdkSrc/jdk8/com/sun/jmx/defaults/JmxProperties.java
Normal file
232
jdkSrc/jdk8/com/sun/jmx/defaults/JmxProperties.java
Normal file
@@ -0,0 +1,232 @@
|
||||
/*
|
||||
* Copyright (c) 1999, 2007, 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.defaults;
|
||||
|
||||
import java.util.logging.Logger;
|
||||
|
||||
/**
|
||||
* This contains the property list defined for this
|
||||
* JMX implementation.
|
||||
*
|
||||
*
|
||||
* @since 1.5
|
||||
*/
|
||||
public class JmxProperties {
|
||||
|
||||
// private constructor defined to "hide" the default public constructor
|
||||
private JmxProperties() {
|
||||
}
|
||||
|
||||
// PUBLIC STATIC CONSTANTS
|
||||
//------------------------
|
||||
|
||||
/**
|
||||
* References the property that specifies the directory where
|
||||
* the native libraries will be stored before the MLet Service
|
||||
* loads them into memory.
|
||||
* <p>
|
||||
* Property Name: <B>jmx.mlet.library.dir</B>
|
||||
*/
|
||||
public static final String JMX_INITIAL_BUILDER =
|
||||
"javax.management.builder.initial";
|
||||
|
||||
/**
|
||||
* References the property that specifies the directory where
|
||||
* the native libraries will be stored before the MLet Service
|
||||
* loads them into memory.
|
||||
* <p>
|
||||
* Property Name: <B>jmx.mlet.library.dir</B>
|
||||
*/
|
||||
public static final String MLET_LIB_DIR = "jmx.mlet.library.dir";
|
||||
|
||||
/**
|
||||
* References the property that specifies the full name of the JMX
|
||||
* specification implemented by this product.
|
||||
* <p>
|
||||
* Property Name: <B>jmx.specification.name</B>
|
||||
*/
|
||||
public static final String JMX_SPEC_NAME = "jmx.specification.name";
|
||||
|
||||
/**
|
||||
* References the property that specifies the version of the JMX
|
||||
* specification implemented by this product.
|
||||
* <p>
|
||||
* Property Name: <B>jmx.specification.version</B>
|
||||
*/
|
||||
public static final String JMX_SPEC_VERSION = "jmx.specification.version";
|
||||
|
||||
/**
|
||||
* References the property that specifies the vendor of the JMX
|
||||
* specification implemented by this product.
|
||||
* <p>
|
||||
* Property Name: <B>jmx.specification.vendor</B>
|
||||
*/
|
||||
public static final String JMX_SPEC_VENDOR = "jmx.specification.vendor";
|
||||
|
||||
/**
|
||||
* References the property that specifies the full name of this product
|
||||
* implementing the JMX specification.
|
||||
* <p>
|
||||
* Property Name: <B>jmx.implementation.name</B>
|
||||
*/
|
||||
public static final String JMX_IMPL_NAME = "jmx.implementation.name";
|
||||
|
||||
/**
|
||||
* References the property that specifies the name of the vendor of this
|
||||
* product implementing the JMX specification.
|
||||
* <p>
|
||||
* Property Name: <B>jmx.implementation.vendor</B>
|
||||
*/
|
||||
public static final String JMX_IMPL_VENDOR = "jmx.implementation.vendor";
|
||||
|
||||
/**
|
||||
* References the property that specifies the version of this product
|
||||
* implementing the JMX specification.
|
||||
* <p>
|
||||
* Property Name: <B>jmx.implementation.version</B>
|
||||
*/
|
||||
public static final String JMX_IMPL_VERSION = "jmx.implementation.version";
|
||||
|
||||
/**
|
||||
* Logger name for MBean Server information.
|
||||
*/
|
||||
public static final String MBEANSERVER_LOGGER_NAME =
|
||||
"javax.management.mbeanserver";
|
||||
|
||||
/**
|
||||
* Logger for MBean Server information.
|
||||
*/
|
||||
public static final Logger MBEANSERVER_LOGGER =
|
||||
Logger.getLogger(MBEANSERVER_LOGGER_NAME);
|
||||
|
||||
/**
|
||||
* Logger name for MLet service information.
|
||||
*/
|
||||
public static final String MLET_LOGGER_NAME =
|
||||
"javax.management.mlet";
|
||||
|
||||
/**
|
||||
* Logger for MLet service information.
|
||||
*/
|
||||
public static final Logger MLET_LOGGER =
|
||||
Logger.getLogger(MLET_LOGGER_NAME);
|
||||
|
||||
/**
|
||||
* Logger name for Monitor information.
|
||||
*/
|
||||
public static final String MONITOR_LOGGER_NAME =
|
||||
"javax.management.monitor";
|
||||
|
||||
/**
|
||||
* Logger for Monitor information.
|
||||
*/
|
||||
public static final Logger MONITOR_LOGGER =
|
||||
Logger.getLogger(MONITOR_LOGGER_NAME);
|
||||
|
||||
/**
|
||||
* Logger name for Timer information.
|
||||
*/
|
||||
public static final String TIMER_LOGGER_NAME =
|
||||
"javax.management.timer";
|
||||
|
||||
/**
|
||||
* Logger for Timer information.
|
||||
*/
|
||||
public static final Logger TIMER_LOGGER =
|
||||
Logger.getLogger(TIMER_LOGGER_NAME);
|
||||
|
||||
/**
|
||||
* Logger name for Event Management information.
|
||||
*/
|
||||
public static final String NOTIFICATION_LOGGER_NAME =
|
||||
"javax.management.notification";
|
||||
|
||||
/**
|
||||
* Logger for Event Management information.
|
||||
*/
|
||||
public static final Logger NOTIFICATION_LOGGER =
|
||||
Logger.getLogger(NOTIFICATION_LOGGER_NAME);
|
||||
|
||||
/**
|
||||
* Logger name for Relation Service.
|
||||
*/
|
||||
public static final String RELATION_LOGGER_NAME =
|
||||
"javax.management.relation";
|
||||
|
||||
/**
|
||||
* Logger for Relation Service.
|
||||
*/
|
||||
public static final Logger RELATION_LOGGER =
|
||||
Logger.getLogger(RELATION_LOGGER_NAME);
|
||||
|
||||
/**
|
||||
* Logger name for Model MBean.
|
||||
*/
|
||||
public static final String MODELMBEAN_LOGGER_NAME =
|
||||
"javax.management.modelmbean";
|
||||
|
||||
/**
|
||||
* Logger for Model MBean.
|
||||
*/
|
||||
public static final Logger MODELMBEAN_LOGGER =
|
||||
Logger.getLogger(MODELMBEAN_LOGGER_NAME);
|
||||
|
||||
/**
|
||||
* Logger name for all other JMX classes.
|
||||
*/
|
||||
public static final String MISC_LOGGER_NAME =
|
||||
"javax.management.misc";
|
||||
|
||||
/**
|
||||
* Logger for all other JMX classes.
|
||||
*/
|
||||
public static final Logger MISC_LOGGER =
|
||||
Logger.getLogger(MISC_LOGGER_NAME);
|
||||
|
||||
/**
|
||||
* Logger name for SNMP.
|
||||
*/
|
||||
public static final String SNMP_LOGGER_NAME =
|
||||
"javax.management.snmp";
|
||||
|
||||
/**
|
||||
* Logger for SNMP.
|
||||
*/
|
||||
public static final Logger SNMP_LOGGER =
|
||||
Logger.getLogger(SNMP_LOGGER_NAME);
|
||||
|
||||
/**
|
||||
* Logger name for SNMP Adaptor.
|
||||
*/
|
||||
public static final String SNMP_ADAPTOR_LOGGER_NAME =
|
||||
"javax.management.snmp.daemon";
|
||||
|
||||
/**
|
||||
* Logger for SNMP Adaptor.
|
||||
*/
|
||||
public static final Logger SNMP_ADAPTOR_LOGGER =
|
||||
Logger.getLogger(SNMP_ADAPTOR_LOGGER_NAME);
|
||||
}
|
||||
97
jdkSrc/jdk8/com/sun/jmx/defaults/ServiceName.java
Normal file
97
jdkSrc/jdk8/com/sun/jmx/defaults/ServiceName.java
Normal file
@@ -0,0 +1,97 @@
|
||||
/*
|
||||
* Copyright (c) 1999, 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.defaults;
|
||||
|
||||
/**
|
||||
* Used for storing default values used by JMX services.
|
||||
*
|
||||
* @since 1.5
|
||||
*/
|
||||
public class ServiceName {
|
||||
|
||||
// private constructor defined to "hide" the default public constructor
|
||||
private ServiceName() {
|
||||
}
|
||||
|
||||
/**
|
||||
* The object name of the MBeanServer delegate object
|
||||
* <BR>
|
||||
* The value is <CODE>JMImplementation:type=MBeanServerDelegate</CODE>.
|
||||
*/
|
||||
public static final String DELEGATE =
|
||||
"JMImplementation:type=MBeanServerDelegate" ;
|
||||
|
||||
/**
|
||||
* The default key properties for registering the class loader of the
|
||||
* MLet service.
|
||||
* <BR>
|
||||
* The value is <CODE>type=MLet</CODE>.
|
||||
*/
|
||||
public static final String MLET = "type=MLet";
|
||||
|
||||
/**
|
||||
* The default domain.
|
||||
* <BR>
|
||||
* The value is <CODE>DefaultDomain</CODE>.
|
||||
*/
|
||||
public static final String DOMAIN = "DefaultDomain";
|
||||
|
||||
/**
|
||||
* The name of the JMX specification implemented by this product.
|
||||
* <BR>
|
||||
* The value is <CODE>Java Management Extensions</CODE>.
|
||||
*/
|
||||
public static final String JMX_SPEC_NAME = "Java Management Extensions";
|
||||
|
||||
/**
|
||||
* The version of the JMX specification implemented by this product.
|
||||
* <BR>
|
||||
* The value is <CODE>1.4</CODE>.
|
||||
*/
|
||||
public static final String JMX_SPEC_VERSION = "1.4";
|
||||
|
||||
/**
|
||||
* The vendor of the JMX specification implemented by this product.
|
||||
* <BR>
|
||||
* The value is <CODE>Oracle Corporation</CODE>.
|
||||
*/
|
||||
public static final String JMX_SPEC_VENDOR = "Oracle Corporation";
|
||||
|
||||
/**
|
||||
* The name of this product implementing the JMX specification.
|
||||
* <BR>
|
||||
* The value is <CODE>JMX</CODE>.
|
||||
*/
|
||||
public static final String JMX_IMPL_NAME = "JMX";
|
||||
|
||||
/**
|
||||
* The name of the vendor of this product implementing the
|
||||
* JMX specification.
|
||||
* <BR>
|
||||
* The value is <CODE>Oracle Corporation</CODE>.
|
||||
*/
|
||||
public static final String JMX_IMPL_VENDOR = "Oracle Corporation";
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
130
jdkSrc/jdk8/com/sun/jmx/interceptor/MBeanServerInterceptor.java
Normal file
130
jdkSrc/jdk8/com/sun/jmx/interceptor/MBeanServerInterceptor.java
Normal file
@@ -0,0 +1,130 @@
|
||||
/*
|
||||
* Copyright (c) 2002, 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.interceptor;
|
||||
|
||||
|
||||
import java.io.ObjectInputStream;
|
||||
import javax.management.InstanceNotFoundException;
|
||||
import javax.management.MBeanException;
|
||||
import javax.management.MBeanServer;
|
||||
import javax.management.ObjectName;
|
||||
import javax.management.OperationsException;
|
||||
import javax.management.ReflectionException;
|
||||
import javax.management.loading.ClassLoaderRepository;
|
||||
|
||||
/**
|
||||
* <p>This interface specifies the behavior to be implemented by an
|
||||
* MBean Server Interceptor. An MBean Server Interceptor has
|
||||
* essentially the same interface as an MBean Server. An MBean Server
|
||||
* forwards received requests to its default interceptor, which may
|
||||
* handle them itself or forward them to other interceptors. The
|
||||
* default interceptor may be changed via the {@link
|
||||
* com.sun.jmx.mbeanserver.SunJmxMBeanServer#setMBeanServerInterceptor}
|
||||
* method.</p>
|
||||
*
|
||||
* <p>The initial default interceptor provides the standard MBean
|
||||
* Server behavior. It handles a collection of named MBeans, each
|
||||
* represented by a Java object. A replacement default interceptor
|
||||
* may build on this behavior, for instance by adding logging or
|
||||
* security checks, before forwarding requests to the initial default
|
||||
* interceptor. Or, it may route each request to one of a number of
|
||||
* sub-interceptors, for instance based on the {@link ObjectName} in
|
||||
* the request.</p>
|
||||
*
|
||||
* <p>An interceptor, default or not, need not implement MBeans as
|
||||
* Java objects, in the way that the initial default interceptor does.
|
||||
* It may instead implement <em>virtual MBeans</em>, which do not
|
||||
* exist as Java objects when they are not in use. For example, these
|
||||
* MBeans could be implemented by forwarding requests to a database,
|
||||
* or to a remote MBean server, or by performing system calls to query
|
||||
* or modify system resources.</p>
|
||||
*
|
||||
* @since 1.5
|
||||
*/
|
||||
public interface MBeanServerInterceptor extends MBeanServer {
|
||||
/**
|
||||
* This method should never be called.
|
||||
* Usually hrows UnsupportedOperationException.
|
||||
*/
|
||||
public Object instantiate(String className)
|
||||
throws ReflectionException, MBeanException;
|
||||
/**
|
||||
* This method should never be called.
|
||||
* Usually throws UnsupportedOperationException.
|
||||
*/
|
||||
public Object instantiate(String className, ObjectName loaderName)
|
||||
throws ReflectionException, MBeanException,
|
||||
InstanceNotFoundException;
|
||||
/**
|
||||
* This method should never be called.
|
||||
* Usually throws UnsupportedOperationException.
|
||||
*/
|
||||
public Object instantiate(String className, Object[] params,
|
||||
String[] signature) throws ReflectionException, MBeanException;
|
||||
|
||||
/**
|
||||
* This method should never be called.
|
||||
* Usually throws UnsupportedOperationException.
|
||||
*/
|
||||
public Object instantiate(String className, ObjectName loaderName,
|
||||
Object[] params, String[] signature)
|
||||
throws ReflectionException, MBeanException,
|
||||
InstanceNotFoundException;
|
||||
|
||||
/**
|
||||
* This method should never be called.
|
||||
* Usually throws UnsupportedOperationException.
|
||||
*/
|
||||
@Deprecated
|
||||
public ObjectInputStream deserialize(ObjectName name, byte[] data)
|
||||
throws InstanceNotFoundException, OperationsException;
|
||||
|
||||
/**
|
||||
* This method should never be called.
|
||||
* Usually throws UnsupportedOperationException.
|
||||
*/
|
||||
@Deprecated
|
||||
public ObjectInputStream deserialize(String className, byte[] data)
|
||||
throws OperationsException, ReflectionException;
|
||||
|
||||
/**
|
||||
* This method should never be called.
|
||||
* Usually hrows UnsupportedOperationException.
|
||||
*/
|
||||
@Deprecated
|
||||
public ObjectInputStream deserialize(String className,
|
||||
ObjectName loaderName, byte[] data)
|
||||
throws InstanceNotFoundException, OperationsException,
|
||||
ReflectionException;
|
||||
|
||||
/**
|
||||
* This method should never be called.
|
||||
* Usually throws UnsupportedOperationException.
|
||||
*/
|
||||
public ClassLoaderRepository getClassLoaderRepository();
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,320 @@
|
||||
/*
|
||||
* Copyright (c) 2002, 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 com.sun.jmx.mbeanserver;
|
||||
|
||||
|
||||
import static com.sun.jmx.defaults.JmxProperties.MBEANSERVER_LOGGER;
|
||||
import java.security.Permission;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Hashtable;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.logging.Level;
|
||||
import javax.management.MBeanPermission;
|
||||
|
||||
import javax.management.ObjectName;
|
||||
import javax.management.loading.PrivateClassLoader;
|
||||
import sun.reflect.misc.ReflectUtil;
|
||||
|
||||
/**
|
||||
* This class keeps the list of Class Loaders registered in the MBean Server.
|
||||
* It provides the necessary methods to load classes using the
|
||||
* registered Class Loaders.
|
||||
*
|
||||
* @since 1.5
|
||||
*/
|
||||
final class ClassLoaderRepositorySupport
|
||||
implements ModifiableClassLoaderRepository {
|
||||
|
||||
/* We associate an optional ObjectName with each entry so that
|
||||
we can remove the correct entry when unregistering an MBean
|
||||
that is a ClassLoader. The same object could be registered
|
||||
under two different names (even though this is not recommended)
|
||||
so if we did not do this we could disturb the defined
|
||||
semantics for the order of ClassLoaders in the repository. */
|
||||
private static class LoaderEntry {
|
||||
ObjectName name; // can be null
|
||||
ClassLoader loader;
|
||||
|
||||
LoaderEntry(ObjectName name, ClassLoader loader) {
|
||||
this.name = name;
|
||||
this.loader = loader;
|
||||
}
|
||||
}
|
||||
|
||||
private static final LoaderEntry[] EMPTY_LOADER_ARRAY = new LoaderEntry[0];
|
||||
|
||||
/**
|
||||
* List of class loaders
|
||||
* Only read-only actions should be performed on this object.
|
||||
*
|
||||
* We do O(n) operations on this array, e.g. when removing
|
||||
* a ClassLoader. The assumption is that the number of elements
|
||||
* is small, probably less than ten, and that the vast majority
|
||||
* of operations are searches (loadClass) which are by definition
|
||||
* linear.
|
||||
*/
|
||||
private LoaderEntry[] loaders = EMPTY_LOADER_ARRAY;
|
||||
|
||||
/**
|
||||
* Same behavior as add(Object o) in {@link java.util.List}.
|
||||
* Replace the loader list with a new one in which the new
|
||||
* loader has been added.
|
||||
**/
|
||||
private synchronized boolean add(ObjectName name, ClassLoader cl) {
|
||||
List<LoaderEntry> l =
|
||||
new ArrayList<LoaderEntry>(Arrays.asList(loaders));
|
||||
l.add(new LoaderEntry(name, cl));
|
||||
loaders = l.toArray(EMPTY_LOADER_ARRAY);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Same behavior as remove(Object o) in {@link java.util.List}.
|
||||
* Replace the loader list with a new one in which the old loader
|
||||
* has been removed.
|
||||
*
|
||||
* The ObjectName may be null, in which case the entry to
|
||||
* be removed must also have a null ObjectName and the ClassLoader
|
||||
* values must match. If the ObjectName is not null, then
|
||||
* the first entry with a matching ObjectName is removed,
|
||||
* regardless of whether ClassLoader values match. (In fact,
|
||||
* the ClassLoader parameter will usually be null in this case.)
|
||||
**/
|
||||
private synchronized boolean remove(ObjectName name, ClassLoader cl) {
|
||||
final int size = loaders.length;
|
||||
for (int i = 0; i < size; i++) {
|
||||
LoaderEntry entry = loaders[i];
|
||||
boolean match =
|
||||
(name == null) ?
|
||||
cl == entry.loader :
|
||||
name.equals(entry.name);
|
||||
if (match) {
|
||||
LoaderEntry[] newloaders = new LoaderEntry[size - 1];
|
||||
System.arraycopy(loaders, 0, newloaders, 0, i);
|
||||
System.arraycopy(loaders, i + 1, newloaders, i,
|
||||
size - 1 - i);
|
||||
loaders = newloaders;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* List of valid search
|
||||
*/
|
||||
private final Map<String,List<ClassLoader>> search =
|
||||
new Hashtable<String,List<ClassLoader>>(10);
|
||||
|
||||
/**
|
||||
* List of named class loaders.
|
||||
*/
|
||||
private final Map<ObjectName,ClassLoader> loadersWithNames =
|
||||
new Hashtable<ObjectName,ClassLoader>(10);
|
||||
|
||||
// from javax.management.loading.DefaultLoaderRepository
|
||||
public final Class<?> loadClass(String className)
|
||||
throws ClassNotFoundException {
|
||||
return loadClass(loaders, className, null, null);
|
||||
}
|
||||
|
||||
|
||||
// from javax.management.loading.DefaultLoaderRepository
|
||||
public final Class<?> loadClassWithout(ClassLoader without, String className)
|
||||
throws ClassNotFoundException {
|
||||
if (MBEANSERVER_LOGGER.isLoggable(Level.FINER)) {
|
||||
MBEANSERVER_LOGGER.logp(Level.FINER,
|
||||
ClassLoaderRepositorySupport.class.getName(),
|
||||
"loadClassWithout", className + " without " + without);
|
||||
}
|
||||
|
||||
// without is null => just behave as loadClass
|
||||
//
|
||||
if (without == null)
|
||||
return loadClass(loaders, className, null, null);
|
||||
|
||||
// We must try to load the class without the given loader.
|
||||
//
|
||||
startValidSearch(without, className);
|
||||
try {
|
||||
return loadClass(loaders, className, without, null);
|
||||
} finally {
|
||||
stopValidSearch(without, className);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public final Class<?> loadClassBefore(ClassLoader stop, String className)
|
||||
throws ClassNotFoundException {
|
||||
if (MBEANSERVER_LOGGER.isLoggable(Level.FINER)) {
|
||||
MBEANSERVER_LOGGER.logp(Level.FINER,
|
||||
ClassLoaderRepositorySupport.class.getName(),
|
||||
"loadClassBefore", className + " before " + stop);
|
||||
}
|
||||
|
||||
if (stop == null)
|
||||
return loadClass(loaders, className, null, null);
|
||||
|
||||
startValidSearch(stop, className);
|
||||
try {
|
||||
return loadClass(loaders, className, null, stop);
|
||||
} finally {
|
||||
stopValidSearch(stop, className);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private Class<?> loadClass(final LoaderEntry list[],
|
||||
final String className,
|
||||
final ClassLoader without,
|
||||
final ClassLoader stop)
|
||||
throws ClassNotFoundException {
|
||||
ReflectUtil.checkPackageAccess(className);
|
||||
final int size = list.length;
|
||||
for(int i=0; i<size; i++) {
|
||||
try {
|
||||
final ClassLoader cl = list[i].loader;
|
||||
if (cl == null) // bootstrap class loader
|
||||
return Class.forName(className, false, null);
|
||||
if (cl == without)
|
||||
continue;
|
||||
if (cl == stop)
|
||||
break;
|
||||
if (MBEANSERVER_LOGGER.isLoggable(Level.FINER)) {
|
||||
MBEANSERVER_LOGGER.logp(Level.FINER,
|
||||
ClassLoaderRepositorySupport.class.getName(),
|
||||
"loadClass", "Trying loader = " + cl);
|
||||
}
|
||||
/* We used to have a special case for "instanceof
|
||||
MLet" here, where we invoked the method
|
||||
loadClass(className, null) to prevent infinite
|
||||
recursion. But the rule whereby the MLet only
|
||||
consults loaders that precede it in the CLR (via
|
||||
loadClassBefore) means that the recursion can't
|
||||
happen, and the test here caused some legitimate
|
||||
classloading to fail. For example, if you have
|
||||
dependencies C->D->E with loaders {E D C} in the
|
||||
CLR in that order, you would expect to be able to
|
||||
load C. The problem is that while resolving D, CLR
|
||||
delegation is disabled, so it can't find E. */
|
||||
return Class.forName(className, false, cl);
|
||||
} catch (ClassNotFoundException e) {
|
||||
// OK: continue with next class
|
||||
}
|
||||
}
|
||||
|
||||
throw new ClassNotFoundException(className);
|
||||
}
|
||||
|
||||
private synchronized void startValidSearch(ClassLoader aloader,
|
||||
String className)
|
||||
throws ClassNotFoundException {
|
||||
// Check if we have such a current search
|
||||
//
|
||||
List<ClassLoader> excluded = search.get(className);
|
||||
if ((excluded!= null) && (excluded.contains(aloader))) {
|
||||
if (MBEANSERVER_LOGGER.isLoggable(Level.FINER)) {
|
||||
MBEANSERVER_LOGGER.logp(Level.FINER,
|
||||
ClassLoaderRepositorySupport.class.getName(),
|
||||
"startValidSearch", "Already requested loader = " +
|
||||
aloader + " class = " + className);
|
||||
}
|
||||
throw new ClassNotFoundException(className);
|
||||
}
|
||||
|
||||
// Add an entry
|
||||
//
|
||||
if (excluded == null) {
|
||||
excluded = new ArrayList<ClassLoader>(1);
|
||||
search.put(className, excluded);
|
||||
}
|
||||
excluded.add(aloader);
|
||||
if (MBEANSERVER_LOGGER.isLoggable(Level.FINER)) {
|
||||
MBEANSERVER_LOGGER.logp(Level.FINER,
|
||||
ClassLoaderRepositorySupport.class.getName(),
|
||||
"startValidSearch",
|
||||
"loader = " + aloader + " class = " + className);
|
||||
}
|
||||
}
|
||||
|
||||
private synchronized void stopValidSearch(ClassLoader aloader,
|
||||
String className) {
|
||||
|
||||
// Retrieve the search.
|
||||
//
|
||||
List<ClassLoader> excluded = search.get(className);
|
||||
if (excluded != null) {
|
||||
excluded.remove(aloader);
|
||||
if (MBEANSERVER_LOGGER.isLoggable(Level.FINER)) {
|
||||
MBEANSERVER_LOGGER.logp(Level.FINER,
|
||||
ClassLoaderRepositorySupport.class.getName(),
|
||||
"stopValidSearch",
|
||||
"loader = " + aloader + " class = " + className);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public final void addClassLoader(ClassLoader loader) {
|
||||
add(null, loader);
|
||||
}
|
||||
|
||||
public final void removeClassLoader(ClassLoader loader) {
|
||||
remove(null, loader);
|
||||
}
|
||||
|
||||
public final synchronized void addClassLoader(ObjectName name,
|
||||
ClassLoader loader) {
|
||||
loadersWithNames.put(name, loader);
|
||||
if (!(loader instanceof PrivateClassLoader))
|
||||
add(name, loader);
|
||||
}
|
||||
|
||||
public final synchronized void removeClassLoader(ObjectName name) {
|
||||
ClassLoader loader = loadersWithNames.remove(name);
|
||||
if (!(loader instanceof PrivateClassLoader))
|
||||
remove(name, loader);
|
||||
}
|
||||
|
||||
public final ClassLoader getClassLoader(ObjectName name) {
|
||||
ClassLoader instance = loadersWithNames.get(name);
|
||||
if (instance != null) {
|
||||
SecurityManager sm = System.getSecurityManager();
|
||||
if (sm != null) {
|
||||
Permission perm =
|
||||
new MBeanPermission(instance.getClass().getName(),
|
||||
null,
|
||||
name,
|
||||
"getClassLoader");
|
||||
sm.checkPermission(perm);
|
||||
}
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
|
||||
}
|
||||
229
jdkSrc/jdk8/com/sun/jmx/mbeanserver/ConvertingMethod.java
Normal file
229
jdkSrc/jdk8/com/sun/jmx/mbeanserver/ConvertingMethod.java
Normal file
@@ -0,0 +1,229 @@
|
||||
/*
|
||||
* Copyright (c) 2005, 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 com.sun.jmx.mbeanserver;
|
||||
import java.io.InvalidObjectException;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Type;
|
||||
|
||||
import javax.management.Descriptor;
|
||||
import javax.management.MBeanException;
|
||||
import javax.management.openmbean.OpenDataException;
|
||||
import javax.management.openmbean.OpenType;
|
||||
import sun.reflect.misc.MethodUtil;
|
||||
|
||||
final class ConvertingMethod {
|
||||
static ConvertingMethod from(Method m) {
|
||||
try {
|
||||
return new ConvertingMethod(m);
|
||||
} catch (OpenDataException ode) {
|
||||
final String msg = "Method " + m.getDeclaringClass().getName() +
|
||||
"." + m.getName() + " has parameter or return type that " +
|
||||
"cannot be translated into an open type";
|
||||
throw new IllegalArgumentException(msg, ode);
|
||||
}
|
||||
}
|
||||
|
||||
Method getMethod() {
|
||||
return method;
|
||||
}
|
||||
|
||||
Descriptor getDescriptor() {
|
||||
return Introspector.descriptorForElement(method);
|
||||
}
|
||||
|
||||
Type getGenericReturnType() {
|
||||
return method.getGenericReturnType();
|
||||
}
|
||||
|
||||
Type[] getGenericParameterTypes() {
|
||||
return method.getGenericParameterTypes();
|
||||
}
|
||||
|
||||
String getName() {
|
||||
return method.getName();
|
||||
}
|
||||
|
||||
OpenType<?> getOpenReturnType() {
|
||||
return returnMapping.getOpenType();
|
||||
}
|
||||
|
||||
OpenType<?>[] getOpenParameterTypes() {
|
||||
final OpenType<?>[] types = new OpenType<?>[paramMappings.length];
|
||||
for (int i = 0; i < paramMappings.length; i++)
|
||||
types[i] = paramMappings[i].getOpenType();
|
||||
return types;
|
||||
}
|
||||
|
||||
/* Check that this method will be callable when we are going from
|
||||
* open types to Java types, for example when we are going from
|
||||
* an MXBean wrapper to the underlying resource.
|
||||
* The parameters will be converted to
|
||||
* Java types, so they must be "reconstructible". The return
|
||||
* value will be converted to an Open Type, so if it is convertible
|
||||
* at all there is no further check needed.
|
||||
*/
|
||||
void checkCallFromOpen() {
|
||||
try {
|
||||
for (MXBeanMapping paramConverter : paramMappings)
|
||||
paramConverter.checkReconstructible();
|
||||
} catch (InvalidObjectException e) {
|
||||
throw new IllegalArgumentException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/* Check that this method will be callable when we are going from
|
||||
* Java types to open types, for example when we are going from
|
||||
* an MXBean proxy to the open types that it will be mapped to.
|
||||
* The return type will be converted back to a Java type, so it
|
||||
* must be "reconstructible". The parameters will be converted to
|
||||
* open types, so if it is convertible at all there is no further
|
||||
* check needed.
|
||||
*/
|
||||
void checkCallToOpen() {
|
||||
try {
|
||||
returnMapping.checkReconstructible();
|
||||
} catch (InvalidObjectException e) {
|
||||
throw new IllegalArgumentException(e);
|
||||
}
|
||||
}
|
||||
|
||||
String[] getOpenSignature() {
|
||||
if (paramMappings.length == 0)
|
||||
return noStrings;
|
||||
|
||||
String[] sig = new String[paramMappings.length];
|
||||
for (int i = 0; i < paramMappings.length; i++)
|
||||
sig[i] = paramMappings[i].getOpenClass().getName();
|
||||
return sig;
|
||||
}
|
||||
|
||||
final Object toOpenReturnValue(MXBeanLookup lookup, Object ret)
|
||||
throws OpenDataException {
|
||||
return returnMapping.toOpenValue(ret);
|
||||
}
|
||||
|
||||
final Object fromOpenReturnValue(MXBeanLookup lookup, Object ret)
|
||||
throws InvalidObjectException {
|
||||
return returnMapping.fromOpenValue(ret);
|
||||
}
|
||||
|
||||
final Object[] toOpenParameters(MXBeanLookup lookup, Object[] params)
|
||||
throws OpenDataException {
|
||||
if (paramConversionIsIdentity || params == null)
|
||||
return params;
|
||||
final Object[] oparams = new Object[params.length];
|
||||
for (int i = 0; i < params.length; i++)
|
||||
oparams[i] = paramMappings[i].toOpenValue(params[i]);
|
||||
return oparams;
|
||||
}
|
||||
|
||||
final Object[] fromOpenParameters(Object[] params)
|
||||
throws InvalidObjectException {
|
||||
if (paramConversionIsIdentity || params == null)
|
||||
return params;
|
||||
final Object[] jparams = new Object[params.length];
|
||||
for (int i = 0; i < params.length; i++)
|
||||
jparams[i] = paramMappings[i].fromOpenValue(params[i]);
|
||||
return jparams;
|
||||
}
|
||||
|
||||
final Object toOpenParameter(MXBeanLookup lookup,
|
||||
Object param,
|
||||
int paramNo)
|
||||
throws OpenDataException {
|
||||
return paramMappings[paramNo].toOpenValue(param);
|
||||
}
|
||||
|
||||
final Object fromOpenParameter(MXBeanLookup lookup,
|
||||
Object param,
|
||||
int paramNo)
|
||||
throws InvalidObjectException {
|
||||
return paramMappings[paramNo].fromOpenValue(param);
|
||||
}
|
||||
|
||||
Object invokeWithOpenReturn(MXBeanLookup lookup,
|
||||
Object obj, Object[] params)
|
||||
throws MBeanException, IllegalAccessException,
|
||||
InvocationTargetException {
|
||||
MXBeanLookup old = MXBeanLookup.getLookup();
|
||||
try {
|
||||
MXBeanLookup.setLookup(lookup);
|
||||
return invokeWithOpenReturn(obj, params);
|
||||
} finally {
|
||||
MXBeanLookup.setLookup(old);
|
||||
}
|
||||
}
|
||||
|
||||
private Object invokeWithOpenReturn(Object obj, Object[] params)
|
||||
throws MBeanException, IllegalAccessException,
|
||||
InvocationTargetException {
|
||||
final Object[] javaParams;
|
||||
try {
|
||||
javaParams = fromOpenParameters(params);
|
||||
} catch (InvalidObjectException e) {
|
||||
// probably can't happen
|
||||
final String msg = methodName() + ": cannot convert parameters " +
|
||||
"from open values: " + e;
|
||||
throw new MBeanException(e, msg);
|
||||
}
|
||||
final Object javaReturn = MethodUtil.invoke(method, obj, javaParams);
|
||||
try {
|
||||
return returnMapping.toOpenValue(javaReturn);
|
||||
} catch (OpenDataException e) {
|
||||
// probably can't happen
|
||||
final String msg = methodName() + ": cannot convert return " +
|
||||
"value to open value: " + e;
|
||||
throw new MBeanException(e, msg);
|
||||
}
|
||||
}
|
||||
|
||||
private String methodName() {
|
||||
return method.getDeclaringClass() + "." + method.getName();
|
||||
}
|
||||
|
||||
private ConvertingMethod(Method m) throws OpenDataException {
|
||||
this.method = m;
|
||||
MXBeanMappingFactory mappingFactory = MXBeanMappingFactory.DEFAULT;
|
||||
returnMapping =
|
||||
mappingFactory.mappingForType(m.getGenericReturnType(), mappingFactory);
|
||||
Type[] params = m.getGenericParameterTypes();
|
||||
paramMappings = new MXBeanMapping[params.length];
|
||||
boolean identity = true;
|
||||
for (int i = 0; i < params.length; i++) {
|
||||
paramMappings[i] = mappingFactory.mappingForType(params[i], mappingFactory);
|
||||
identity &= DefaultMXBeanMappingFactory.isIdentity(paramMappings[i]);
|
||||
}
|
||||
paramConversionIsIdentity = identity;
|
||||
}
|
||||
|
||||
private static final String[] noStrings = new String[0];
|
||||
|
||||
private final Method method;
|
||||
private final MXBeanMapping returnMapping;
|
||||
private final MXBeanMapping[] paramMappings;
|
||||
private final boolean paramConversionIsIdentity;
|
||||
}
|
||||
1541
jdkSrc/jdk8/com/sun/jmx/mbeanserver/DefaultMXBeanMappingFactory.java
Normal file
1541
jdkSrc/jdk8/com/sun/jmx/mbeanserver/DefaultMXBeanMappingFactory.java
Normal file
File diff suppressed because it is too large
Load Diff
67
jdkSrc/jdk8/com/sun/jmx/mbeanserver/DescriptorCache.java
Normal file
67
jdkSrc/jdk8/com/sun/jmx/mbeanserver/DescriptorCache.java
Normal file
@@ -0,0 +1,67 @@
|
||||
/*
|
||||
* 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 com.sun.jmx.mbeanserver;
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.util.WeakHashMap;
|
||||
import javax.management.Descriptor;
|
||||
import javax.management.ImmutableDescriptor;
|
||||
import javax.management.JMX;
|
||||
|
||||
public class DescriptorCache {
|
||||
private DescriptorCache() {
|
||||
}
|
||||
|
||||
static DescriptorCache getInstance() {
|
||||
return instance;
|
||||
}
|
||||
|
||||
public static DescriptorCache getInstance(JMX proof) {
|
||||
if (proof != null)
|
||||
return instance;
|
||||
else
|
||||
return null;
|
||||
}
|
||||
|
||||
public ImmutableDescriptor get(ImmutableDescriptor descriptor) {
|
||||
WeakReference<ImmutableDescriptor> wr = map.get(descriptor);
|
||||
ImmutableDescriptor got = (wr == null) ? null : wr.get();
|
||||
if (got != null)
|
||||
return got;
|
||||
map.put(descriptor, new WeakReference<ImmutableDescriptor>(descriptor));
|
||||
return descriptor;
|
||||
}
|
||||
|
||||
public ImmutableDescriptor union(Descriptor... descriptors) {
|
||||
return get(ImmutableDescriptor.union(descriptors));
|
||||
}
|
||||
|
||||
private final static DescriptorCache instance = new DescriptorCache();
|
||||
private final WeakHashMap<ImmutableDescriptor,
|
||||
WeakReference<ImmutableDescriptor>>
|
||||
map = new WeakHashMap<ImmutableDescriptor,
|
||||
WeakReference<ImmutableDescriptor>>();
|
||||
}
|
||||
77
jdkSrc/jdk8/com/sun/jmx/mbeanserver/DynamicMBean2.java
Normal file
77
jdkSrc/jdk8/com/sun/jmx/mbeanserver/DynamicMBean2.java
Normal file
@@ -0,0 +1,77 @@
|
||||
/*
|
||||
* 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 com.sun.jmx.mbeanserver;
|
||||
|
||||
import javax.management.DynamicMBean;
|
||||
import javax.management.MBeanServer;
|
||||
import javax.management.ObjectName;
|
||||
|
||||
/**
|
||||
* A dynamic MBean that wraps an underlying resource. A version of this
|
||||
* interface might eventually appear in the public JMX API.
|
||||
*
|
||||
* @since 1.6
|
||||
*/
|
||||
public interface DynamicMBean2 extends DynamicMBean {
|
||||
/**
|
||||
* The resource corresponding to this MBean. This is the object whose
|
||||
* class name should be reflected by the MBean's
|
||||
* getMBeanInfo().getClassName() for example. For a "plain"
|
||||
* DynamicMBean it will be "this". For an MBean that wraps another
|
||||
* object, like javax.management.StandardMBean, it will be the wrapped
|
||||
* object.
|
||||
*/
|
||||
public Object getResource();
|
||||
|
||||
/**
|
||||
* The name of this MBean's class, as used by permission checks.
|
||||
* This is typically equal to getResource().getClass().getName().
|
||||
* This method is typically faster, sometimes much faster,
|
||||
* than getMBeanInfo().getClassName(), but should return the same
|
||||
* result.
|
||||
*/
|
||||
public String getClassName();
|
||||
|
||||
/**
|
||||
* Additional registration hook. This method is called after
|
||||
* {@link javax.management.MBeanRegistration#preRegister preRegister}.
|
||||
* Unlike that method, if it throws an exception and the MBean implements
|
||||
* {@code MBeanRegistration}, then {@link
|
||||
* javax.management.MBeanRegistration#postRegister postRegister(false)}
|
||||
* will be called on the MBean. This is the behavior that the MBean
|
||||
* expects for a problem that does not come from its own preRegister
|
||||
* method.
|
||||
*/
|
||||
public void preRegister2(MBeanServer mbs, ObjectName name)
|
||||
throws Exception;
|
||||
|
||||
/**
|
||||
* Additional registration hook. This method is called if preRegister
|
||||
* and preRegister2 succeed, but then the MBean cannot be registered
|
||||
* (for example because there is already another MBean of the same name).
|
||||
*/
|
||||
public void registerFailed();
|
||||
}
|
||||
46
jdkSrc/jdk8/com/sun/jmx/mbeanserver/GetPropertyAction.java
Normal file
46
jdkSrc/jdk8/com/sun/jmx/mbeanserver/GetPropertyAction.java
Normal file
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* Copyright (c) 2002, 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 com.sun.jmx.mbeanserver;
|
||||
|
||||
import java.security.PrivilegedAction;
|
||||
|
||||
/**
|
||||
* Utility class to be used by the method <tt>AccessControler.doPrivileged</tt>
|
||||
* to get a system property.
|
||||
*
|
||||
* @since 1.5
|
||||
*/
|
||||
public class GetPropertyAction implements PrivilegedAction<String> {
|
||||
private final String key;
|
||||
|
||||
public GetPropertyAction(String key) {
|
||||
this.key = key;
|
||||
}
|
||||
|
||||
public String run() {
|
||||
return System.getProperty(key);
|
||||
}
|
||||
}
|
||||
816
jdkSrc/jdk8/com/sun/jmx/mbeanserver/Introspector.java
Normal file
816
jdkSrc/jdk8/com/sun/jmx/mbeanserver/Introspector.java
Normal file
@@ -0,0 +1,816 @@
|
||||
/*
|
||||
* Copyright (c) 1999, 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 com.sun.jmx.mbeanserver;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.lang.ref.SoftReference;
|
||||
import java.lang.reflect.AnnotatedElement;
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.lang.reflect.Proxy;
|
||||
import java.lang.reflect.UndeclaredThrowableException;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.LinkedList;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.WeakHashMap;
|
||||
|
||||
import javax.management.Descriptor;
|
||||
import javax.management.DescriptorKey;
|
||||
import javax.management.DynamicMBean;
|
||||
import javax.management.ImmutableDescriptor;
|
||||
import javax.management.MBeanInfo;
|
||||
import javax.management.NotCompliantMBeanException;
|
||||
|
||||
import com.sun.jmx.remote.util.EnvHelp;
|
||||
import java.lang.reflect.Array;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.security.AccessController;
|
||||
import javax.management.AttributeNotFoundException;
|
||||
import javax.management.openmbean.CompositeData;
|
||||
import sun.reflect.misc.MethodUtil;
|
||||
import sun.reflect.misc.ReflectUtil;
|
||||
|
||||
/**
|
||||
* This class contains the methods for performing all the tests needed to verify
|
||||
* that a class represents a JMX compliant MBean.
|
||||
*
|
||||
* @since 1.5
|
||||
*/
|
||||
public class Introspector {
|
||||
final public static boolean ALLOW_NONPUBLIC_MBEAN;
|
||||
static {
|
||||
String val = AccessController.doPrivileged(new GetPropertyAction("jdk.jmx.mbeans.allowNonPublic"));
|
||||
ALLOW_NONPUBLIC_MBEAN = Boolean.parseBoolean(val);
|
||||
}
|
||||
|
||||
/*
|
||||
* ------------------------------------------
|
||||
* PRIVATE CONSTRUCTORS
|
||||
* ------------------------------------------
|
||||
*/
|
||||
|
||||
// private constructor defined to "hide" the default public constructor
|
||||
private Introspector() {
|
||||
|
||||
// ------------------------------
|
||||
// ------------------------------
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* ------------------------------------------
|
||||
* PUBLIC METHODS
|
||||
* ------------------------------------------
|
||||
*/
|
||||
|
||||
/**
|
||||
* Tell whether a MBean of the given class is a Dynamic MBean.
|
||||
* This method does nothing more than returning
|
||||
* <pre>
|
||||
* javax.management.DynamicMBean.class.isAssignableFrom(c)
|
||||
* </pre>
|
||||
* This method does not check for any JMX MBean compliance:
|
||||
* <ul><li>If <code>true</code> is returned, then instances of
|
||||
* <code>c</code> are DynamicMBean.</li>
|
||||
* <li>If <code>false</code> is returned, then no further
|
||||
* assumption can be made on instances of <code>c</code>.
|
||||
* In particular, instances of <code>c</code> may, or may not
|
||||
* be JMX standard MBeans.</li>
|
||||
* </ul>
|
||||
* @param c The class of the MBean under examination.
|
||||
* @return <code>true</code> if instances of <code>c</code> are
|
||||
* Dynamic MBeans, <code>false</code> otherwise.
|
||||
*
|
||||
**/
|
||||
public static final boolean isDynamic(final Class<?> c) {
|
||||
// Check if the MBean implements the DynamicMBean interface
|
||||
return javax.management.DynamicMBean.class.isAssignableFrom(c);
|
||||
}
|
||||
|
||||
/**
|
||||
* Basic method for testing that a MBean of a given class can be
|
||||
* instantiated by the MBean server.<p>
|
||||
* This method checks that:
|
||||
* <ul><li>The given class is a concrete class.</li>
|
||||
* <li>The given class exposes at least one public constructor.</li>
|
||||
* </ul>
|
||||
* If these conditions are not met, throws a NotCompliantMBeanException.
|
||||
* @param c The class of the MBean we want to create.
|
||||
* @exception NotCompliantMBeanException if the MBean class makes it
|
||||
* impossible to instantiate the MBean from within the
|
||||
* MBeanServer.
|
||||
*
|
||||
**/
|
||||
public static void testCreation(Class<?> c)
|
||||
throws NotCompliantMBeanException {
|
||||
// Check if the class is a concrete class
|
||||
final int mods = c.getModifiers();
|
||||
if (Modifier.isAbstract(mods) || Modifier.isInterface(mods)) {
|
||||
throw new NotCompliantMBeanException("MBean class must be concrete");
|
||||
}
|
||||
|
||||
// Check if the MBean has a public constructor
|
||||
final Constructor<?>[] consList = c.getConstructors();
|
||||
if (consList.length == 0) {
|
||||
throw new NotCompliantMBeanException("MBean class must have public constructor");
|
||||
}
|
||||
}
|
||||
|
||||
public static void checkCompliance(Class<?> mbeanClass)
|
||||
throws NotCompliantMBeanException {
|
||||
// Is DynamicMBean?
|
||||
//
|
||||
if (DynamicMBean.class.isAssignableFrom(mbeanClass))
|
||||
return;
|
||||
// Is Standard MBean?
|
||||
//
|
||||
final Exception mbeanException;
|
||||
try {
|
||||
getStandardMBeanInterface(mbeanClass);
|
||||
return;
|
||||
} catch (NotCompliantMBeanException e) {
|
||||
mbeanException = e;
|
||||
}
|
||||
// Is MXBean?
|
||||
//
|
||||
final Exception mxbeanException;
|
||||
try {
|
||||
getMXBeanInterface(mbeanClass);
|
||||
return;
|
||||
} catch (NotCompliantMBeanException e) {
|
||||
mxbeanException = e;
|
||||
}
|
||||
final String msg =
|
||||
"MBean class " + mbeanClass.getName() + " does not implement " +
|
||||
"DynamicMBean, and neither follows the Standard MBean conventions (" +
|
||||
mbeanException.toString() + ") nor the MXBean conventions (" +
|
||||
mxbeanException.toString() + ")";
|
||||
throw new NotCompliantMBeanException(msg);
|
||||
}
|
||||
|
||||
public static <T> DynamicMBean makeDynamicMBean(T mbean)
|
||||
throws NotCompliantMBeanException {
|
||||
if (mbean instanceof DynamicMBean)
|
||||
return (DynamicMBean) mbean;
|
||||
final Class<?> mbeanClass = mbean.getClass();
|
||||
Class<? super T> c = null;
|
||||
try {
|
||||
c = Util.cast(getStandardMBeanInterface(mbeanClass));
|
||||
} catch (NotCompliantMBeanException e) {
|
||||
// Ignore exception - we need to check whether
|
||||
// mbean is an MXBean first.
|
||||
}
|
||||
if (c != null)
|
||||
return new StandardMBeanSupport(mbean, c);
|
||||
|
||||
try {
|
||||
c = Util.cast(getMXBeanInterface(mbeanClass));
|
||||
} catch (NotCompliantMBeanException e) {
|
||||
// Ignore exception - we cannot decide whether mbean was supposed
|
||||
// to be an MBean or an MXBean. We will call checkCompliance()
|
||||
// to generate the appropriate exception.
|
||||
}
|
||||
if (c != null)
|
||||
return new MXBeanSupport(mbean, c);
|
||||
checkCompliance(mbeanClass);
|
||||
throw new NotCompliantMBeanException("Not compliant"); // not reached
|
||||
}
|
||||
|
||||
/**
|
||||
* Basic method for testing if a given class is a JMX compliant MBean.
|
||||
*
|
||||
* @param baseClass The class to be tested
|
||||
*
|
||||
* @return <code>null</code> if the MBean is a DynamicMBean,
|
||||
* the computed {@link javax.management.MBeanInfo} otherwise.
|
||||
* @exception NotCompliantMBeanException The specified class is not a
|
||||
* JMX compliant MBean
|
||||
*/
|
||||
public static MBeanInfo testCompliance(Class<?> baseClass)
|
||||
throws NotCompliantMBeanException {
|
||||
|
||||
// ------------------------------
|
||||
// ------------------------------
|
||||
|
||||
// Check if the MBean implements the MBean or the Dynamic
|
||||
// MBean interface
|
||||
if (isDynamic(baseClass))
|
||||
return null;
|
||||
|
||||
return testCompliance(baseClass, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the given interface class for being a compliant MXBean interface.
|
||||
* A compliant MXBean interface is any publicly accessible interface
|
||||
* following the {@link MXBean} conventions.
|
||||
* @param interfaceClass An interface class to test for the MXBean compliance
|
||||
* @throws NotCompliantMBeanException Thrown when the tested interface
|
||||
* is not public or contradicts the {@link MXBean} conventions.
|
||||
*/
|
||||
public static void testComplianceMXBeanInterface(Class<?> interfaceClass)
|
||||
throws NotCompliantMBeanException {
|
||||
MXBeanIntrospector.getInstance().getAnalyzer(interfaceClass);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the given interface class for being a compliant MBean interface.
|
||||
* A compliant MBean interface is any publicly accessible interface
|
||||
* following the {@code MBean} conventions.
|
||||
* @param interfaceClass An interface class to test for the MBean compliance
|
||||
* @throws NotCompliantMBeanException Thrown when the tested interface
|
||||
* is not public or contradicts the {@code MBean} conventions.
|
||||
*/
|
||||
public static void testComplianceMBeanInterface(Class<?> interfaceClass)
|
||||
throws NotCompliantMBeanException{
|
||||
StandardMBeanIntrospector.getInstance().getAnalyzer(interfaceClass);
|
||||
}
|
||||
|
||||
/**
|
||||
* Basic method for testing if a given class is a JMX compliant
|
||||
* Standard MBean. This method is only called by the legacy code
|
||||
* in com.sun.management.jmx.
|
||||
*
|
||||
* @param baseClass The class to be tested.
|
||||
*
|
||||
* @param mbeanInterface the MBean interface that the class implements,
|
||||
* or null if the interface must be determined by introspection.
|
||||
*
|
||||
* @return the computed {@link javax.management.MBeanInfo}.
|
||||
* @exception NotCompliantMBeanException The specified class is not a
|
||||
* JMX compliant Standard MBean
|
||||
*/
|
||||
public static synchronized MBeanInfo
|
||||
testCompliance(final Class<?> baseClass,
|
||||
Class<?> mbeanInterface)
|
||||
throws NotCompliantMBeanException {
|
||||
if (mbeanInterface == null)
|
||||
mbeanInterface = getStandardMBeanInterface(baseClass);
|
||||
ReflectUtil.checkPackageAccess(mbeanInterface);
|
||||
MBeanIntrospector<?> introspector = StandardMBeanIntrospector.getInstance();
|
||||
return getClassMBeanInfo(introspector, baseClass, mbeanInterface);
|
||||
}
|
||||
|
||||
private static <M> MBeanInfo
|
||||
getClassMBeanInfo(MBeanIntrospector<M> introspector,
|
||||
Class<?> baseClass, Class<?> mbeanInterface)
|
||||
throws NotCompliantMBeanException {
|
||||
PerInterface<M> perInterface = introspector.getPerInterface(mbeanInterface);
|
||||
return introspector.getClassMBeanInfo(baseClass, perInterface);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the MBean interface implemented by a JMX Standard
|
||||
* MBean class. This method is only called by the legacy
|
||||
* code in "com.sun.management.jmx".
|
||||
*
|
||||
* @param baseClass The class to be tested.
|
||||
*
|
||||
* @return The MBean interface implemented by the MBean.
|
||||
* Return <code>null</code> if the MBean is a DynamicMBean,
|
||||
* or if no MBean interface is found.
|
||||
*/
|
||||
public static Class<?> getMBeanInterface(Class<?> baseClass) {
|
||||
// Check if the given class implements the MBean interface
|
||||
// or the Dynamic MBean interface
|
||||
if (isDynamic(baseClass)) return null;
|
||||
try {
|
||||
return getStandardMBeanInterface(baseClass);
|
||||
} catch (NotCompliantMBeanException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the MBean interface implemented by a JMX Standard MBean class.
|
||||
*
|
||||
* @param baseClass The class to be tested.
|
||||
*
|
||||
* @return The MBean interface implemented by the Standard MBean.
|
||||
*
|
||||
* @throws NotCompliantMBeanException The specified class is
|
||||
* not a JMX compliant Standard MBean.
|
||||
*/
|
||||
public static <T> Class<? super T> getStandardMBeanInterface(Class<T> baseClass)
|
||||
throws NotCompliantMBeanException {
|
||||
Class<? super T> current = baseClass;
|
||||
Class<? super T> mbeanInterface = null;
|
||||
while (current != null) {
|
||||
mbeanInterface =
|
||||
findMBeanInterface(current, current.getName());
|
||||
if (mbeanInterface != null) break;
|
||||
current = current.getSuperclass();
|
||||
}
|
||||
if (mbeanInterface != null) {
|
||||
return mbeanInterface;
|
||||
} else {
|
||||
final String msg =
|
||||
"Class " + baseClass.getName() +
|
||||
" is not a JMX compliant Standard MBean";
|
||||
throw new NotCompliantMBeanException(msg);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the MXBean interface implemented by a JMX MXBean class.
|
||||
*
|
||||
* @param baseClass The class to be tested.
|
||||
*
|
||||
* @return The MXBean interface implemented by the MXBean.
|
||||
*
|
||||
* @throws NotCompliantMBeanException The specified class is
|
||||
* not a JMX compliant MXBean.
|
||||
*/
|
||||
public static <T> Class<? super T> getMXBeanInterface(Class<T> baseClass)
|
||||
throws NotCompliantMBeanException {
|
||||
try {
|
||||
return MXBeanSupport.findMXBeanInterface(baseClass);
|
||||
} catch (Exception e) {
|
||||
throw throwException(baseClass,e);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* ------------------------------------------
|
||||
* PRIVATE METHODS
|
||||
* ------------------------------------------
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* Try to find the MBean interface corresponding to the class aName
|
||||
* - i.e. <i>aName</i>MBean, from within aClass and its superclasses.
|
||||
**/
|
||||
private static <T> Class<? super T> findMBeanInterface(
|
||||
Class<T> aClass, String aName) {
|
||||
Class<? super T> current = aClass;
|
||||
while (current != null) {
|
||||
final Class<?>[] interfaces = current.getInterfaces();
|
||||
final int len = interfaces.length;
|
||||
for (int i=0;i<len;i++) {
|
||||
Class<? super T> inter = Util.cast(interfaces[i]);
|
||||
inter = implementsMBean(inter, aName);
|
||||
if (inter != null) return inter;
|
||||
}
|
||||
current = current.getSuperclass();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static Descriptor descriptorForElement(final AnnotatedElement elmt) {
|
||||
if (elmt == null)
|
||||
return ImmutableDescriptor.EMPTY_DESCRIPTOR;
|
||||
final Annotation[] annots = elmt.getAnnotations();
|
||||
return descriptorForAnnotations(annots);
|
||||
}
|
||||
|
||||
public static Descriptor descriptorForAnnotations(Annotation[] annots) {
|
||||
if (annots.length == 0)
|
||||
return ImmutableDescriptor.EMPTY_DESCRIPTOR;
|
||||
Map<String, Object> descriptorMap = new HashMap<String, Object>();
|
||||
for (Annotation a : annots) {
|
||||
Class<? extends Annotation> c = a.annotationType();
|
||||
Method[] elements = c.getMethods();
|
||||
boolean packageAccess = false;
|
||||
for (Method element : elements) {
|
||||
DescriptorKey key = element.getAnnotation(DescriptorKey.class);
|
||||
if (key != null) {
|
||||
String name = key.value();
|
||||
Object value;
|
||||
try {
|
||||
// Avoid checking access more than once per annotation
|
||||
if (!packageAccess) {
|
||||
ReflectUtil.checkPackageAccess(c);
|
||||
packageAccess = true;
|
||||
}
|
||||
value = MethodUtil.invoke(element, a, null);
|
||||
} catch (RuntimeException e) {
|
||||
// we don't expect this - except for possibly
|
||||
// security exceptions?
|
||||
// RuntimeExceptions shouldn't be "UndeclaredThrowable".
|
||||
// anyway...
|
||||
//
|
||||
throw e;
|
||||
} catch (Exception e) {
|
||||
// we don't expect this
|
||||
throw new UndeclaredThrowableException(e);
|
||||
}
|
||||
value = annotationToField(value);
|
||||
Object oldValue = descriptorMap.put(name, value);
|
||||
if (oldValue != null && !equals(oldValue, value)) {
|
||||
final String msg =
|
||||
"Inconsistent values for descriptor field " + name +
|
||||
" from annotations: " + value + " :: " + oldValue;
|
||||
throw new IllegalArgumentException(msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (descriptorMap.isEmpty())
|
||||
return ImmutableDescriptor.EMPTY_DESCRIPTOR;
|
||||
else
|
||||
return new ImmutableDescriptor(descriptorMap);
|
||||
}
|
||||
|
||||
/**
|
||||
* Throws a NotCompliantMBeanException or a SecurityException.
|
||||
* @param notCompliant the class which was under examination
|
||||
* @param cause the raeson why NotCompliantMBeanException should
|
||||
* be thrown.
|
||||
* @return nothing - this method always throw an exception.
|
||||
* The return type makes it possible to write
|
||||
* <pre> throw throwException(clazz,cause); </pre>
|
||||
* @throws SecurityException - if cause is a SecurityException
|
||||
* @throws NotCompliantMBeanException otherwise.
|
||||
**/
|
||||
static NotCompliantMBeanException throwException(Class<?> notCompliant,
|
||||
Throwable cause)
|
||||
throws NotCompliantMBeanException, SecurityException {
|
||||
if (cause instanceof SecurityException)
|
||||
throw (SecurityException) cause;
|
||||
if (cause instanceof NotCompliantMBeanException)
|
||||
throw (NotCompliantMBeanException)cause;
|
||||
final String classname =
|
||||
(notCompliant==null)?"null class":notCompliant.getName();
|
||||
final String reason =
|
||||
(cause==null)?"Not compliant":cause.getMessage();
|
||||
final NotCompliantMBeanException res =
|
||||
new NotCompliantMBeanException(classname+": "+reason);
|
||||
res.initCause(cause);
|
||||
throw res;
|
||||
}
|
||||
|
||||
// Convert a value from an annotation element to a descriptor field value
|
||||
// E.g. with @interface Foo {class value()} an annotation @Foo(String.class)
|
||||
// will produce a Descriptor field value "java.lang.String"
|
||||
private static Object annotationToField(Object x) {
|
||||
// An annotation element cannot have a null value but never mind
|
||||
if (x == null)
|
||||
return null;
|
||||
if (x instanceof Number || x instanceof String ||
|
||||
x instanceof Character || x instanceof Boolean ||
|
||||
x instanceof String[])
|
||||
return x;
|
||||
// Remaining possibilities: array of primitive (e.g. int[]),
|
||||
// enum, class, array of enum or class.
|
||||
Class<?> c = x.getClass();
|
||||
if (c.isArray()) {
|
||||
if (c.getComponentType().isPrimitive())
|
||||
return x;
|
||||
Object[] xx = (Object[]) x;
|
||||
String[] ss = new String[xx.length];
|
||||
for (int i = 0; i < xx.length; i++)
|
||||
ss[i] = (String) annotationToField(xx[i]);
|
||||
return ss;
|
||||
}
|
||||
if (x instanceof Class<?>)
|
||||
return ((Class<?>) x).getName();
|
||||
if (x instanceof Enum<?>)
|
||||
return ((Enum<?>) x).name();
|
||||
// The only other possibility is that the value is another
|
||||
// annotation, or that the language has evolved since this code
|
||||
// was written. We don't allow for either of those currently.
|
||||
// If it is indeed another annotation, then x will be a proxy
|
||||
// with an unhelpful name like $Proxy2. So we extract the
|
||||
// proxy's interface to use that in the exception message.
|
||||
if (Proxy.isProxyClass(c))
|
||||
c = c.getInterfaces()[0]; // array "can't be empty"
|
||||
throw new IllegalArgumentException("Illegal type for annotation " +
|
||||
"element using @DescriptorKey: " + c.getName());
|
||||
}
|
||||
|
||||
// This must be consistent with the check for duplicate field values in
|
||||
// ImmutableDescriptor.union. But we don't expect to be called very
|
||||
// often so this inefficient check should be enough.
|
||||
private static boolean equals(Object x, Object y) {
|
||||
return Arrays.deepEquals(new Object[] {x}, new Object[] {y});
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the XXMBean interface or null if no such interface exists
|
||||
*
|
||||
* @param c The interface to be tested
|
||||
* @param clName The name of the class implementing this interface
|
||||
*/
|
||||
private static <T> Class<? super T> implementsMBean(Class<T> c, String clName) {
|
||||
String clMBeanName = clName + "MBean";
|
||||
if (c.getName().equals(clMBeanName)) {
|
||||
return c;
|
||||
}
|
||||
Class<?>[] interfaces = c.getInterfaces();
|
||||
for (int i = 0;i < interfaces.length; i++) {
|
||||
if (interfaces[i].getName().equals(clMBeanName) &&
|
||||
(Modifier.isPublic(interfaces[i].getModifiers()) ||
|
||||
ALLOW_NONPUBLIC_MBEAN)) {
|
||||
return Util.cast(interfaces[i]);
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public static Object elementFromComplex(Object complex, String element)
|
||||
throws AttributeNotFoundException {
|
||||
try {
|
||||
if (complex.getClass().isArray() && element.equals("length")) {
|
||||
return Array.getLength(complex);
|
||||
} else if (complex instanceof CompositeData) {
|
||||
return ((CompositeData) complex).get(element);
|
||||
} else {
|
||||
// Java Beans introspection
|
||||
//
|
||||
Class<?> clazz = complex.getClass();
|
||||
Method readMethod = null;
|
||||
if (BeansHelper.isAvailable()) {
|
||||
Object bi = BeansHelper.getBeanInfo(clazz);
|
||||
Object[] pds = BeansHelper.getPropertyDescriptors(bi);
|
||||
for (Object pd: pds) {
|
||||
if (BeansHelper.getPropertyName(pd).equals(element)) {
|
||||
readMethod = BeansHelper.getReadMethod(pd);
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Java Beans not available so use simple introspection
|
||||
// to locate method
|
||||
readMethod = SimpleIntrospector.getReadMethod(clazz, element);
|
||||
}
|
||||
if (readMethod != null) {
|
||||
ReflectUtil.checkPackageAccess(readMethod.getDeclaringClass());
|
||||
return MethodUtil.invoke(readMethod, complex, new Class[0]);
|
||||
}
|
||||
|
||||
throw new AttributeNotFoundException(
|
||||
"Could not find the getter method for the property " +
|
||||
element + " using the Java Beans introspector");
|
||||
}
|
||||
} catch (InvocationTargetException e) {
|
||||
throw new IllegalArgumentException(e);
|
||||
} catch (AttributeNotFoundException e) {
|
||||
throw e;
|
||||
} catch (Exception e) {
|
||||
throw EnvHelp.initCause(
|
||||
new AttributeNotFoundException(e.getMessage()), e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A simple introspector that uses reflection to analyze a class and
|
||||
* identify its "getter" methods. This class is intended for use only when
|
||||
* Java Beans is not present (which implies that there isn't explicit
|
||||
* information about the bean available).
|
||||
*/
|
||||
private static class SimpleIntrospector {
|
||||
private SimpleIntrospector() { }
|
||||
|
||||
private static final String GET_METHOD_PREFIX = "get";
|
||||
private static final String IS_METHOD_PREFIX = "is";
|
||||
|
||||
// cache to avoid repeated lookups
|
||||
private static final Map<Class<?>,SoftReference<List<Method>>> cache =
|
||||
Collections.synchronizedMap(
|
||||
new WeakHashMap<Class<?>,SoftReference<List<Method>>> ());
|
||||
|
||||
/**
|
||||
* Returns the list of methods cached for the given class, or {@code null}
|
||||
* if not cached.
|
||||
*/
|
||||
private static List<Method> getCachedMethods(Class<?> clazz) {
|
||||
// return cached methods if possible
|
||||
SoftReference<List<Method>> ref = cache.get(clazz);
|
||||
if (ref != null) {
|
||||
List<Method> cached = ref.get();
|
||||
if (cached != null)
|
||||
return cached;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns {@code true} if the given method is a "getter" method (where
|
||||
* "getter" method is a public method of the form getXXX or "boolean
|
||||
* isXXX")
|
||||
*/
|
||||
static boolean isReadMethod(Method method) {
|
||||
// ignore static methods
|
||||
int modifiers = method.getModifiers();
|
||||
if (Modifier.isStatic(modifiers))
|
||||
return false;
|
||||
|
||||
String name = method.getName();
|
||||
Class<?>[] paramTypes = method.getParameterTypes();
|
||||
int paramCount = paramTypes.length;
|
||||
|
||||
if (paramCount == 0 && name.length() > 2) {
|
||||
// boolean isXXX()
|
||||
if (name.startsWith(IS_METHOD_PREFIX))
|
||||
return (method.getReturnType() == boolean.class);
|
||||
// getXXX()
|
||||
if (name.length() > 3 && name.startsWith(GET_METHOD_PREFIX))
|
||||
return (method.getReturnType() != void.class);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the list of "getter" methods for the given class. The list
|
||||
* is ordered so that isXXX methods appear before getXXX methods - this
|
||||
* is for compatibility with the JavaBeans Introspector.
|
||||
*/
|
||||
static List<Method> getReadMethods(Class<?> clazz) {
|
||||
// return cached result if available
|
||||
List<Method> cachedResult = getCachedMethods(clazz);
|
||||
if (cachedResult != null)
|
||||
return cachedResult;
|
||||
|
||||
// get list of public methods, filtering out methods that have
|
||||
// been overridden to return a more specific type.
|
||||
List<Method> methods =
|
||||
StandardMBeanIntrospector.getInstance().getMethods(clazz);
|
||||
methods = MBeanAnalyzer.eliminateCovariantMethods(methods);
|
||||
|
||||
// filter out the non-getter methods
|
||||
List<Method> result = new LinkedList<Method>();
|
||||
for (Method m: methods) {
|
||||
if (isReadMethod(m)) {
|
||||
// favor isXXX over getXXX
|
||||
if (m.getName().startsWith(IS_METHOD_PREFIX)) {
|
||||
result.add(0, m);
|
||||
} else {
|
||||
result.add(m);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// add result to cache
|
||||
cache.put(clazz, new SoftReference<List<Method>>(result));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the "getter" to read the given property from the given class or
|
||||
* {@code null} if no method is found.
|
||||
*/
|
||||
static Method getReadMethod(Class<?> clazz, String property) {
|
||||
// first character in uppercase (compatibility with JavaBeans)
|
||||
property = property.substring(0, 1).toUpperCase(Locale.ENGLISH) +
|
||||
property.substring(1);
|
||||
String getMethod = GET_METHOD_PREFIX + property;
|
||||
String isMethod = IS_METHOD_PREFIX + property;
|
||||
for (Method m: getReadMethods(clazz)) {
|
||||
String name = m.getName();
|
||||
if (name.equals(isMethod) || name.equals(getMethod)) {
|
||||
return m;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A class that provides access to the JavaBeans Introspector and
|
||||
* PropertyDescriptors without creating a static dependency on java.beans.
|
||||
*/
|
||||
private static class BeansHelper {
|
||||
private static final Class<?> introspectorClass =
|
||||
getClass("java.beans.Introspector");
|
||||
private static final Class<?> beanInfoClass =
|
||||
(introspectorClass == null) ? null : getClass("java.beans.BeanInfo");
|
||||
private static final Class<?> getPropertyDescriptorClass =
|
||||
(beanInfoClass == null) ? null : getClass("java.beans.PropertyDescriptor");
|
||||
|
||||
private static final Method getBeanInfo =
|
||||
getMethod(introspectorClass, "getBeanInfo", Class.class);
|
||||
private static final Method getPropertyDescriptors =
|
||||
getMethod(beanInfoClass, "getPropertyDescriptors");
|
||||
private static final Method getPropertyName =
|
||||
getMethod(getPropertyDescriptorClass, "getName");
|
||||
private static final Method getReadMethod =
|
||||
getMethod(getPropertyDescriptorClass, "getReadMethod");
|
||||
|
||||
private static Class<?> getClass(String name) {
|
||||
try {
|
||||
return Class.forName(name, true, null);
|
||||
} catch (ClassNotFoundException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
private static Method getMethod(Class<?> clazz,
|
||||
String name,
|
||||
Class<?>... paramTypes)
|
||||
{
|
||||
if (clazz != null) {
|
||||
try {
|
||||
return clazz.getMethod(name, paramTypes);
|
||||
} catch (NoSuchMethodException e) {
|
||||
throw new AssertionError(e);
|
||||
}
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private BeansHelper() { }
|
||||
|
||||
/**
|
||||
* Returns {@code true} if java.beans is available.
|
||||
*/
|
||||
static boolean isAvailable() {
|
||||
return introspectorClass != null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Invokes java.beans.Introspector.getBeanInfo(Class)
|
||||
*/
|
||||
static Object getBeanInfo(Class<?> clazz) throws Exception {
|
||||
try {
|
||||
return getBeanInfo.invoke(null, clazz);
|
||||
} catch (InvocationTargetException e) {
|
||||
Throwable cause = e.getCause();
|
||||
if (cause instanceof Exception)
|
||||
throw (Exception)cause;
|
||||
throw new AssertionError(e);
|
||||
} catch (IllegalAccessException iae) {
|
||||
throw new AssertionError(iae);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Invokes java.beans.BeanInfo.getPropertyDescriptors()
|
||||
*/
|
||||
static Object[] getPropertyDescriptors(Object bi) {
|
||||
try {
|
||||
return (Object[])getPropertyDescriptors.invoke(bi);
|
||||
} catch (InvocationTargetException e) {
|
||||
Throwable cause = e.getCause();
|
||||
if (cause instanceof RuntimeException)
|
||||
throw (RuntimeException)cause;
|
||||
throw new AssertionError(e);
|
||||
} catch (IllegalAccessException iae) {
|
||||
throw new AssertionError(iae);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Invokes java.beans.PropertyDescriptor.getName()
|
||||
*/
|
||||
static String getPropertyName(Object pd) {
|
||||
try {
|
||||
return (String)getPropertyName.invoke(pd);
|
||||
} catch (InvocationTargetException e) {
|
||||
Throwable cause = e.getCause();
|
||||
if (cause instanceof RuntimeException)
|
||||
throw (RuntimeException)cause;
|
||||
throw new AssertionError(e);
|
||||
} catch (IllegalAccessException iae) {
|
||||
throw new AssertionError(iae);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Invokes java.beans.PropertyDescriptor.getReadMethod()
|
||||
*/
|
||||
static Method getReadMethod(Object pd) {
|
||||
try {
|
||||
return (Method)getReadMethod.invoke(pd);
|
||||
} catch (InvocationTargetException e) {
|
||||
Throwable cause = e.getCause();
|
||||
if (cause instanceof RuntimeException)
|
||||
throw (RuntimeException)cause;
|
||||
throw new AssertionError(e);
|
||||
} catch (IllegalAccessException iae) {
|
||||
throw new AssertionError(iae);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
1522
jdkSrc/jdk8/com/sun/jmx/mbeanserver/JmxMBeanServer.java
Normal file
1522
jdkSrc/jdk8/com/sun/jmx/mbeanserver/JmxMBeanServer.java
Normal file
File diff suppressed because it is too large
Load Diff
114
jdkSrc/jdk8/com/sun/jmx/mbeanserver/JmxMBeanServerBuilder.java
Normal file
114
jdkSrc/jdk8/com/sun/jmx/mbeanserver/JmxMBeanServerBuilder.java
Normal file
@@ -0,0 +1,114 @@
|
||||
/*
|
||||
* Copyright (c) 2002, 2007, 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.mbeanserver;
|
||||
|
||||
import javax.management.MBeanServer;
|
||||
import javax.management.MBeanServerDelegate;
|
||||
import javax.management.MBeanServerBuilder;
|
||||
|
||||
/**
|
||||
* This class represents a builder that creates
|
||||
* {@link javax.management.MBeanServer} implementations.
|
||||
* The JMX {@link javax.management.MBeanServerFactory} allows
|
||||
* for applications to provide their custom MBeanServer
|
||||
* implementation. This class is not used when the whole Sun Reference JMX
|
||||
* Implementation is used. However it may be used to substitute Sun
|
||||
* MBeanServer implementation to another JMX implementation.
|
||||
* <p>
|
||||
* Contrarily to the default {@link javax.management.MBeanServerBuilder
|
||||
* javax.management.MBeanServerBuilder} this MBeanServerBuilder returns
|
||||
* MBeanServers on which
|
||||
* {@link com.sun.jmx.interceptor.MBeanServerInterceptor}s are enabled.
|
||||
*
|
||||
* @since 1.5
|
||||
*/
|
||||
public class JmxMBeanServerBuilder extends MBeanServerBuilder {
|
||||
/**
|
||||
* This method creates a new MBeanServerDelegate for a new MBeanServer.
|
||||
* When creating a new MBeanServer the
|
||||
* {@link javax.management.MBeanServerFactory} first calls this method
|
||||
* in order to create a new MBeanServerDelegate.
|
||||
* <br>Then it calls
|
||||
* <code>newMBeanServer(defaultDomain,outer,delegate)</code>
|
||||
* passing the <var>delegate</var> that should be used by the MBeanServer
|
||||
* implementation.
|
||||
* <p>Note that the passed <var>delegate</var> might not be directly the
|
||||
* MBeanServerDelegate that was returned by this method. It could
|
||||
* be, for instance, a new object wrapping the previously
|
||||
* returned object.
|
||||
*
|
||||
* @return A new {@link javax.management.MBeanServerDelegate}.
|
||||
**/
|
||||
public MBeanServerDelegate newMBeanServerDelegate() {
|
||||
return JmxMBeanServer.newMBeanServerDelegate();
|
||||
}
|
||||
|
||||
/**
|
||||
* This method creates a new MBeanServer implementation object.
|
||||
* When creating a new MBeanServer the
|
||||
* {@link javax.management.MBeanServerFactory} first calls
|
||||
* <code>newMBeanServerDelegate()</code> in order to obtain a new
|
||||
* {@link javax.management.MBeanServerDelegate} for the new
|
||||
* MBeanServer. Then it calls
|
||||
* <code>newMBeanServer(defaultDomain,outer,delegate)</code>
|
||||
* passing the <var>delegate</var> that should be used by the
|
||||
* MBeanServer implementation.
|
||||
* <p>Note that the passed <var>delegate</var> might not be directly the
|
||||
* MBeanServerDelegate that was returned by this implementation. It could
|
||||
* be, for instance, a new object wrapping the previously
|
||||
* returned delegate.
|
||||
* <p>The <var>outer</var> parameter is a pointer to the MBeanServer that
|
||||
* should be passed to the {@link javax.management.MBeanRegistration}
|
||||
* interface when registering MBeans inside the MBeanServer.
|
||||
* If <var>outer</var> is <code>null</code>, then the MBeanServer
|
||||
* implementation is free to use its own <code>this</code> pointer when
|
||||
* invoking the {@link javax.management.MBeanRegistration} interface.
|
||||
* <p>This makes it possible for a MBeanServer implementation to wrap
|
||||
* another MBeanServer implementation, in order to implement, e.g,
|
||||
* security checks, or to prevent access to the actual MBeanServer
|
||||
* implementation by returning a pointer to a wrapping object.
|
||||
* <p>
|
||||
* This MBeanServerBuilder makes it possible to create MBeanServer
|
||||
* which support {@link com.sun.jmx.interceptor.MBeanServerInterceptor}s.
|
||||
*
|
||||
* @param defaultDomain Default domain of the new MBeanServer.
|
||||
* @param outer A pointer to the MBeanServer object that must be
|
||||
* passed to the MBeans when invoking their
|
||||
* {@link javax.management.MBeanRegistration} interface.
|
||||
* @param delegate A pointer to the MBeanServerDelegate associated
|
||||
* with the new MBeanServer. The new MBeanServer must register
|
||||
* this MBean in its MBean repository.
|
||||
*
|
||||
* @return A new private implementation of an MBeanServer.
|
||||
**/
|
||||
public MBeanServer newMBeanServer(String defaultDomain,
|
||||
MBeanServer outer,
|
||||
MBeanServerDelegate delegate) {
|
||||
return JmxMBeanServer.newMBeanServer(defaultDomain,outer,delegate,
|
||||
true);
|
||||
}
|
||||
|
||||
}
|
||||
275
jdkSrc/jdk8/com/sun/jmx/mbeanserver/MBeanAnalyzer.java
Normal file
275
jdkSrc/jdk8/com/sun/jmx/mbeanserver/MBeanAnalyzer.java
Normal file
@@ -0,0 +1,275 @@
|
||||
/*
|
||||
* Copyright (c) 2005, 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 com.sun.jmx.mbeanserver;
|
||||
|
||||
import static com.sun.jmx.mbeanserver.Util.*;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.security.AccessController;
|
||||
import java.util.Arrays;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import javax.management.NotCompliantMBeanException;
|
||||
|
||||
/**
|
||||
* <p>An analyzer for a given MBean interface. The analyzer can
|
||||
* be for Standard MBeans or MXBeans, depending on the MBeanIntrospector
|
||||
* passed at construction.
|
||||
*
|
||||
* <p>The analyzer can
|
||||
* visit the attributes and operations of the interface, calling
|
||||
* a caller-supplied visitor method for each one.</p>
|
||||
*
|
||||
* @param <M> Method or ConvertingMethod according as this is a
|
||||
* Standard MBean or an MXBean.
|
||||
*
|
||||
* @since 1.6
|
||||
*/
|
||||
class MBeanAnalyzer<M> {
|
||||
static interface MBeanVisitor<M> {
|
||||
public void visitAttribute(String attributeName,
|
||||
M getter,
|
||||
M setter);
|
||||
public void visitOperation(String operationName,
|
||||
M operation);
|
||||
}
|
||||
|
||||
void visit(MBeanVisitor<M> visitor) {
|
||||
// visit attributes
|
||||
for (Map.Entry<String, AttrMethods<M>> entry : attrMap.entrySet()) {
|
||||
String name = entry.getKey();
|
||||
AttrMethods<M> am = entry.getValue();
|
||||
visitor.visitAttribute(name, am.getter, am.setter);
|
||||
}
|
||||
|
||||
// visit operations
|
||||
for (Map.Entry<String, List<M>> entry : opMap.entrySet()) {
|
||||
for (M m : entry.getValue())
|
||||
visitor.visitOperation(entry.getKey(), m);
|
||||
}
|
||||
}
|
||||
|
||||
/* Map op name to method */
|
||||
private Map<String, List<M>> opMap = newInsertionOrderMap();
|
||||
/* Map attr name to getter and/or setter */
|
||||
private Map<String, AttrMethods<M>> attrMap = newInsertionOrderMap();
|
||||
|
||||
private static class AttrMethods<M> {
|
||||
M getter;
|
||||
M setter;
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Return an MBeanAnalyzer for the given MBean interface and
|
||||
* MBeanIntrospector. Calling this method twice with the same
|
||||
* parameters may return the same object or two different but
|
||||
* equivalent objects.
|
||||
*/
|
||||
// Currently it's two different but equivalent objects. This only
|
||||
// really impacts proxy generation. For MBean creation, the
|
||||
// cached PerInterface object for an MBean interface means that
|
||||
// an analyzer will not be recreated for a second MBean using the
|
||||
// same interface.
|
||||
static <M> MBeanAnalyzer<M> analyzer(Class<?> mbeanType,
|
||||
MBeanIntrospector<M> introspector)
|
||||
throws NotCompliantMBeanException {
|
||||
return new MBeanAnalyzer<M>(mbeanType, introspector);
|
||||
}
|
||||
|
||||
private MBeanAnalyzer(Class<?> mbeanType,
|
||||
MBeanIntrospector<M> introspector)
|
||||
throws NotCompliantMBeanException {
|
||||
if (!mbeanType.isInterface()) {
|
||||
throw new NotCompliantMBeanException("Not an interface: " +
|
||||
mbeanType.getName());
|
||||
} else if (!Modifier.isPublic(mbeanType.getModifiers()) &&
|
||||
!Introspector.ALLOW_NONPUBLIC_MBEAN) {
|
||||
throw new NotCompliantMBeanException("Interface is not public: " +
|
||||
mbeanType.getName());
|
||||
}
|
||||
|
||||
try {
|
||||
initMaps(mbeanType, introspector);
|
||||
} catch (Exception x) {
|
||||
throw Introspector.throwException(mbeanType,x);
|
||||
}
|
||||
}
|
||||
|
||||
// Introspect the mbeanInterface and initialize this object's maps.
|
||||
//
|
||||
private void initMaps(Class<?> mbeanType,
|
||||
MBeanIntrospector<M> introspector) throws Exception {
|
||||
final List<Method> methods1 = introspector.getMethods(mbeanType);
|
||||
final List<Method> methods = eliminateCovariantMethods(methods1);
|
||||
|
||||
/* Run through the methods to detect inconsistencies and to enable
|
||||
us to give getter and setter together to visitAttribute. */
|
||||
for (Method m : methods) {
|
||||
final String name = m.getName();
|
||||
final int nParams = m.getParameterTypes().length;
|
||||
|
||||
final M cm = introspector.mFrom(m);
|
||||
|
||||
String attrName = "";
|
||||
if (name.startsWith("get"))
|
||||
attrName = name.substring(3);
|
||||
else if (name.startsWith("is")
|
||||
&& m.getReturnType() == boolean.class)
|
||||
attrName = name.substring(2);
|
||||
|
||||
if (attrName.length() != 0 && nParams == 0
|
||||
&& m.getReturnType() != void.class) {
|
||||
// It's a getter
|
||||
// Check we don't have both isX and getX
|
||||
AttrMethods<M> am = attrMap.get(attrName);
|
||||
if (am == null)
|
||||
am = new AttrMethods<M>();
|
||||
else {
|
||||
if (am.getter != null) {
|
||||
final String msg = "Attribute " + attrName +
|
||||
" has more than one getter";
|
||||
throw new NotCompliantMBeanException(msg);
|
||||
}
|
||||
}
|
||||
am.getter = cm;
|
||||
attrMap.put(attrName, am);
|
||||
} else if (name.startsWith("set") && name.length() > 3
|
||||
&& nParams == 1 &&
|
||||
m.getReturnType() == void.class) {
|
||||
// It's a setter
|
||||
attrName = name.substring(3);
|
||||
AttrMethods<M> am = attrMap.get(attrName);
|
||||
if (am == null)
|
||||
am = new AttrMethods<M>();
|
||||
else if (am.setter != null) {
|
||||
final String msg = "Attribute " + attrName +
|
||||
" has more than one setter";
|
||||
throw new NotCompliantMBeanException(msg);
|
||||
}
|
||||
am.setter = cm;
|
||||
attrMap.put(attrName, am);
|
||||
} else {
|
||||
// It's an operation
|
||||
List<M> cms = opMap.get(name);
|
||||
if (cms == null)
|
||||
cms = newList();
|
||||
cms.add(cm);
|
||||
opMap.put(name, cms);
|
||||
}
|
||||
}
|
||||
/* Check that getters and setters are consistent. */
|
||||
for (Map.Entry<String, AttrMethods<M>> entry : attrMap.entrySet()) {
|
||||
AttrMethods<M> am = entry.getValue();
|
||||
if (!introspector.consistent(am.getter, am.setter)) {
|
||||
final String msg = "Getter and setter for " + entry.getKey() +
|
||||
" have inconsistent types";
|
||||
throw new NotCompliantMBeanException(msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A comparator that defines a total order so that methods have the
|
||||
* same name and identical signatures appear next to each others.
|
||||
* The methods are sorted in such a way that methods which
|
||||
* override each other will sit next to each other, with the
|
||||
* overridden method first - e.g. Object getFoo() is placed before
|
||||
* Integer getFoo(). This makes it possible to determine whether
|
||||
* a method overrides another one simply by looking at the method(s)
|
||||
* that precedes it in the list. (see eliminateCovariantMethods).
|
||||
**/
|
||||
private static class MethodOrder implements Comparator<Method> {
|
||||
public int compare(Method a, Method b) {
|
||||
final int cmp = a.getName().compareTo(b.getName());
|
||||
if (cmp != 0) return cmp;
|
||||
final Class<?>[] aparams = a.getParameterTypes();
|
||||
final Class<?>[] bparams = b.getParameterTypes();
|
||||
if (aparams.length != bparams.length)
|
||||
return aparams.length - bparams.length;
|
||||
if (!Arrays.equals(aparams, bparams)) {
|
||||
return Arrays.toString(aparams).
|
||||
compareTo(Arrays.toString(bparams));
|
||||
}
|
||||
final Class<?> aret = a.getReturnType();
|
||||
final Class<?> bret = b.getReturnType();
|
||||
if (aret == bret) return 0;
|
||||
|
||||
// Super type comes first: Object, Number, Integer
|
||||
if (aret.isAssignableFrom(bret))
|
||||
return -1;
|
||||
return +1; // could assert bret.isAssignableFrom(aret)
|
||||
}
|
||||
public final static MethodOrder instance = new MethodOrder();
|
||||
}
|
||||
|
||||
|
||||
/* Eliminate methods that are overridden with a covariant return type.
|
||||
Reflection will return both the original and the overriding method
|
||||
but only the overriding one is of interest. We return the methods
|
||||
in the same order they arrived in. This isn't required by the spec
|
||||
but existing code may depend on it and users may be used to seeing
|
||||
operations or attributes appear in a particular order.
|
||||
|
||||
Because of the way this method works, if the same Method appears
|
||||
more than once in the given List then it will be completely deleted!
|
||||
So don't do that. */
|
||||
static List<Method>
|
||||
eliminateCovariantMethods(List<Method> startMethods) {
|
||||
// We are assuming that you never have very many methods with the
|
||||
// same name, so it is OK to use algorithms that are quadratic
|
||||
// in the number of methods with the same name.
|
||||
|
||||
final int len = startMethods.size();
|
||||
final Method[] sorted = startMethods.toArray(new Method[len]);
|
||||
Arrays.sort(sorted,MethodOrder.instance);
|
||||
final Set<Method> overridden = newSet();
|
||||
for (int i=1;i<len;i++) {
|
||||
final Method m0 = sorted[i-1];
|
||||
final Method m1 = sorted[i];
|
||||
|
||||
// Methods that don't have the same name can't override each other
|
||||
if (!m0.getName().equals(m1.getName())) continue;
|
||||
|
||||
// Methods that have the same name and same signature override
|
||||
// each other. In that case, the second method overrides the first,
|
||||
// due to the way we have sorted them in MethodOrder.
|
||||
if (Arrays.equals(m0.getParameterTypes(),
|
||||
m1.getParameterTypes())) {
|
||||
if (!overridden.add(m0))
|
||||
throw new RuntimeException("Internal error: duplicate Method");
|
||||
}
|
||||
}
|
||||
|
||||
final List<Method> methods = newList(startMethods);
|
||||
methods.removeAll(overridden);
|
||||
return methods;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
786
jdkSrc/jdk8/com/sun/jmx/mbeanserver/MBeanInstantiator.java
Normal file
786
jdkSrc/jdk8/com/sun/jmx/mbeanserver/MBeanInstantiator.java
Normal 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 com.sun.jmx.mbeanserver;
|
||||
|
||||
|
||||
import static com.sun.jmx.defaults.JmxProperties.MBEANSERVER_LOGGER;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.ObjectInputStream;
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.security.AccessControlContext;
|
||||
import java.security.AccessController;
|
||||
import java.security.Permission;
|
||||
import java.security.Permissions;
|
||||
import java.security.PrivilegedAction;
|
||||
import java.security.ProtectionDomain;
|
||||
import java.util.Map;
|
||||
import java.util.logging.Level;
|
||||
|
||||
import javax.management.InstanceNotFoundException;
|
||||
import javax.management.MBeanException;
|
||||
import javax.management.MBeanPermission;
|
||||
import javax.management.NotCompliantMBeanException;
|
||||
import javax.management.ObjectName;
|
||||
import javax.management.OperationsException;
|
||||
import javax.management.ReflectionException;
|
||||
import javax.management.RuntimeErrorException;
|
||||
import javax.management.RuntimeMBeanException;
|
||||
import javax.management.RuntimeOperationsException;
|
||||
import sun.reflect.misc.ConstructorUtil;
|
||||
import sun.reflect.misc.ReflectUtil;
|
||||
|
||||
/**
|
||||
* Implements the MBeanInstantiator interface. Provides methods for
|
||||
* instantiating objects, finding the class given its name and using
|
||||
* different class loaders, deserializing objects in the context of a
|
||||
* given class loader.
|
||||
*
|
||||
* @since 1.5
|
||||
*/
|
||||
public class MBeanInstantiator {
|
||||
private final ModifiableClassLoaderRepository clr;
|
||||
// private MetaData meta = null;
|
||||
|
||||
MBeanInstantiator(ModifiableClassLoaderRepository clr) {
|
||||
this.clr = clr;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* This methods tests if the MBean class makes it possible to
|
||||
* instantiate an MBean of this class in the MBeanServer.
|
||||
* e.g. it must have a public constructor, be a concrete class...
|
||||
*/
|
||||
public void testCreation(Class<?> c) throws NotCompliantMBeanException {
|
||||
Introspector.testCreation(c);
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads the class with the specified name using this object's
|
||||
* Default Loader Repository.
|
||||
**/
|
||||
public Class<?> findClassWithDefaultLoaderRepository(String className)
|
||||
throws ReflectionException {
|
||||
|
||||
Class<?> theClass;
|
||||
if (className == null) {
|
||||
throw new RuntimeOperationsException(new
|
||||
IllegalArgumentException("The class name cannot be null"),
|
||||
"Exception occurred during object instantiation");
|
||||
}
|
||||
|
||||
ReflectUtil.checkPackageAccess(className);
|
||||
try {
|
||||
if (clr == null) throw new ClassNotFoundException(className);
|
||||
theClass = clr.loadClass(className);
|
||||
}
|
||||
catch (ClassNotFoundException ee) {
|
||||
throw new ReflectionException(ee,
|
||||
"The MBean class could not be loaded by the default loader repository");
|
||||
}
|
||||
|
||||
return theClass;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Gets the class for the specified class name using the MBean
|
||||
* Interceptor's classloader
|
||||
*/
|
||||
public Class<?> findClass(String className, ClassLoader loader)
|
||||
throws ReflectionException {
|
||||
|
||||
return loadClass(className,loader);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the class for the specified class name using the specified
|
||||
* class loader
|
||||
*/
|
||||
public Class<?> findClass(String className, ObjectName aLoader)
|
||||
throws ReflectionException, InstanceNotFoundException {
|
||||
|
||||
if (aLoader == null)
|
||||
throw new RuntimeOperationsException(new
|
||||
IllegalArgumentException(), "Null loader passed in parameter");
|
||||
|
||||
// Retrieve the class loader from the repository
|
||||
ClassLoader loader = null;
|
||||
synchronized (this) {
|
||||
loader = getClassLoader(aLoader);
|
||||
}
|
||||
if (loader == null) {
|
||||
throw new InstanceNotFoundException("The loader named " +
|
||||
aLoader + " is not registered in the MBeanServer");
|
||||
}
|
||||
return findClass(className,loader);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return an array of Class corresponding to the given signature, using
|
||||
* the specified class loader.
|
||||
*/
|
||||
public Class<?>[] findSignatureClasses(String signature[],
|
||||
ClassLoader loader)
|
||||
throws ReflectionException {
|
||||
|
||||
if (signature == null) return null;
|
||||
final ClassLoader aLoader = loader;
|
||||
final int length= signature.length;
|
||||
final Class<?> tab[]=new Class<?>[length];
|
||||
|
||||
if (length == 0) return tab;
|
||||
try {
|
||||
for (int i= 0; i < length; i++) {
|
||||
// Start handling primitive types (int. boolean and so
|
||||
// forth)
|
||||
//
|
||||
|
||||
final Class<?> primCla = primitiveClasses.get(signature[i]);
|
||||
if (primCla != null) {
|
||||
tab[i] = primCla;
|
||||
continue;
|
||||
}
|
||||
|
||||
ReflectUtil.checkPackageAccess(signature[i]);
|
||||
// Ok we do not have a primitive type ! We need to build
|
||||
// the signature of the method
|
||||
//
|
||||
if (aLoader != null) {
|
||||
// We need to load the class through the class
|
||||
// loader of the target object.
|
||||
//
|
||||
tab[i] = Class.forName(signature[i], false, aLoader);
|
||||
} else {
|
||||
// Load through the default class loader
|
||||
//
|
||||
tab[i] = findClass(signature[i],
|
||||
this.getClass().getClassLoader());
|
||||
}
|
||||
}
|
||||
} catch (ClassNotFoundException e) {
|
||||
if (MBEANSERVER_LOGGER.isLoggable(Level.FINEST)) {
|
||||
MBEANSERVER_LOGGER.logp(Level.FINEST,
|
||||
MBeanInstantiator.class.getName(),
|
||||
"findSignatureClasses",
|
||||
"The parameter class could not be found", e);
|
||||
}
|
||||
throw new ReflectionException(e,
|
||||
"The parameter class could not be found");
|
||||
} catch (RuntimeException e) {
|
||||
if (MBEANSERVER_LOGGER.isLoggable(Level.FINEST)) {
|
||||
MBEANSERVER_LOGGER.logp(Level.FINEST,
|
||||
MBeanInstantiator.class.getName(),
|
||||
"findSignatureClasses",
|
||||
"Unexpected exception", e);
|
||||
}
|
||||
throw e;
|
||||
}
|
||||
return tab;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Instantiates an object given its class, using its empty constructor.
|
||||
* The call returns a reference to the newly created object.
|
||||
*/
|
||||
public Object instantiate(Class<?> theClass)
|
||||
throws ReflectionException, MBeanException {
|
||||
|
||||
checkMBeanPermission(theClass, null, null, "instantiate");
|
||||
|
||||
Object moi;
|
||||
|
||||
// ------------------------------
|
||||
// ------------------------------
|
||||
Constructor<?> cons = findConstructor(theClass, null);
|
||||
if (cons == null) {
|
||||
throw new ReflectionException(new
|
||||
NoSuchMethodException("No such constructor"));
|
||||
}
|
||||
// Instantiate the new object
|
||||
try {
|
||||
ReflectUtil.checkPackageAccess(theClass);
|
||||
ensureClassAccess(theClass);
|
||||
moi= cons.newInstance();
|
||||
} catch (InvocationTargetException e) {
|
||||
// Wrap the exception.
|
||||
Throwable t = e.getTargetException();
|
||||
if (t instanceof RuntimeException) {
|
||||
throw new RuntimeMBeanException((RuntimeException)t,
|
||||
"RuntimeException thrown in the MBean's empty constructor");
|
||||
} else if (t instanceof Error) {
|
||||
throw new RuntimeErrorException((Error) t,
|
||||
"Error thrown in the MBean's empty constructor");
|
||||
} else {
|
||||
throw new MBeanException((Exception) t,
|
||||
"Exception thrown in the MBean's empty constructor");
|
||||
}
|
||||
} catch (NoSuchMethodError error) {
|
||||
throw new ReflectionException(new
|
||||
NoSuchMethodException("No constructor"),
|
||||
"No such constructor");
|
||||
} catch (InstantiationException e) {
|
||||
throw new ReflectionException(e,
|
||||
"Exception thrown trying to invoke the MBean's empty constructor");
|
||||
} catch (IllegalAccessException e) {
|
||||
throw new ReflectionException(e,
|
||||
"Exception thrown trying to invoke the MBean's empty constructor");
|
||||
} catch (IllegalArgumentException e) {
|
||||
throw new ReflectionException(e,
|
||||
"Exception thrown trying to invoke the MBean's empty constructor");
|
||||
}
|
||||
return moi;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Instantiates an object given its class, the parameters and
|
||||
* signature of its constructor The call returns a reference to
|
||||
* the newly created object.
|
||||
*/
|
||||
public Object instantiate(Class<?> theClass, Object params[],
|
||||
String signature[], ClassLoader loader)
|
||||
throws ReflectionException, MBeanException {
|
||||
|
||||
checkMBeanPermission(theClass, null, null, "instantiate");
|
||||
|
||||
// Instantiate the new object
|
||||
// ------------------------------
|
||||
// ------------------------------
|
||||
final Class<?>[] tab;
|
||||
Object moi;
|
||||
try {
|
||||
// Build the signature of the method
|
||||
//
|
||||
ClassLoader aLoader= theClass.getClassLoader();
|
||||
// Build the signature of the method
|
||||
//
|
||||
tab =
|
||||
((signature == null)?null:
|
||||
findSignatureClasses(signature,aLoader));
|
||||
}
|
||||
// Exception IllegalArgumentException raised in Jdk1.1.8
|
||||
catch (IllegalArgumentException e) {
|
||||
throw new ReflectionException(e,
|
||||
"The constructor parameter classes could not be loaded");
|
||||
}
|
||||
|
||||
// Query the metadata service to get the right constructor
|
||||
Constructor<?> cons = findConstructor(theClass, tab);
|
||||
|
||||
if (cons == null) {
|
||||
throw new ReflectionException(new
|
||||
NoSuchMethodException("No such constructor"));
|
||||
}
|
||||
try {
|
||||
ReflectUtil.checkPackageAccess(theClass);
|
||||
ensureClassAccess(theClass);
|
||||
moi = cons.newInstance(params);
|
||||
}
|
||||
catch (NoSuchMethodError error) {
|
||||
throw new ReflectionException(new
|
||||
NoSuchMethodException("No such constructor found"),
|
||||
"No such constructor" );
|
||||
}
|
||||
catch (InstantiationException e) {
|
||||
throw new ReflectionException(e,
|
||||
"Exception thrown trying to invoke the MBean's constructor");
|
||||
}
|
||||
catch (IllegalAccessException e) {
|
||||
throw new ReflectionException(e,
|
||||
"Exception thrown trying to invoke the MBean's constructor");
|
||||
}
|
||||
catch (InvocationTargetException e) {
|
||||
// Wrap the exception.
|
||||
Throwable th = e.getTargetException();
|
||||
if (th instanceof RuntimeException) {
|
||||
throw new RuntimeMBeanException((RuntimeException)th,
|
||||
"RuntimeException thrown in the MBean's constructor");
|
||||
} else if (th instanceof Error) {
|
||||
throw new RuntimeErrorException((Error) th,
|
||||
"Error thrown in the MBean's constructor");
|
||||
} else {
|
||||
throw new MBeanException((Exception) th,
|
||||
"Exception thrown in the MBean's constructor");
|
||||
}
|
||||
}
|
||||
return moi;
|
||||
}
|
||||
|
||||
/**
|
||||
* De-serializes a byte array in the context of a classloader.
|
||||
*
|
||||
* @param loader the classloader to use for de-serialization
|
||||
* @param data The byte array to be de-sererialized.
|
||||
*
|
||||
* @return The de-serialized object stream.
|
||||
*
|
||||
* @exception OperationsException Any of the usual Input/Output related
|
||||
* exceptions.
|
||||
*/
|
||||
public ObjectInputStream deserialize(ClassLoader loader, byte[] data)
|
||||
throws OperationsException {
|
||||
|
||||
// Check parameter validity
|
||||
if (data == null) {
|
||||
throw new RuntimeOperationsException(new
|
||||
IllegalArgumentException(), "Null data passed in parameter");
|
||||
}
|
||||
if (data.length == 0) {
|
||||
throw new RuntimeOperationsException(new
|
||||
IllegalArgumentException(), "Empty data passed in parameter");
|
||||
}
|
||||
|
||||
// Object deserialization
|
||||
ByteArrayInputStream bIn;
|
||||
ObjectInputStream objIn;
|
||||
|
||||
bIn = new ByteArrayInputStream(data);
|
||||
try {
|
||||
objIn = new ObjectInputStreamWithLoader(bIn,loader);
|
||||
} catch (IOException e) {
|
||||
throw new OperationsException(
|
||||
"An IOException occurred trying to de-serialize the data");
|
||||
}
|
||||
|
||||
return objIn;
|
||||
}
|
||||
|
||||
/**
|
||||
* De-serializes a byte array in the context of a given MBean class loader.
|
||||
* <P>The class loader is the one that loaded the class with name
|
||||
* "className".
|
||||
* <P>The name of the class loader to be used for loading the specified
|
||||
* class is specified. If null, a default one has to be provided (for a
|
||||
* MBean Server, its own class loader will be used).
|
||||
*
|
||||
* @param className The name of the class whose class loader should
|
||||
* be used for the de-serialization.
|
||||
* @param data The byte array to be de-sererialized.
|
||||
* @param loaderName The name of the class loader to be used for loading
|
||||
* the specified class. If null, a default one has to be provided (for a
|
||||
* MBean Server, its own class loader will be used).
|
||||
*
|
||||
* @return The de-serialized object stream.
|
||||
*
|
||||
* @exception InstanceNotFoundException The specified class loader MBean is
|
||||
* not found.
|
||||
* @exception OperationsException Any of the usual Input/Output related
|
||||
* exceptions.
|
||||
* @exception ReflectionException The specified class could not be loaded
|
||||
* by the specified class loader.
|
||||
*/
|
||||
public ObjectInputStream deserialize(String className,
|
||||
ObjectName loaderName,
|
||||
byte[] data,
|
||||
ClassLoader loader)
|
||||
throws InstanceNotFoundException,
|
||||
OperationsException,
|
||||
ReflectionException {
|
||||
|
||||
// Check parameter validity
|
||||
if (data == null) {
|
||||
throw new RuntimeOperationsException(new
|
||||
IllegalArgumentException(), "Null data passed in parameter");
|
||||
}
|
||||
if (data.length == 0) {
|
||||
throw new RuntimeOperationsException(new
|
||||
IllegalArgumentException(), "Empty data passed in parameter");
|
||||
}
|
||||
if (className == null) {
|
||||
throw new RuntimeOperationsException(new
|
||||
IllegalArgumentException(), "Null className passed in parameter");
|
||||
}
|
||||
|
||||
ReflectUtil.checkPackageAccess(className);
|
||||
Class<?> theClass;
|
||||
if (loaderName == null) {
|
||||
// Load the class using the agent class loader
|
||||
theClass = findClass(className, loader);
|
||||
|
||||
} else {
|
||||
// Get the class loader MBean
|
||||
try {
|
||||
ClassLoader instance = null;
|
||||
|
||||
instance = getClassLoader(loaderName);
|
||||
if (instance == null)
|
||||
throw new ClassNotFoundException(className);
|
||||
theClass = Class.forName(className, false, instance);
|
||||
}
|
||||
catch (ClassNotFoundException e) {
|
||||
throw new ReflectionException(e,
|
||||
"The MBean class could not be loaded by the " +
|
||||
loaderName.toString() + " class loader");
|
||||
}
|
||||
}
|
||||
|
||||
// Object deserialization
|
||||
ByteArrayInputStream bIn;
|
||||
ObjectInputStream objIn;
|
||||
|
||||
bIn = new ByteArrayInputStream(data);
|
||||
try {
|
||||
objIn = new ObjectInputStreamWithLoader(bIn,
|
||||
theClass.getClassLoader());
|
||||
} catch (IOException e) {
|
||||
throw new OperationsException(
|
||||
"An IOException occurred trying to de-serialize the data");
|
||||
}
|
||||
|
||||
return objIn;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Instantiates an object using the list of all class loaders registered
|
||||
* in the MBean Interceptor
|
||||
* (using its {@link javax.management.loading.ClassLoaderRepository}).
|
||||
* <P>The object's class should have a public constructor.
|
||||
* <P>It returns a reference to the newly created object.
|
||||
* <P>The newly created object is not registered in the MBean Interceptor.
|
||||
*
|
||||
* @param className The class name of the object to be instantiated.
|
||||
*
|
||||
* @return The newly instantiated object.
|
||||
*
|
||||
* @exception ReflectionException Wraps a
|
||||
* <CODE>java.lang.ClassNotFoundException</CODE> or the
|
||||
* <CODE>java.lang.Exception</CODE> that occurred when trying to invoke the
|
||||
* object's constructor.
|
||||
* @exception MBeanException The constructor of the object has thrown an
|
||||
* exception
|
||||
* @exception RuntimeOperationsException Wraps a
|
||||
* <CODE>java.lang.IllegalArgumentException</CODE>: the className passed in
|
||||
* parameter is null.
|
||||
*/
|
||||
public Object instantiate(String className)
|
||||
throws ReflectionException,
|
||||
MBeanException {
|
||||
|
||||
return instantiate(className, (Object[]) null, (String[]) null, null);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Instantiates an object using the class Loader specified by its
|
||||
* <CODE>ObjectName</CODE>.
|
||||
* <P>If the loader name is null, a default one has to be provided (for a
|
||||
* MBean Server, the ClassLoader that loaded it will be used).
|
||||
* <P>The object's class should have a public constructor.
|
||||
* <P>It returns a reference to the newly created object.
|
||||
* <P>The newly created object is not registered in the MBean Interceptor.
|
||||
*
|
||||
* @param className The class name of the MBean to be instantiated.
|
||||
* @param loaderName The object name of the class loader to be used.
|
||||
*
|
||||
* @return The newly instantiated object.
|
||||
*
|
||||
* @exception ReflectionException Wraps a
|
||||
* <CODE>java.lang.ClassNotFoundException</CODE> or the
|
||||
* <CODE>java.lang.Exception</CODE> that occurred when trying to invoke the
|
||||
* object's constructor.
|
||||
* @exception MBeanException The constructor of the object has thrown an
|
||||
* exception.
|
||||
* @exception InstanceNotFoundException The specified class loader is not
|
||||
* registered in the MBeanServerInterceptor.
|
||||
* @exception RuntimeOperationsException Wraps a
|
||||
* <CODE>java.lang.IllegalArgumentException</CODE>: the className passed in
|
||||
* parameter is null.
|
||||
*/
|
||||
public Object instantiate(String className, ObjectName loaderName,
|
||||
ClassLoader loader)
|
||||
throws ReflectionException, MBeanException,
|
||||
InstanceNotFoundException {
|
||||
|
||||
return instantiate(className, loaderName, (Object[]) null,
|
||||
(String[]) null, loader);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Instantiates an object using the list of all class loaders registered
|
||||
* in the MBean server
|
||||
* (using its {@link javax.management.loading.ClassLoaderRepository}).
|
||||
* <P>The object's class should have a public constructor.
|
||||
* <P>The call returns a reference to the newly created object.
|
||||
* <P>The newly created object is not registered in the MBean Interceptor.
|
||||
*
|
||||
* @param className The class name of the object to be instantiated.
|
||||
* @param params An array containing the parameters of the constructor to
|
||||
* be invoked.
|
||||
* @param signature An array containing the signature of the constructor to
|
||||
* be invoked.
|
||||
*
|
||||
* @return The newly instantiated object.
|
||||
*
|
||||
* @exception ReflectionException Wraps a
|
||||
* <CODE>java.lang.ClassNotFoundException</CODE> or the
|
||||
* <CODE>java.lang.Exception</CODE> that occurred when trying to invoke the
|
||||
* object's constructor.
|
||||
* @exception MBeanException The constructor of the object has thrown an
|
||||
* exception
|
||||
* @exception RuntimeOperationsException Wraps a
|
||||
* <CODE>java.lang.IllegalArgumentException</CODE>: the className passed in
|
||||
* parameter is null.
|
||||
*/
|
||||
public Object instantiate(String className,
|
||||
Object params[],
|
||||
String signature[],
|
||||
ClassLoader loader)
|
||||
throws ReflectionException,
|
||||
MBeanException {
|
||||
|
||||
Class<?> theClass = findClassWithDefaultLoaderRepository(className);
|
||||
return instantiate(theClass, params, signature, loader);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Instantiates an object. The class loader to be used is identified by its
|
||||
* object name.
|
||||
* <P>If the object name of the loader is null, a default has to be
|
||||
* provided (for example, for a MBean Server, the ClassLoader that loaded
|
||||
* it will be used).
|
||||
* <P>The object's class should have a public constructor.
|
||||
* <P>The call returns a reference to the newly created object.
|
||||
* <P>The newly created object is not registered in the MBean server.
|
||||
*
|
||||
* @param className The class name of the object to be instantiated.
|
||||
* @param params An array containing the parameters of the constructor to
|
||||
* be invoked.
|
||||
* @param signature An array containing the signature of the constructor to
|
||||
* be invoked.
|
||||
* @param loaderName The object name of the class loader to be used.
|
||||
*
|
||||
* @return The newly instantiated object.
|
||||
*
|
||||
* @exception ReflectionException Wraps a
|
||||
* <CODE>java.lang.ClassNotFoundException</CODE> or the
|
||||
* <CODE>java.lang.Exception</CODE> that occurred when trying to invoke the
|
||||
* object's constructor.
|
||||
* @exception MBeanException The constructor of the object has thrown an
|
||||
* exception
|
||||
* @exception InstanceNotFoundException The specified class loader is not
|
||||
* registered in the MBean Interceptor.
|
||||
* @exception RuntimeOperationsException Wraps a
|
||||
* <CODE>java.lang.IllegalArgumentException</CODE>: the className passed in
|
||||
* parameter is null.
|
||||
*/
|
||||
public Object instantiate(String className,
|
||||
ObjectName loaderName,
|
||||
Object params[],
|
||||
String signature[],
|
||||
ClassLoader loader)
|
||||
throws ReflectionException,
|
||||
MBeanException,
|
||||
InstanceNotFoundException {
|
||||
|
||||
// ------------------------------
|
||||
// ------------------------------
|
||||
Class<?> theClass;
|
||||
|
||||
if (loaderName == null) {
|
||||
theClass = findClass(className, loader);
|
||||
} else {
|
||||
theClass = findClass(className, loaderName);
|
||||
}
|
||||
return instantiate(theClass, params, signature, loader);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return the Default Loader Repository used by this instantiator object.
|
||||
**/
|
||||
public ModifiableClassLoaderRepository getClassLoaderRepository() {
|
||||
checkMBeanPermission((String)null, null, null, "getClassLoaderRepository");
|
||||
return clr;
|
||||
}
|
||||
|
||||
/**
|
||||
* Load a class with the specified loader, or with this object
|
||||
* class loader if the specified loader is null.
|
||||
**/
|
||||
static Class<?> loadClass(String className, ClassLoader loader)
|
||||
throws ReflectionException {
|
||||
Class<?> theClass;
|
||||
if (className == null) {
|
||||
throw new RuntimeOperationsException(new
|
||||
IllegalArgumentException("The class name cannot be null"),
|
||||
"Exception occurred during object instantiation");
|
||||
}
|
||||
ReflectUtil.checkPackageAccess(className);
|
||||
try {
|
||||
if (loader == null)
|
||||
loader = MBeanInstantiator.class.getClassLoader();
|
||||
if (loader != null) {
|
||||
theClass = Class.forName(className, false, loader);
|
||||
} else {
|
||||
theClass = Class.forName(className);
|
||||
}
|
||||
} catch (ClassNotFoundException e) {
|
||||
throw new ReflectionException(e,
|
||||
"The MBean class could not be loaded");
|
||||
}
|
||||
return theClass;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Load the classes specified in the signature with the given loader,
|
||||
* or with this object class loader.
|
||||
**/
|
||||
static Class<?>[] loadSignatureClasses(String signature[],
|
||||
ClassLoader loader)
|
||||
throws ReflectionException {
|
||||
|
||||
if (signature == null) return null;
|
||||
final ClassLoader aLoader =
|
||||
(loader==null?MBeanInstantiator.class.getClassLoader():loader);
|
||||
final int length= signature.length;
|
||||
final Class<?> tab[]=new Class<?>[length];
|
||||
|
||||
if (length == 0) return tab;
|
||||
try {
|
||||
for (int i= 0; i < length; i++) {
|
||||
// Start handling primitive types (int. boolean and so
|
||||
// forth)
|
||||
//
|
||||
|
||||
final Class<?> primCla = primitiveClasses.get(signature[i]);
|
||||
if (primCla != null) {
|
||||
tab[i] = primCla;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Ok we do not have a primitive type ! We need to build
|
||||
// the signature of the method
|
||||
//
|
||||
// We need to load the class through the class
|
||||
// loader of the target object.
|
||||
//
|
||||
ReflectUtil.checkPackageAccess(signature[i]);
|
||||
tab[i] = Class.forName(signature[i], false, aLoader);
|
||||
}
|
||||
} catch (ClassNotFoundException e) {
|
||||
if (MBEANSERVER_LOGGER.isLoggable(Level.FINEST)) {
|
||||
MBEANSERVER_LOGGER.logp(Level.FINEST,
|
||||
MBeanInstantiator.class.getName(),
|
||||
"findSignatureClasses",
|
||||
"The parameter class could not be found", e);
|
||||
}
|
||||
throw new ReflectionException(e,
|
||||
"The parameter class could not be found");
|
||||
} catch (RuntimeException e) {
|
||||
if (MBEANSERVER_LOGGER.isLoggable(Level.FINEST)) {
|
||||
MBEANSERVER_LOGGER.logp(Level.FINEST,
|
||||
MBeanInstantiator.class.getName(),
|
||||
"findSignatureClasses",
|
||||
"Unexpected exception", e);
|
||||
}
|
||||
throw e;
|
||||
}
|
||||
return tab;
|
||||
}
|
||||
|
||||
private Constructor<?> findConstructor(Class<?> c, Class<?>[] params) {
|
||||
try {
|
||||
return ConstructorUtil.getConstructor(c, params);
|
||||
} catch (Exception e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static final Map<String, Class<?>> primitiveClasses = Util.newMap();
|
||||
static {
|
||||
for (Class<?> c : new Class<?>[] {byte.class, short.class, int.class,
|
||||
long.class, float.class, double.class,
|
||||
char.class, boolean.class})
|
||||
primitiveClasses.put(c.getName(), c);
|
||||
}
|
||||
|
||||
private static void checkMBeanPermission(Class<?> clazz,
|
||||
String member,
|
||||
ObjectName objectName,
|
||||
String actions) {
|
||||
if (clazz != null) {
|
||||
checkMBeanPermission(clazz.getName(), member, objectName, actions);
|
||||
}
|
||||
}
|
||||
|
||||
private static void checkMBeanPermission(String classname,
|
||||
String member,
|
||||
ObjectName objectName,
|
||||
String actions)
|
||||
throws SecurityException {
|
||||
SecurityManager sm = System.getSecurityManager();
|
||||
if (sm != null) {
|
||||
Permission perm = new MBeanPermission(classname,
|
||||
member,
|
||||
objectName,
|
||||
actions);
|
||||
sm.checkPermission(perm);
|
||||
}
|
||||
}
|
||||
|
||||
private static void ensureClassAccess(Class clazz)
|
||||
throws IllegalAccessException
|
||||
{
|
||||
int mod = clazz.getModifiers();
|
||||
if (!Modifier.isPublic(mod)) {
|
||||
throw new IllegalAccessException("Class is not public and can't be instantiated");
|
||||
}
|
||||
}
|
||||
|
||||
private ClassLoader getClassLoader(final ObjectName name) {
|
||||
if(clr == null){
|
||||
return null;
|
||||
}
|
||||
// Restrict to getClassLoader permission only
|
||||
Permissions permissions = new Permissions();
|
||||
permissions.add(new MBeanPermission("*", null, name, "getClassLoader"));
|
||||
ProtectionDomain protectionDomain = new ProtectionDomain(null, permissions);
|
||||
ProtectionDomain[] domains = {protectionDomain};
|
||||
AccessControlContext ctx = new AccessControlContext(domains);
|
||||
ClassLoader loader = AccessController.doPrivileged(new PrivilegedAction<ClassLoader>() {
|
||||
public ClassLoader run() {
|
||||
return clr.getClassLoader(name);
|
||||
}
|
||||
}, ctx);
|
||||
return loader;
|
||||
}
|
||||
}
|
||||
471
jdkSrc/jdk8/com/sun/jmx/mbeanserver/MBeanIntrospector.java
Normal file
471
jdkSrc/jdk8/com/sun/jmx/mbeanserver/MBeanIntrospector.java
Normal file
@@ -0,0 +1,471 @@
|
||||
/*
|
||||
* Copyright (c) 2005, 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 com.sun.jmx.mbeanserver;
|
||||
|
||||
|
||||
import static com.sun.jmx.mbeanserver.Util.*;
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.lang.reflect.Array;
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.WeakHashMap;
|
||||
|
||||
import javax.management.Descriptor;
|
||||
import javax.management.ImmutableDescriptor;
|
||||
import javax.management.IntrospectionException;
|
||||
import javax.management.InvalidAttributeValueException;
|
||||
import javax.management.MBeanAttributeInfo;
|
||||
import javax.management.MBeanConstructorInfo;
|
||||
import javax.management.MBeanException;
|
||||
import javax.management.MBeanInfo;
|
||||
import javax.management.MBeanNotificationInfo;
|
||||
import javax.management.MBeanOperationInfo;
|
||||
import javax.management.NotCompliantMBeanException;
|
||||
import javax.management.NotificationBroadcaster;
|
||||
import javax.management.ReflectionException;
|
||||
import sun.reflect.misc.ReflectUtil;
|
||||
|
||||
/**
|
||||
* An introspector for MBeans of a certain type. There is one instance
|
||||
* of this class for Standard MBeans, and one for every MXBeanMappingFactory;
|
||||
* these two cases correspond to the two concrete subclasses of this abstract
|
||||
* class.
|
||||
*
|
||||
* @param <M> the representation of methods for this kind of MBean:
|
||||
* Method for Standard MBeans, ConvertingMethod for MXBeans.
|
||||
*
|
||||
* @since 1.6
|
||||
*/
|
||||
/*
|
||||
* Using a type parameter <M> allows us to deal with the fact that
|
||||
* Method and ConvertingMethod have no useful common ancestor, on
|
||||
* which we could call getName, getGenericReturnType, etc. A simpler approach
|
||||
* would be to wrap every Method in an object that does have a common
|
||||
* ancestor with ConvertingMethod. But that would mean an extra object
|
||||
* for every Method in every Standard MBean interface.
|
||||
*/
|
||||
abstract class MBeanIntrospector<M> {
|
||||
static final class PerInterfaceMap<M>
|
||||
extends WeakHashMap<Class<?>, WeakReference<PerInterface<M>>> {}
|
||||
|
||||
/** The map from interface to PerInterface for this type of MBean. */
|
||||
abstract PerInterfaceMap<M> getPerInterfaceMap();
|
||||
/**
|
||||
* The map from concrete implementation class and interface to
|
||||
* MBeanInfo for this type of MBean.
|
||||
*/
|
||||
abstract MBeanInfoMap getMBeanInfoMap();
|
||||
|
||||
/** Make an interface analyzer for this type of MBean. */
|
||||
abstract MBeanAnalyzer<M> getAnalyzer(Class<?> mbeanInterface)
|
||||
throws NotCompliantMBeanException;
|
||||
|
||||
/** True if MBeans with this kind of introspector are MXBeans. */
|
||||
abstract boolean isMXBean();
|
||||
|
||||
/** Find the M corresponding to the given Method. */
|
||||
abstract M mFrom(Method m);
|
||||
|
||||
/** Get the name of this method. */
|
||||
abstract String getName(M m);
|
||||
|
||||
/**
|
||||
* Get the return type of this method. This is the return type
|
||||
* of a method in a Java interface, so for MXBeans it is the
|
||||
* declared Java type, not the mapped Open Type.
|
||||
*/
|
||||
abstract Type getGenericReturnType(M m);
|
||||
|
||||
/**
|
||||
* Get the parameter types of this method in the Java interface
|
||||
* it came from.
|
||||
*/
|
||||
abstract Type[] getGenericParameterTypes(M m);
|
||||
|
||||
/**
|
||||
* Get the signature of this method as a caller would have to supply
|
||||
* it in MBeanServer.invoke. For MXBeans, the named types will be
|
||||
* the mapped Open Types for the parameters.
|
||||
*/
|
||||
abstract String[] getSignature(M m);
|
||||
|
||||
/**
|
||||
* Check that this method is valid. For example, a method in an
|
||||
* MXBean interface is not valid if one of its parameters cannot be
|
||||
* mapped to an Open Type.
|
||||
*/
|
||||
abstract void checkMethod(M m);
|
||||
|
||||
/**
|
||||
* Invoke the method with the given target and arguments.
|
||||
*
|
||||
* @param cookie Additional information about the target. For an
|
||||
* MXBean, this is the MXBeanLookup associated with the MXBean.
|
||||
*/
|
||||
/*
|
||||
* It would be cleaner if the type of the cookie were a
|
||||
* type parameter to this class, but that would involve a lot of
|
||||
* messy type parameter propagation just to avoid a couple of casts.
|
||||
*/
|
||||
abstract Object invokeM2(M m, Object target, Object[] args, Object cookie)
|
||||
throws InvocationTargetException, IllegalAccessException,
|
||||
MBeanException;
|
||||
|
||||
/**
|
||||
* Test whether the given value is valid for the given parameter of this
|
||||
* M.
|
||||
*/
|
||||
abstract boolean validParameter(M m, Object value, int paramNo,
|
||||
Object cookie);
|
||||
|
||||
/**
|
||||
* Construct an MBeanAttributeInfo for the given attribute based on the
|
||||
* given getter and setter. One but not both of the getter and setter
|
||||
* may be null.
|
||||
*/
|
||||
abstract MBeanAttributeInfo getMBeanAttributeInfo(String attributeName,
|
||||
M getter, M setter);
|
||||
/**
|
||||
* Construct an MBeanOperationInfo for the given operation based on
|
||||
* the M it was derived from.
|
||||
*/
|
||||
abstract MBeanOperationInfo getMBeanOperationInfo(String operationName,
|
||||
M operation);
|
||||
|
||||
/**
|
||||
* Get a Descriptor containing fields that MBeans of this kind will
|
||||
* always have. For example, MXBeans will always have "mxbean=true".
|
||||
*/
|
||||
abstract Descriptor getBasicMBeanDescriptor();
|
||||
|
||||
/**
|
||||
* Get a Descriptor containing additional fields beyond the ones
|
||||
* from getBasicMBeanDescriptor that MBeans whose concrete class
|
||||
* is resourceClass will always have.
|
||||
*/
|
||||
abstract Descriptor getMBeanDescriptor(Class<?> resourceClass);
|
||||
|
||||
/**
|
||||
* Get the methods to be analyzed to build the MBean interface.
|
||||
*/
|
||||
final List<Method> getMethods(final Class<?> mbeanType) {
|
||||
ReflectUtil.checkPackageAccess(mbeanType);
|
||||
return Arrays.asList(mbeanType.getMethods());
|
||||
}
|
||||
|
||||
final PerInterface<M> getPerInterface(Class<?> mbeanInterface)
|
||||
throws NotCompliantMBeanException {
|
||||
PerInterfaceMap<M> map = getPerInterfaceMap();
|
||||
synchronized (map) {
|
||||
WeakReference<PerInterface<M>> wr = map.get(mbeanInterface);
|
||||
PerInterface<M> pi = (wr == null) ? null : wr.get();
|
||||
if (pi == null) {
|
||||
try {
|
||||
MBeanAnalyzer<M> analyzer = getAnalyzer(mbeanInterface);
|
||||
MBeanInfo mbeanInfo =
|
||||
makeInterfaceMBeanInfo(mbeanInterface, analyzer);
|
||||
pi = new PerInterface<M>(mbeanInterface, this, analyzer,
|
||||
mbeanInfo);
|
||||
wr = new WeakReference<PerInterface<M>>(pi);
|
||||
map.put(mbeanInterface, wr);
|
||||
} catch (Exception x) {
|
||||
throw Introspector.throwException(mbeanInterface,x);
|
||||
}
|
||||
}
|
||||
return pi;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Make the MBeanInfo skeleton for the given MBean interface using
|
||||
* the given analyzer. This will never be the MBeanInfo of any real
|
||||
* MBean (because the getClassName() must be a concrete class), but
|
||||
* its MBeanAttributeInfo[] and MBeanOperationInfo[] can be inserted
|
||||
* into such an MBeanInfo, and its Descriptor can be the basis for
|
||||
* the MBeanInfo's Descriptor.
|
||||
*/
|
||||
private MBeanInfo makeInterfaceMBeanInfo(Class<?> mbeanInterface,
|
||||
MBeanAnalyzer<M> analyzer) {
|
||||
final MBeanInfoMaker maker = new MBeanInfoMaker();
|
||||
analyzer.visit(maker);
|
||||
final String description =
|
||||
"Information on the management interface of the MBean";
|
||||
return maker.makeMBeanInfo(mbeanInterface, description);
|
||||
}
|
||||
|
||||
/** True if the given getter and setter are consistent. */
|
||||
final boolean consistent(M getter, M setter) {
|
||||
return (getter == null || setter == null ||
|
||||
getGenericReturnType(getter).equals(getGenericParameterTypes(setter)[0]));
|
||||
}
|
||||
|
||||
/**
|
||||
* Invoke the given M on the given target with the given args and cookie.
|
||||
* Wrap exceptions appropriately.
|
||||
*/
|
||||
final Object invokeM(M m, Object target, Object[] args, Object cookie)
|
||||
throws MBeanException, ReflectionException {
|
||||
try {
|
||||
return invokeM2(m, target, args, cookie);
|
||||
} catch (InvocationTargetException e) {
|
||||
unwrapInvocationTargetException(e);
|
||||
throw new RuntimeException(e); // not reached
|
||||
} catch (IllegalAccessException e) {
|
||||
throw new ReflectionException(e, e.toString());
|
||||
}
|
||||
/* We do not catch and wrap RuntimeException or Error,
|
||||
* because we're in a DynamicMBean, so the logic for DynamicMBeans
|
||||
* will do the wrapping.
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* Invoke the given setter on the given target with the given argument
|
||||
* and cookie. Wrap exceptions appropriately.
|
||||
*/
|
||||
/* If the value is of the wrong type for the method we are about to
|
||||
* invoke, we are supposed to throw an InvalidAttributeValueException.
|
||||
* Rather than making the check always, we invoke the method, then
|
||||
* if it throws an exception we check the type to see if that was
|
||||
* what caused the exception. The assumption is that an exception
|
||||
* from an invalid type will arise before any user method is ever
|
||||
* called (either in reflection or in OpenConverter).
|
||||
*/
|
||||
final void invokeSetter(String name, M setter, Object target, Object arg,
|
||||
Object cookie)
|
||||
throws MBeanException, ReflectionException,
|
||||
InvalidAttributeValueException {
|
||||
try {
|
||||
invokeM2(setter, target, new Object[] {arg}, cookie);
|
||||
} catch (IllegalAccessException e) {
|
||||
throw new ReflectionException(e, e.toString());
|
||||
} catch (RuntimeException e) {
|
||||
maybeInvalidParameter(name, setter, arg, cookie);
|
||||
throw e;
|
||||
} catch (InvocationTargetException e) {
|
||||
maybeInvalidParameter(name, setter, arg, cookie);
|
||||
unwrapInvocationTargetException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private void maybeInvalidParameter(String name, M setter, Object arg,
|
||||
Object cookie)
|
||||
throws InvalidAttributeValueException {
|
||||
if (!validParameter(setter, arg, 0, cookie)) {
|
||||
final String msg =
|
||||
"Invalid value for attribute " + name + ": " + arg;
|
||||
throw new InvalidAttributeValueException(msg);
|
||||
}
|
||||
}
|
||||
|
||||
static boolean isValidParameter(Method m, Object value, int paramNo) {
|
||||
Class<?> c = m.getParameterTypes()[paramNo];
|
||||
try {
|
||||
// Following is expensive but we only call this method to determine
|
||||
// if an exception is due to an incompatible parameter type.
|
||||
// Plain old c.isInstance doesn't work for primitive types.
|
||||
Object a = Array.newInstance(c, 1);
|
||||
Array.set(a, 0, value);
|
||||
return true;
|
||||
} catch (IllegalArgumentException e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private static void
|
||||
unwrapInvocationTargetException(InvocationTargetException e)
|
||||
throws MBeanException {
|
||||
Throwable t = e.getCause();
|
||||
if (t instanceof RuntimeException)
|
||||
throw (RuntimeException) t;
|
||||
else if (t instanceof Error)
|
||||
throw (Error) t;
|
||||
else
|
||||
throw new MBeanException((Exception) t,
|
||||
(t == null ? null : t.toString()));
|
||||
}
|
||||
|
||||
/** A visitor that constructs the per-interface MBeanInfo. */
|
||||
private class MBeanInfoMaker
|
||||
implements MBeanAnalyzer.MBeanVisitor<M> {
|
||||
|
||||
public void visitAttribute(String attributeName,
|
||||
M getter,
|
||||
M setter) {
|
||||
MBeanAttributeInfo mbai =
|
||||
getMBeanAttributeInfo(attributeName, getter, setter);
|
||||
|
||||
attrs.add(mbai);
|
||||
}
|
||||
|
||||
public void visitOperation(String operationName,
|
||||
M operation) {
|
||||
MBeanOperationInfo mboi =
|
||||
getMBeanOperationInfo(operationName, operation);
|
||||
|
||||
ops.add(mboi);
|
||||
}
|
||||
|
||||
/** Make an MBeanInfo based on the attributes and operations
|
||||
* found in the interface. */
|
||||
MBeanInfo makeMBeanInfo(Class<?> mbeanInterface,
|
||||
String description) {
|
||||
final MBeanAttributeInfo[] attrArray =
|
||||
attrs.toArray(new MBeanAttributeInfo[0]);
|
||||
final MBeanOperationInfo[] opArray =
|
||||
ops.toArray(new MBeanOperationInfo[0]);
|
||||
final String interfaceClassName =
|
||||
"interfaceClassName=" + mbeanInterface.getName();
|
||||
final Descriptor classNameDescriptor =
|
||||
new ImmutableDescriptor(interfaceClassName);
|
||||
final Descriptor mbeanDescriptor = getBasicMBeanDescriptor();
|
||||
final Descriptor annotatedDescriptor =
|
||||
Introspector.descriptorForElement(mbeanInterface);
|
||||
final Descriptor descriptor =
|
||||
DescriptorCache.getInstance().union(
|
||||
classNameDescriptor,
|
||||
mbeanDescriptor,
|
||||
annotatedDescriptor);
|
||||
|
||||
return new MBeanInfo(mbeanInterface.getName(),
|
||||
description,
|
||||
attrArray,
|
||||
null,
|
||||
opArray,
|
||||
null,
|
||||
descriptor);
|
||||
}
|
||||
|
||||
private final List<MBeanAttributeInfo> attrs = newList();
|
||||
private final List<MBeanOperationInfo> ops = newList();
|
||||
}
|
||||
|
||||
/*
|
||||
* Looking up the MBeanInfo for a given base class (implementation class)
|
||||
* is complicated by the fact that we may use the same base class with
|
||||
* several different explicit MBean interfaces via the
|
||||
* javax.management.StandardMBean class. It is further complicated
|
||||
* by the fact that we have to be careful not to retain a strong reference
|
||||
* to any Class object for fear we would prevent a ClassLoader from being
|
||||
* garbage-collected. So we have a first lookup from the base class
|
||||
* to a map for each interface that base class might specify giving
|
||||
* the MBeanInfo constructed for that base class and interface.
|
||||
*/
|
||||
static class MBeanInfoMap
|
||||
extends WeakHashMap<Class<?>, WeakHashMap<Class<?>, MBeanInfo>> {
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the MBeanInfo for the given resource, based on the given
|
||||
* per-interface data.
|
||||
*/
|
||||
final MBeanInfo getMBeanInfo(Object resource, PerInterface<M> perInterface) {
|
||||
MBeanInfo mbi =
|
||||
getClassMBeanInfo(resource.getClass(), perInterface);
|
||||
MBeanNotificationInfo[] notifs = findNotifications(resource);
|
||||
if (notifs == null || notifs.length == 0)
|
||||
return mbi;
|
||||
else {
|
||||
return new MBeanInfo(mbi.getClassName(),
|
||||
mbi.getDescription(),
|
||||
mbi.getAttributes(),
|
||||
mbi.getConstructors(),
|
||||
mbi.getOperations(),
|
||||
notifs,
|
||||
mbi.getDescriptor());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the basic MBeanInfo for resources of the given class and
|
||||
* per-interface data. This MBeanInfo might not be the final MBeanInfo
|
||||
* for instances of the class, because if the class is a
|
||||
* NotificationBroadcaster then each instance gets to decide what
|
||||
* MBeanNotificationInfo[] to put in its own MBeanInfo.
|
||||
*/
|
||||
final MBeanInfo getClassMBeanInfo(Class<?> resourceClass,
|
||||
PerInterface<M> perInterface) {
|
||||
MBeanInfoMap map = getMBeanInfoMap();
|
||||
synchronized (map) {
|
||||
WeakHashMap<Class<?>, MBeanInfo> intfMap = map.get(resourceClass);
|
||||
if (intfMap == null) {
|
||||
intfMap = new WeakHashMap<Class<?>, MBeanInfo>();
|
||||
map.put(resourceClass, intfMap);
|
||||
}
|
||||
Class<?> intfClass = perInterface.getMBeanInterface();
|
||||
MBeanInfo mbi = intfMap.get(intfClass);
|
||||
if (mbi == null) {
|
||||
MBeanInfo imbi = perInterface.getMBeanInfo();
|
||||
Descriptor descriptor =
|
||||
ImmutableDescriptor.union(imbi.getDescriptor(),
|
||||
getMBeanDescriptor(resourceClass));
|
||||
mbi = new MBeanInfo(resourceClass.getName(),
|
||||
imbi.getDescription(),
|
||||
imbi.getAttributes(),
|
||||
findConstructors(resourceClass),
|
||||
imbi.getOperations(),
|
||||
(MBeanNotificationInfo[]) null,
|
||||
descriptor);
|
||||
intfMap.put(intfClass, mbi);
|
||||
}
|
||||
return mbi;
|
||||
}
|
||||
}
|
||||
|
||||
static MBeanNotificationInfo[] findNotifications(Object moi) {
|
||||
if (!(moi instanceof NotificationBroadcaster))
|
||||
return null;
|
||||
MBeanNotificationInfo[] mbn =
|
||||
((NotificationBroadcaster) moi).getNotificationInfo();
|
||||
if (mbn == null)
|
||||
return null;
|
||||
MBeanNotificationInfo[] result =
|
||||
new MBeanNotificationInfo[mbn.length];
|
||||
for (int i = 0; i < mbn.length; i++) {
|
||||
MBeanNotificationInfo ni = mbn[i];
|
||||
if (ni.getClass() != MBeanNotificationInfo.class)
|
||||
ni = (MBeanNotificationInfo) ni.clone();
|
||||
result[i] = ni;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private static MBeanConstructorInfo[] findConstructors(Class<?> c) {
|
||||
Constructor<?>[] cons = c.getConstructors();
|
||||
MBeanConstructorInfo[] mbc = new MBeanConstructorInfo[cons.length];
|
||||
for (int i = 0; i < cons.length; i++) {
|
||||
final String descr = "Public constructor of the MBean";
|
||||
mbc[i] = new MBeanConstructorInfo(descr, cons[i]);
|
||||
}
|
||||
return mbc;
|
||||
}
|
||||
|
||||
}
|
||||
321
jdkSrc/jdk8/com/sun/jmx/mbeanserver/MBeanServerDelegateImpl.java
Normal file
321
jdkSrc/jdk8/com/sun/jmx/mbeanserver/MBeanServerDelegateImpl.java
Normal file
@@ -0,0 +1,321 @@
|
||||
/*
|
||||
* Copyright (c) 2002, 2006, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
package com.sun.jmx.mbeanserver;
|
||||
|
||||
import java.util.logging.Level;
|
||||
|
||||
import javax.management.Attribute;
|
||||
import javax.management.AttributeList;
|
||||
import javax.management.AttributeNotFoundException;
|
||||
import javax.management.DynamicMBean;
|
||||
import javax.management.InvalidAttributeValueException;
|
||||
import javax.management.JMRuntimeException;
|
||||
import javax.management.MBeanAttributeInfo;
|
||||
import javax.management.MBeanException;
|
||||
import javax.management.MBeanInfo;
|
||||
import javax.management.MBeanRegistration;
|
||||
import javax.management.MBeanServer;
|
||||
import javax.management.MBeanServerDelegate;
|
||||
import javax.management.ObjectName;
|
||||
import javax.management.ReflectionException;
|
||||
import javax.management.RuntimeOperationsException;
|
||||
|
||||
import static com.sun.jmx.defaults.JmxProperties.MBEANSERVER_LOGGER;
|
||||
|
||||
/**
|
||||
* This class is the MBean implementation of the MBeanServerDelegate.
|
||||
*
|
||||
* @since 1.5
|
||||
*/
|
||||
final class MBeanServerDelegateImpl
|
||||
extends MBeanServerDelegate
|
||||
implements DynamicMBean, MBeanRegistration {
|
||||
|
||||
final private static String[] attributeNames = new String[] {
|
||||
"MBeanServerId",
|
||||
"SpecificationName",
|
||||
"SpecificationVersion",
|
||||
"SpecificationVendor",
|
||||
"ImplementationName",
|
||||
"ImplementationVersion",
|
||||
"ImplementationVendor"
|
||||
};
|
||||
|
||||
private static final MBeanAttributeInfo[] attributeInfos =
|
||||
new MBeanAttributeInfo[] {
|
||||
new MBeanAttributeInfo("MBeanServerId","java.lang.String",
|
||||
"The MBean server agent identification",
|
||||
true,false,false),
|
||||
new MBeanAttributeInfo("SpecificationName","java.lang.String",
|
||||
"The full name of the JMX specification "+
|
||||
"implemented by this product.",
|
||||
true,false,false),
|
||||
new MBeanAttributeInfo("SpecificationVersion","java.lang.String",
|
||||
"The version of the JMX specification "+
|
||||
"implemented by this product.",
|
||||
true,false,false),
|
||||
new MBeanAttributeInfo("SpecificationVendor","java.lang.String",
|
||||
"The vendor of the JMX specification "+
|
||||
"implemented by this product.",
|
||||
true,false,false),
|
||||
new MBeanAttributeInfo("ImplementationName","java.lang.String",
|
||||
"The JMX implementation name "+
|
||||
"(the name of this product)",
|
||||
true,false,false),
|
||||
new MBeanAttributeInfo("ImplementationVersion","java.lang.String",
|
||||
"The JMX implementation version "+
|
||||
"(the version of this product).",
|
||||
true,false,false),
|
||||
new MBeanAttributeInfo("ImplementationVendor","java.lang.String",
|
||||
"the JMX implementation vendor "+
|
||||
"(the vendor of this product).",
|
||||
true,false,false)
|
||||
};
|
||||
|
||||
private final MBeanInfo delegateInfo;
|
||||
|
||||
public MBeanServerDelegateImpl () {
|
||||
super();
|
||||
delegateInfo =
|
||||
new MBeanInfo("javax.management.MBeanServerDelegate",
|
||||
"Represents the MBean server from the management "+
|
||||
"point of view.",
|
||||
MBeanServerDelegateImpl.attributeInfos, null,
|
||||
null,getNotificationInfo());
|
||||
}
|
||||
|
||||
final public ObjectName preRegister (MBeanServer server, ObjectName name)
|
||||
throws java.lang.Exception {
|
||||
if (name == null) return DELEGATE_NAME;
|
||||
else return name;
|
||||
}
|
||||
|
||||
final public void postRegister (Boolean registrationDone) {
|
||||
}
|
||||
|
||||
final public void preDeregister()
|
||||
throws java.lang.Exception {
|
||||
throw new IllegalArgumentException(
|
||||
"The MBeanServerDelegate MBean cannot be unregistered");
|
||||
}
|
||||
|
||||
final public void postDeregister() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtains the value of a specific attribute of the MBeanServerDelegate.
|
||||
*
|
||||
* @param attribute The name of the attribute to be retrieved
|
||||
*
|
||||
* @return The value of the attribute retrieved.
|
||||
*
|
||||
* @exception AttributeNotFoundException
|
||||
* @exception MBeanException
|
||||
* Wraps a <CODE>java.lang.Exception</CODE> thrown by the
|
||||
* MBean's getter.
|
||||
*/
|
||||
public Object getAttribute(String attribute)
|
||||
throws AttributeNotFoundException,
|
||||
MBeanException, ReflectionException {
|
||||
try {
|
||||
// attribute must not be null
|
||||
//
|
||||
if (attribute == null)
|
||||
throw new AttributeNotFoundException("null");
|
||||
|
||||
// Extract the requested attribute from file
|
||||
//
|
||||
if (attribute.equals("MBeanServerId"))
|
||||
return getMBeanServerId();
|
||||
else if (attribute.equals("SpecificationName"))
|
||||
return getSpecificationName();
|
||||
else if (attribute.equals("SpecificationVersion"))
|
||||
return getSpecificationVersion();
|
||||
else if (attribute.equals("SpecificationVendor"))
|
||||
return getSpecificationVendor();
|
||||
else if (attribute.equals("ImplementationName"))
|
||||
return getImplementationName();
|
||||
else if (attribute.equals("ImplementationVersion"))
|
||||
return getImplementationVersion();
|
||||
else if (attribute.equals("ImplementationVendor"))
|
||||
return getImplementationVendor();
|
||||
|
||||
// Unknown attribute
|
||||
//
|
||||
else
|
||||
throw new AttributeNotFoundException("null");
|
||||
|
||||
} catch (AttributeNotFoundException x) {
|
||||
throw x;
|
||||
} catch (JMRuntimeException j) {
|
||||
throw j;
|
||||
} catch (SecurityException s) {
|
||||
throw s;
|
||||
} catch (Exception x) {
|
||||
throw new MBeanException(x,"Failed to get " + attribute);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This method always fail since all MBeanServerDelegateMBean attributes
|
||||
* are read-only.
|
||||
*
|
||||
* @param attribute The identification of the attribute to
|
||||
* be set and the value it is to be set to.
|
||||
*
|
||||
* @exception AttributeNotFoundException
|
||||
*/
|
||||
public void setAttribute(Attribute attribute)
|
||||
throws AttributeNotFoundException, InvalidAttributeValueException,
|
||||
MBeanException, ReflectionException {
|
||||
|
||||
// Now we will always fail:
|
||||
// Either because the attribute is null or because it is not
|
||||
// accessible (or does not exist).
|
||||
//
|
||||
final String attname = (attribute==null?null:attribute.getName());
|
||||
if (attname == null) {
|
||||
final RuntimeException r =
|
||||
new IllegalArgumentException("Attribute name cannot be null");
|
||||
throw new RuntimeOperationsException(r,
|
||||
"Exception occurred trying to invoke the setter on the MBean");
|
||||
}
|
||||
|
||||
// This is a hack: we call getAttribute in order to generate an
|
||||
// AttributeNotFoundException if the attribute does not exist.
|
||||
//
|
||||
Object val = getAttribute(attname);
|
||||
|
||||
// If we reach this point, we know that the requested attribute
|
||||
// exists. However, since all attributes are read-only, we throw
|
||||
// an AttributeNotFoundException.
|
||||
//
|
||||
throw new AttributeNotFoundException(attname + " not accessible");
|
||||
}
|
||||
|
||||
/**
|
||||
* Makes it possible to get the values of several attributes of
|
||||
* the MBeanServerDelegate.
|
||||
*
|
||||
* @param attributes A list of the attributes to be retrieved.
|
||||
*
|
||||
* @return The list of attributes retrieved.
|
||||
*
|
||||
*/
|
||||
public AttributeList getAttributes(String[] attributes) {
|
||||
// If attributes is null, the get all attributes.
|
||||
//
|
||||
final String[] attn = (attributes==null?attributeNames:attributes);
|
||||
|
||||
// Prepare the result list.
|
||||
//
|
||||
final int len = attn.length;
|
||||
final AttributeList list = new AttributeList(len);
|
||||
|
||||
// Get each requested attribute.
|
||||
//
|
||||
for (int i=0;i<len;i++) {
|
||||
try {
|
||||
final Attribute a =
|
||||
new Attribute(attn[i],getAttribute(attn[i]));
|
||||
list.add(a);
|
||||
} catch (Exception x) {
|
||||
// Skip the attribute that couldn't be obtained.
|
||||
//
|
||||
if (MBEANSERVER_LOGGER.isLoggable(Level.FINEST)) {
|
||||
MBEANSERVER_LOGGER.logp(Level.FINEST,
|
||||
MBeanServerDelegateImpl.class.getName(),
|
||||
"getAttributes",
|
||||
"Attribute " + attn[i] + " not found");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Finally return the result.
|
||||
//
|
||||
return list;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method always return an empty list since all
|
||||
* MBeanServerDelegateMBean attributes are read-only.
|
||||
*
|
||||
* @param attributes A list of attributes: The identification of the
|
||||
* attributes to be set and the values they are to be set to.
|
||||
*
|
||||
* @return The list of attributes that were set, with their new values.
|
||||
* In fact, this method always return an empty list since all
|
||||
* MBeanServerDelegateMBean attributes are read-only.
|
||||
*/
|
||||
public AttributeList setAttributes(AttributeList attributes) {
|
||||
return new AttributeList(0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Always fails since the MBeanServerDelegate MBean has no operation.
|
||||
*
|
||||
* @param actionName The name of the action to be invoked.
|
||||
* @param params An array containing the parameters to be set when the
|
||||
* action is invoked.
|
||||
* @param signature An array containing the signature of the action.
|
||||
*
|
||||
* @return The object returned by the action, which represents
|
||||
* the result of invoking the action on the MBean specified.
|
||||
*
|
||||
* @exception MBeanException Wraps a <CODE>java.lang.Exception</CODE>
|
||||
* thrown by the MBean's invoked method.
|
||||
* @exception ReflectionException Wraps a
|
||||
* <CODE>java.lang.Exception</CODE> thrown while trying to invoke
|
||||
* the method.
|
||||
*/
|
||||
public Object invoke(String actionName, Object params[],
|
||||
String signature[])
|
||||
throws MBeanException, ReflectionException {
|
||||
// Check that operation name is not null.
|
||||
//
|
||||
if (actionName == null) {
|
||||
final RuntimeException r =
|
||||
new IllegalArgumentException("Operation name cannot be null");
|
||||
throw new RuntimeOperationsException(r,
|
||||
"Exception occurred trying to invoke the operation on the MBean");
|
||||
}
|
||||
|
||||
throw new ReflectionException(
|
||||
new NoSuchMethodException(actionName),
|
||||
"The operation with name " + actionName +
|
||||
" could not be found");
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides the MBeanInfo describing the MBeanServerDelegate.
|
||||
*
|
||||
* @return The MBeanInfo describing the MBeanServerDelegate.
|
||||
*
|
||||
*/
|
||||
public MBeanInfo getMBeanInfo() {
|
||||
return delegateInfo;
|
||||
}
|
||||
|
||||
}
|
||||
276
jdkSrc/jdk8/com/sun/jmx/mbeanserver/MBeanSupport.java
Normal file
276
jdkSrc/jdk8/com/sun/jmx/mbeanserver/MBeanSupport.java
Normal file
@@ -0,0 +1,276 @@
|
||||
/*
|
||||
* Copyright (c) 2005, 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 com.sun.jmx.mbeanserver;
|
||||
|
||||
|
||||
import javax.management.Attribute;
|
||||
import javax.management.AttributeList;
|
||||
import javax.management.AttributeNotFoundException;
|
||||
import javax.management.InvalidAttributeValueException;
|
||||
import javax.management.MBeanException;
|
||||
import javax.management.MBeanInfo;
|
||||
import javax.management.MBeanRegistration;
|
||||
import javax.management.MBeanServer;
|
||||
import javax.management.NotCompliantMBeanException;
|
||||
import javax.management.ObjectName;
|
||||
import javax.management.ReflectionException;
|
||||
import com.sun.jmx.mbeanserver.MXBeanMappingFactory;
|
||||
import sun.reflect.misc.ReflectUtil;
|
||||
|
||||
/**
|
||||
* Base class for MBeans. There is one instance of this class for
|
||||
* every Standard MBean and every MXBean. We try to limit the amount
|
||||
* of information per instance so we can handle very large numbers of
|
||||
* MBeans comfortably.
|
||||
*
|
||||
* @param <M> either Method or ConvertingMethod, for Standard MBeans
|
||||
* and MXBeans respectively.
|
||||
*
|
||||
* @since 1.6
|
||||
*/
|
||||
/*
|
||||
* We maintain a couple of caches to increase sharing between
|
||||
* different MBeans of the same type and also to reduce creation time
|
||||
* for the second and subsequent instances of the same type.
|
||||
*
|
||||
* The first cache maps from an MBean interface to a PerInterface
|
||||
* object containing information parsed out of the interface. The
|
||||
* interface is either a Standard MBean interface or an MXBean
|
||||
* interface, and there is one cache for each case.
|
||||
*
|
||||
* The PerInterface includes an MBeanInfo. This contains the
|
||||
* attributes and operations parsed out of the interface's methods,
|
||||
* plus a basic Descriptor for the interface containing at least the
|
||||
* interfaceClassName field and any fields derived from annotations on
|
||||
* the interface. This MBeanInfo can never be the MBeanInfo for any
|
||||
* actual MBean, because an MBeanInfo's getClassName() is the name of
|
||||
* a concrete class and we don't know what the class will be.
|
||||
* Furthermore a real MBeanInfo may need to add constructors and/or
|
||||
* notifications to the MBeanInfo.
|
||||
*
|
||||
* The PerInterface also contains an MBeanDispatcher which is able to
|
||||
* route getAttribute, setAttribute, and invoke to the appropriate
|
||||
* method of the interface, including doing any necessary translation
|
||||
* of parameters and return values for MXBeans.
|
||||
*
|
||||
* The PerInterface also contains the original Class for the interface.
|
||||
*
|
||||
* We need to be careful about references. When there are no MBeans
|
||||
* with a given interface, there must not be any strong references to
|
||||
* the interface Class. Otherwise it could never be garbage collected,
|
||||
* and neither could its ClassLoader or any other classes loaded by
|
||||
* its ClassLoader. Therefore the cache must wrap the PerInterface
|
||||
* in a WeakReference. Each instance of MBeanSupport has a strong
|
||||
* reference to its PerInterface, which prevents PerInterface instances
|
||||
* from being garbage-collected prematurely.
|
||||
*
|
||||
* The second cache maps from a concrete class and an MBean interface
|
||||
* that that class implements to the MBeanInfo for that class and
|
||||
* interface. (The ability to specify an interface separately comes
|
||||
* from the class StandardMBean. MBeans registered directly in the
|
||||
* MBean Server will always have the same interface here.)
|
||||
*
|
||||
* The MBeanInfo in this second cache will be the MBeanInfo from the
|
||||
* PerInterface cache for the given itnerface, but with the
|
||||
* getClassName() having the concrete class's name, and the public
|
||||
* constructors based on the concrete class's constructors. This
|
||||
* MBeanInfo can be shared between all instances of the concrete class
|
||||
* specifying the same interface, except instances that are
|
||||
* NotificationBroadcasters. NotificationBroadcasters supply the
|
||||
* MBeanNotificationInfo[] in the MBeanInfo based on the instance
|
||||
* method NotificationBroadcaster.getNotificationInfo(), so two
|
||||
* instances of the same concrete class do not necessarily have the
|
||||
* same MBeanNotificationInfo[]. Currently we do not try to detect
|
||||
* when they do, although it would probably be worthwhile doing that
|
||||
* since it is a very common case.
|
||||
*
|
||||
* Standard MBeans additionally have the property that
|
||||
* getNotificationInfo() must in principle be called every time
|
||||
* getMBeanInfo() is called for the MBean, since the returned array is
|
||||
* allowed to change over time. We attempt to reduce the cost of
|
||||
* doing this by detecting when the Standard MBean is a subclass of
|
||||
* NotificationBroadcasterSupport that does not override
|
||||
* getNotificationInfo(), meaning that the MBeanNotificationInfo[] is
|
||||
* the one that was supplied to the constructor. MXBeans do not have
|
||||
* this problem because their getNotificationInfo() method is called
|
||||
* only once.
|
||||
*
|
||||
*/
|
||||
public abstract class MBeanSupport<M>
|
||||
implements DynamicMBean2, MBeanRegistration {
|
||||
|
||||
<T> MBeanSupport(T resource, Class<T> mbeanInterfaceType)
|
||||
throws NotCompliantMBeanException {
|
||||
if (mbeanInterfaceType == null)
|
||||
throw new NotCompliantMBeanException("Null MBean interface");
|
||||
if (!mbeanInterfaceType.isInstance(resource)) {
|
||||
final String msg =
|
||||
"Resource class " + resource.getClass().getName() +
|
||||
" is not an instance of " + mbeanInterfaceType.getName();
|
||||
throw new NotCompliantMBeanException(msg);
|
||||
}
|
||||
ReflectUtil.checkPackageAccess(mbeanInterfaceType);
|
||||
this.resource = resource;
|
||||
MBeanIntrospector<M> introspector = getMBeanIntrospector();
|
||||
this.perInterface = introspector.getPerInterface(mbeanInterfaceType);
|
||||
this.mbeanInfo = introspector.getMBeanInfo(resource, perInterface);
|
||||
}
|
||||
|
||||
/** Return the appropriate introspector for this type of MBean. */
|
||||
abstract MBeanIntrospector<M> getMBeanIntrospector();
|
||||
|
||||
/**
|
||||
* Return a cookie for this MBean. This cookie will be passed to
|
||||
* MBean method invocations where it can supply additional information
|
||||
* to the invocation. For example, with MXBeans it can be used to
|
||||
* supply the MXBeanLookup context for resolving inter-MXBean references.
|
||||
*/
|
||||
abstract Object getCookie();
|
||||
|
||||
public final boolean isMXBean() {
|
||||
return perInterface.isMXBean();
|
||||
}
|
||||
|
||||
// Methods that javax.management.StandardMBean should call from its
|
||||
// preRegister and postRegister, given that it is not supposed to
|
||||
// call the contained object's preRegister etc methods even if it has them
|
||||
public abstract void register(MBeanServer mbs, ObjectName name)
|
||||
throws Exception;
|
||||
public abstract void unregister();
|
||||
|
||||
public final ObjectName preRegister(MBeanServer server, ObjectName name)
|
||||
throws Exception {
|
||||
if (resource instanceof MBeanRegistration)
|
||||
name = ((MBeanRegistration) resource).preRegister(server, name);
|
||||
return name;
|
||||
}
|
||||
|
||||
public final void preRegister2(MBeanServer server, ObjectName name)
|
||||
throws Exception {
|
||||
register(server, name);
|
||||
}
|
||||
|
||||
public final void registerFailed() {
|
||||
unregister();
|
||||
}
|
||||
|
||||
public final void postRegister(Boolean registrationDone) {
|
||||
if (resource instanceof MBeanRegistration)
|
||||
((MBeanRegistration) resource).postRegister(registrationDone);
|
||||
}
|
||||
|
||||
public final void preDeregister() throws Exception {
|
||||
if (resource instanceof MBeanRegistration)
|
||||
((MBeanRegistration) resource).preDeregister();
|
||||
}
|
||||
|
||||
public final void postDeregister() {
|
||||
// Undo any work from registration. We do this in postDeregister
|
||||
// not preDeregister, because if the user preDeregister throws an
|
||||
// exception then the MBean is not unregistered.
|
||||
try {
|
||||
unregister();
|
||||
} finally {
|
||||
if (resource instanceof MBeanRegistration)
|
||||
((MBeanRegistration) resource).postDeregister();
|
||||
}
|
||||
}
|
||||
|
||||
public final Object getAttribute(String attribute)
|
||||
throws AttributeNotFoundException,
|
||||
MBeanException,
|
||||
ReflectionException {
|
||||
return perInterface.getAttribute(resource, attribute, getCookie());
|
||||
}
|
||||
|
||||
public final AttributeList getAttributes(String[] attributes) {
|
||||
final AttributeList result = new AttributeList(attributes.length);
|
||||
for (String attrName : attributes) {
|
||||
try {
|
||||
final Object attrValue = getAttribute(attrName);
|
||||
result.add(new Attribute(attrName, attrValue));
|
||||
} catch (Exception e) {
|
||||
// OK: attribute is not included in returned list, per spec
|
||||
// XXX: log the exception
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public final void setAttribute(Attribute attribute)
|
||||
throws AttributeNotFoundException,
|
||||
InvalidAttributeValueException,
|
||||
MBeanException,
|
||||
ReflectionException {
|
||||
final String name = attribute.getName();
|
||||
final Object value = attribute.getValue();
|
||||
perInterface.setAttribute(resource, name, value, getCookie());
|
||||
}
|
||||
|
||||
public final AttributeList setAttributes(AttributeList attributes) {
|
||||
final AttributeList result = new AttributeList(attributes.size());
|
||||
for (Object attrObj : attributes) {
|
||||
// We can't use AttributeList.asList because it has side-effects
|
||||
Attribute attr = (Attribute) attrObj;
|
||||
try {
|
||||
setAttribute(attr);
|
||||
result.add(new Attribute(attr.getName(), attr.getValue()));
|
||||
} catch (Exception e) {
|
||||
// OK: attribute is not included in returned list, per spec
|
||||
// XXX: log the exception
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public final Object invoke(String operation, Object[] params,
|
||||
String[] signature)
|
||||
throws MBeanException, ReflectionException {
|
||||
return perInterface.invoke(resource, operation, params, signature,
|
||||
getCookie());
|
||||
}
|
||||
|
||||
// Overridden by StandardMBeanSupport
|
||||
public MBeanInfo getMBeanInfo() {
|
||||
return mbeanInfo;
|
||||
}
|
||||
|
||||
public final String getClassName() {
|
||||
return resource.getClass().getName();
|
||||
}
|
||||
|
||||
public final Object getResource() {
|
||||
return resource;
|
||||
}
|
||||
|
||||
public final Class<?> getMBeanInterface() {
|
||||
return perInterface.getMBeanInterface();
|
||||
}
|
||||
|
||||
private final MBeanInfo mbeanInfo;
|
||||
private final Object resource;
|
||||
private final PerInterface<M> perInterface;
|
||||
}
|
||||
365
jdkSrc/jdk8/com/sun/jmx/mbeanserver/MXBeanIntrospector.java
Normal file
365
jdkSrc/jdk8/com/sun/jmx/mbeanserver/MXBeanIntrospector.java
Normal file
@@ -0,0 +1,365 @@
|
||||
/*
|
||||
* Copyright (c) 2005, 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.mbeanserver;
|
||||
|
||||
import com.sun.jmx.mbeanserver.MBeanIntrospector.MBeanInfoMap;
|
||||
import com.sun.jmx.mbeanserver.MBeanIntrospector.PerInterfaceMap;
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.lang.reflect.GenericArrayType;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.ParameterizedType;
|
||||
import java.lang.reflect.Type;
|
||||
import javax.management.Descriptor;
|
||||
import javax.management.ImmutableDescriptor;
|
||||
import javax.management.MBeanAttributeInfo;
|
||||
import javax.management.MBeanException;
|
||||
import javax.management.MBeanOperationInfo;
|
||||
import javax.management.MBeanParameterInfo;
|
||||
import javax.management.NotCompliantMBeanException;
|
||||
import javax.management.openmbean.OpenMBeanAttributeInfoSupport;
|
||||
import javax.management.openmbean.OpenMBeanOperationInfoSupport;
|
||||
import javax.management.openmbean.OpenMBeanParameterInfo;
|
||||
import javax.management.openmbean.OpenMBeanParameterInfoSupport;
|
||||
import javax.management.openmbean.OpenType;
|
||||
|
||||
/**
|
||||
* Introspector for MXBeans. There is exactly one instance of this class.
|
||||
*
|
||||
* @since 1.6
|
||||
*/
|
||||
class MXBeanIntrospector extends MBeanIntrospector<ConvertingMethod> {
|
||||
private static final MXBeanIntrospector instance = new MXBeanIntrospector();
|
||||
|
||||
static MXBeanIntrospector getInstance() {
|
||||
return instance;
|
||||
}
|
||||
|
||||
@Override
|
||||
PerInterfaceMap<ConvertingMethod> getPerInterfaceMap() {
|
||||
return perInterfaceMap;
|
||||
}
|
||||
|
||||
@Override
|
||||
MBeanInfoMap getMBeanInfoMap() {
|
||||
return mbeanInfoMap;
|
||||
}
|
||||
|
||||
@Override
|
||||
MBeanAnalyzer<ConvertingMethod> getAnalyzer(Class<?> mbeanInterface)
|
||||
throws NotCompliantMBeanException {
|
||||
return MBeanAnalyzer.analyzer(mbeanInterface, this);
|
||||
}
|
||||
|
||||
@Override
|
||||
boolean isMXBean() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
ConvertingMethod mFrom(Method m) {
|
||||
return ConvertingMethod.from(m);
|
||||
}
|
||||
|
||||
@Override
|
||||
String getName(ConvertingMethod m) {
|
||||
return m.getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
Type getGenericReturnType(ConvertingMethod m) {
|
||||
return m.getGenericReturnType();
|
||||
}
|
||||
|
||||
@Override
|
||||
Type[] getGenericParameterTypes(ConvertingMethod m) {
|
||||
return m.getGenericParameterTypes();
|
||||
}
|
||||
|
||||
@Override
|
||||
String[] getSignature(ConvertingMethod m) {
|
||||
return m.getOpenSignature();
|
||||
}
|
||||
|
||||
@Override
|
||||
void checkMethod(ConvertingMethod m) {
|
||||
m.checkCallFromOpen();
|
||||
}
|
||||
|
||||
@Override
|
||||
Object invokeM2(ConvertingMethod m, Object target, Object[] args,
|
||||
Object cookie)
|
||||
throws InvocationTargetException, IllegalAccessException,
|
||||
MBeanException {
|
||||
return m.invokeWithOpenReturn((MXBeanLookup) cookie, target, args);
|
||||
}
|
||||
|
||||
@Override
|
||||
boolean validParameter(ConvertingMethod m, Object value, int paramNo,
|
||||
Object cookie) {
|
||||
if (value == null) {
|
||||
// Null is a valid value for all OpenTypes, even though
|
||||
// OpenType.isValue(null) will return false. It can always be
|
||||
// matched to the corresponding Java type, except when that
|
||||
// type is primitive.
|
||||
Type t = m.getGenericParameterTypes()[paramNo];
|
||||
return (!(t instanceof Class<?>) || !((Class<?>) t).isPrimitive());
|
||||
} else {
|
||||
Object v;
|
||||
try {
|
||||
v = m.fromOpenParameter((MXBeanLookup) cookie, value, paramNo);
|
||||
} catch (Exception e) {
|
||||
// Ignore the exception and let MBeanIntrospector.invokeSetter()
|
||||
// throw the initial exception.
|
||||
return true;
|
||||
}
|
||||
return isValidParameter(m.getMethod(), v, paramNo);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
MBeanAttributeInfo getMBeanAttributeInfo(String attributeName,
|
||||
ConvertingMethod getter, ConvertingMethod setter) {
|
||||
|
||||
final boolean isReadable = (getter != null);
|
||||
final boolean isWritable = (setter != null);
|
||||
final boolean isIs = isReadable && getName(getter).startsWith("is");
|
||||
|
||||
final String description = attributeName;
|
||||
|
||||
final OpenType<?> openType;
|
||||
final Type originalType;
|
||||
if (isReadable) {
|
||||
openType = getter.getOpenReturnType();
|
||||
originalType = getter.getGenericReturnType();
|
||||
} else {
|
||||
openType = setter.getOpenParameterTypes()[0];
|
||||
originalType = setter.getGenericParameterTypes()[0];
|
||||
}
|
||||
Descriptor descriptor = typeDescriptor(openType, originalType);
|
||||
if (isReadable) {
|
||||
descriptor = ImmutableDescriptor.union(descriptor,
|
||||
getter.getDescriptor());
|
||||
}
|
||||
if (isWritable) {
|
||||
descriptor = ImmutableDescriptor.union(descriptor,
|
||||
setter.getDescriptor());
|
||||
}
|
||||
|
||||
final MBeanAttributeInfo ai;
|
||||
if (canUseOpenInfo(originalType)) {
|
||||
ai = new OpenMBeanAttributeInfoSupport(attributeName,
|
||||
description,
|
||||
openType,
|
||||
isReadable,
|
||||
isWritable,
|
||||
isIs,
|
||||
descriptor);
|
||||
} else {
|
||||
ai = new MBeanAttributeInfo(attributeName,
|
||||
originalTypeString(originalType),
|
||||
description,
|
||||
isReadable,
|
||||
isWritable,
|
||||
isIs,
|
||||
descriptor);
|
||||
}
|
||||
// could also consult annotations for defaultValue,
|
||||
// minValue, maxValue, legalValues
|
||||
|
||||
return ai;
|
||||
}
|
||||
|
||||
@Override
|
||||
MBeanOperationInfo getMBeanOperationInfo(String operationName,
|
||||
ConvertingMethod operation) {
|
||||
final Method method = operation.getMethod();
|
||||
final String description = operationName;
|
||||
/* Ideally this would be an empty string, but
|
||||
OMBOperationInfo constructor forbids that. Also, we
|
||||
could consult an annotation to get a useful
|
||||
description. */
|
||||
|
||||
final int impact = MBeanOperationInfo.UNKNOWN;
|
||||
|
||||
final OpenType<?> returnType = operation.getOpenReturnType();
|
||||
final Type originalReturnType = operation.getGenericReturnType();
|
||||
final OpenType<?>[] paramTypes = operation.getOpenParameterTypes();
|
||||
final Type[] originalParamTypes = operation.getGenericParameterTypes();
|
||||
final MBeanParameterInfo[] params =
|
||||
new MBeanParameterInfo[paramTypes.length];
|
||||
boolean openReturnType = canUseOpenInfo(originalReturnType);
|
||||
boolean openParameterTypes = true;
|
||||
Annotation[][] annots = method.getParameterAnnotations();
|
||||
for (int i = 0; i < paramTypes.length; i++) {
|
||||
final String paramName = "p" + i;
|
||||
final String paramDescription = paramName;
|
||||
final OpenType<?> openType = paramTypes[i];
|
||||
final Type originalType = originalParamTypes[i];
|
||||
Descriptor descriptor =
|
||||
typeDescriptor(openType, originalType);
|
||||
descriptor = ImmutableDescriptor.union(descriptor,
|
||||
Introspector.descriptorForAnnotations(annots[i]));
|
||||
final MBeanParameterInfo pi;
|
||||
if (canUseOpenInfo(originalType)) {
|
||||
pi = new OpenMBeanParameterInfoSupport(paramName,
|
||||
paramDescription,
|
||||
openType,
|
||||
descriptor);
|
||||
} else {
|
||||
openParameterTypes = false;
|
||||
pi = new MBeanParameterInfo(
|
||||
paramName,
|
||||
originalTypeString(originalType),
|
||||
paramDescription,
|
||||
descriptor);
|
||||
}
|
||||
params[i] = pi;
|
||||
}
|
||||
|
||||
Descriptor descriptor =
|
||||
typeDescriptor(returnType, originalReturnType);
|
||||
descriptor = ImmutableDescriptor.union(descriptor,
|
||||
Introspector.descriptorForElement(method));
|
||||
final MBeanOperationInfo oi;
|
||||
if (openReturnType && openParameterTypes) {
|
||||
/* If the return value and all the parameters can be faithfully
|
||||
* represented as OpenType then we return an OpenMBeanOperationInfo.
|
||||
* If any of them is a primitive type, we can't. Compatibility
|
||||
* with JSR 174 means that we must return an MBean*Info where
|
||||
* the getType() is the primitive type, not its wrapped type as
|
||||
* we would get with an OpenMBean*Info. The OpenType is available
|
||||
* in the Descriptor in either case.
|
||||
*/
|
||||
final OpenMBeanParameterInfo[] oparams =
|
||||
new OpenMBeanParameterInfo[params.length];
|
||||
System.arraycopy(params, 0, oparams, 0, params.length);
|
||||
oi = new OpenMBeanOperationInfoSupport(operationName,
|
||||
description,
|
||||
oparams,
|
||||
returnType,
|
||||
impact,
|
||||
descriptor);
|
||||
} else {
|
||||
oi = new MBeanOperationInfo(operationName,
|
||||
description,
|
||||
params,
|
||||
openReturnType ?
|
||||
returnType.getClassName() :
|
||||
originalTypeString(originalReturnType),
|
||||
impact,
|
||||
descriptor);
|
||||
}
|
||||
|
||||
return oi;
|
||||
}
|
||||
|
||||
@Override
|
||||
Descriptor getBasicMBeanDescriptor() {
|
||||
return new ImmutableDescriptor("mxbean=true",
|
||||
"immutableInfo=true");
|
||||
}
|
||||
|
||||
@Override
|
||||
Descriptor getMBeanDescriptor(Class<?> resourceClass) {
|
||||
/* We already have immutableInfo=true in the Descriptor
|
||||
* included in the MBeanInfo for the MXBean interface. This
|
||||
* method is being called for the MXBean *class* to add any
|
||||
* new items beyond those in the interface Descriptor, which
|
||||
* currently it does not.
|
||||
*/
|
||||
return ImmutableDescriptor.EMPTY_DESCRIPTOR;
|
||||
}
|
||||
|
||||
private static Descriptor typeDescriptor(OpenType<?> openType,
|
||||
Type originalType) {
|
||||
return new ImmutableDescriptor(
|
||||
new String[] {"openType",
|
||||
"originalType"},
|
||||
new Object[] {openType,
|
||||
originalTypeString(originalType)});
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>True if this type can be faithfully represented in an
|
||||
* OpenMBean*Info.</p>
|
||||
*
|
||||
* <p>Compatibility with JSR 174 means that primitive types must be
|
||||
* represented by an MBean*Info whose getType() is the primitive type
|
||||
* string, e.g. "int". If we used an OpenMBean*Info then this string
|
||||
* would be the wrapped type, e.g. "java.lang.Integer".</p>
|
||||
*
|
||||
* <p>Compatibility with JMX 1.2 (including J2SE 5.0) means that arrays
|
||||
* of primitive types cannot use an ArrayType representing an array of
|
||||
* primitives, because that didn't exist in JMX 1.2.</p>
|
||||
*/
|
||||
private static boolean canUseOpenInfo(Type type) {
|
||||
if (type instanceof GenericArrayType) {
|
||||
return canUseOpenInfo(
|
||||
((GenericArrayType) type).getGenericComponentType());
|
||||
} else if (type instanceof Class<?> && ((Class<?>) type).isArray()) {
|
||||
return canUseOpenInfo(
|
||||
((Class<?>) type).getComponentType());
|
||||
}
|
||||
return (!(type instanceof Class<?> && ((Class<?>) type).isPrimitive()));
|
||||
}
|
||||
|
||||
private static String originalTypeString(Type type) {
|
||||
if (type instanceof Class<?>)
|
||||
return ((Class<?>) type).getName();
|
||||
else
|
||||
return typeName(type);
|
||||
}
|
||||
|
||||
static String typeName(Type type) {
|
||||
if (type instanceof Class<?>) {
|
||||
Class<?> c = (Class<?>) type;
|
||||
if (c.isArray())
|
||||
return typeName(c.getComponentType()) + "[]";
|
||||
else
|
||||
return c.getName();
|
||||
} else if (type instanceof GenericArrayType) {
|
||||
GenericArrayType gat = (GenericArrayType) type;
|
||||
return typeName(gat.getGenericComponentType()) + "[]";
|
||||
} else if (type instanceof ParameterizedType) {
|
||||
ParameterizedType pt = (ParameterizedType) type;
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append(typeName(pt.getRawType())).append("<");
|
||||
String sep = "";
|
||||
for (Type t : pt.getActualTypeArguments()) {
|
||||
sb.append(sep).append(typeName(t));
|
||||
sep = ", ";
|
||||
}
|
||||
return sb.append(">").toString();
|
||||
} else
|
||||
return "???";
|
||||
}
|
||||
|
||||
private final PerInterfaceMap<ConvertingMethod>
|
||||
perInterfaceMap = new PerInterfaceMap<ConvertingMethod>();
|
||||
|
||||
private static final MBeanInfoMap mbeanInfoMap = new MBeanInfoMap();
|
||||
}
|
||||
188
jdkSrc/jdk8/com/sun/jmx/mbeanserver/MXBeanLookup.java
Normal file
188
jdkSrc/jdk8/com/sun/jmx/mbeanserver/MXBeanLookup.java
Normal file
@@ -0,0 +1,188 @@
|
||||
/*
|
||||
* Copyright (c) 2005, 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.mbeanserver;
|
||||
|
||||
import static com.sun.jmx.mbeanserver.Util.*;
|
||||
import java.util.Map;
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.lang.reflect.InvocationHandler;
|
||||
import java.lang.reflect.Proxy;
|
||||
import java.security.AccessController;
|
||||
import javax.management.InstanceAlreadyExistsException;
|
||||
import javax.management.JMX;
|
||||
import javax.management.MBeanServerConnection;
|
||||
import javax.management.MBeanServerInvocationHandler;
|
||||
import javax.management.ObjectName;
|
||||
import javax.management.openmbean.OpenDataException;
|
||||
|
||||
/**
|
||||
* @since 1.6
|
||||
*/
|
||||
|
||||
/*
|
||||
* This class handles the mapping between MXBean references and
|
||||
* ObjectNames. Consider an MXBean interface like this:
|
||||
*
|
||||
* public interface ModuleMXBean {
|
||||
* ProductMXBean getProduct();
|
||||
* void setProduct(ProductMXBean product);
|
||||
* }
|
||||
*
|
||||
* This defines an attribute called "Product" whose originalType will
|
||||
* be ProductMXBean and whose openType will be ObjectName. The
|
||||
* mapping happens as follows.
|
||||
*
|
||||
* When the MXBean's getProduct method is called, it is supposed to
|
||||
* return a reference to another MXBean, or a proxy for another
|
||||
* MXBean. The MXBean layer has to convert this into an ObjectName.
|
||||
* If it's a reference to another MXBean, it needs to be able to look
|
||||
* up the name under which that MXBean has been registered in this
|
||||
* MBeanServer; this is the purpose of the mxbeanToObjectName map. If
|
||||
* it's a proxy, it can check that the MBeanServer matches and if so
|
||||
* extract the ObjectName from the proxy.
|
||||
*
|
||||
* When the setProduct method is called on a proxy for this MXBean,
|
||||
* the argument can be either an MXBean reference (only really logical
|
||||
* if the proxy has a local MBeanServer) or another proxy. So the
|
||||
* mapping logic is the same as for getProduct on the MXBean.
|
||||
*
|
||||
* When the MXBean's setProduct method is called, it needs to convert
|
||||
* the ObjectName into an object implementing the ProductMXBean
|
||||
* interface. We could have a lookup table that reverses
|
||||
* mxbeanToObjectName, but this could violate the general JMX property
|
||||
* that you cannot obtain a reference to an MBean object. So we
|
||||
* always use a proxy for this. However we do have an
|
||||
* objectNameToProxy map that allows us to reuse proxy instances.
|
||||
*
|
||||
* When the getProduct method is called on a proxy for this MXBean, it
|
||||
* must convert the returned ObjectName into an instance of
|
||||
* ProductMXBean. Again it can do this by making a proxy.
|
||||
*
|
||||
* From the above, it is clear that the logic for getX on an MXBean is
|
||||
* the same as for setX on a proxy, and vice versa.
|
||||
*/
|
||||
public class MXBeanLookup {
|
||||
private MXBeanLookup(MBeanServerConnection mbsc) {
|
||||
this.mbsc = mbsc;
|
||||
}
|
||||
|
||||
static MXBeanLookup lookupFor(MBeanServerConnection mbsc) {
|
||||
synchronized (mbscToLookup) {
|
||||
WeakReference<MXBeanLookup> weakLookup = mbscToLookup.get(mbsc);
|
||||
MXBeanLookup lookup = (weakLookup == null) ? null : weakLookup.get();
|
||||
if (lookup == null) {
|
||||
lookup = new MXBeanLookup(mbsc);
|
||||
mbscToLookup.put(mbsc, new WeakReference<MXBeanLookup>(lookup));
|
||||
}
|
||||
return lookup;
|
||||
}
|
||||
}
|
||||
|
||||
synchronized <T> T objectNameToMXBean(ObjectName name, Class<T> type) {
|
||||
WeakReference<Object> wr = objectNameToProxy.get(name);
|
||||
if (wr != null) {
|
||||
Object proxy = wr.get();
|
||||
if (type.isInstance(proxy))
|
||||
return type.cast(proxy);
|
||||
}
|
||||
T proxy = JMX.newMXBeanProxy(mbsc, name, type);
|
||||
objectNameToProxy.put(name, new WeakReference<Object>(proxy));
|
||||
return proxy;
|
||||
}
|
||||
|
||||
synchronized ObjectName mxbeanToObjectName(Object mxbean)
|
||||
throws OpenDataException {
|
||||
String wrong;
|
||||
if (mxbean instanceof Proxy) {
|
||||
InvocationHandler ih = Proxy.getInvocationHandler(mxbean);
|
||||
if (ih instanceof MBeanServerInvocationHandler) {
|
||||
MBeanServerInvocationHandler mbsih =
|
||||
(MBeanServerInvocationHandler) ih;
|
||||
if (mbsih.getMBeanServerConnection().equals(mbsc))
|
||||
return mbsih.getObjectName();
|
||||
else
|
||||
wrong = "proxy for a different MBeanServer";
|
||||
} else
|
||||
wrong = "not a JMX proxy";
|
||||
} else {
|
||||
ObjectName name = mxbeanToObjectName.get(mxbean);
|
||||
if (name != null)
|
||||
return name;
|
||||
wrong = "not an MXBean registered in this MBeanServer";
|
||||
}
|
||||
String s = (mxbean == null) ?
|
||||
"null" : "object of type " + mxbean.getClass().getName();
|
||||
throw new OpenDataException(
|
||||
"Could not convert " + s + " to an ObjectName: " + wrong);
|
||||
// Message will be strange if mxbean is null but it is not
|
||||
// supposed to be.
|
||||
}
|
||||
|
||||
synchronized void addReference(ObjectName name, Object mxbean)
|
||||
throws InstanceAlreadyExistsException {
|
||||
ObjectName existing = mxbeanToObjectName.get(mxbean);
|
||||
if (existing != null) {
|
||||
String multiname = AccessController.doPrivileged(
|
||||
new GetPropertyAction("jmx.mxbean.multiname"));
|
||||
if (!"true".equalsIgnoreCase(multiname)) {
|
||||
throw new InstanceAlreadyExistsException(
|
||||
"MXBean already registered with name " + existing);
|
||||
}
|
||||
}
|
||||
mxbeanToObjectName.put(mxbean, name);
|
||||
}
|
||||
|
||||
synchronized boolean removeReference(ObjectName name, Object mxbean) {
|
||||
if (name.equals(mxbeanToObjectName.get(mxbean))) {
|
||||
mxbeanToObjectName.remove(mxbean);
|
||||
return true;
|
||||
} else
|
||||
return false;
|
||||
/* removeReference can be called when the above condition fails,
|
||||
* notably if you try to register the same MXBean twice.
|
||||
*/
|
||||
}
|
||||
|
||||
static MXBeanLookup getLookup() {
|
||||
return currentLookup.get();
|
||||
}
|
||||
|
||||
static void setLookup(MXBeanLookup lookup) {
|
||||
currentLookup.set(lookup);
|
||||
}
|
||||
|
||||
private static final ThreadLocal<MXBeanLookup> currentLookup =
|
||||
new ThreadLocal<MXBeanLookup>();
|
||||
|
||||
private final MBeanServerConnection mbsc;
|
||||
private final WeakIdentityHashMap<Object, ObjectName>
|
||||
mxbeanToObjectName = WeakIdentityHashMap.make();
|
||||
private final Map<ObjectName, WeakReference<Object>>
|
||||
objectNameToProxy = newMap();
|
||||
private static final WeakIdentityHashMap<MBeanServerConnection,
|
||||
WeakReference<MXBeanLookup>>
|
||||
mbscToLookup = WeakIdentityHashMap.make();
|
||||
}
|
||||
210
jdkSrc/jdk8/com/sun/jmx/mbeanserver/MXBeanMapping.java
Normal file
210
jdkSrc/jdk8/com/sun/jmx/mbeanserver/MXBeanMapping.java
Normal file
@@ -0,0 +1,210 @@
|
||||
/*
|
||||
* Copyright (c) 2007, 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package com.sun.jmx.mbeanserver;
|
||||
|
||||
import java.io.InvalidObjectException;
|
||||
import java.lang.reflect.Type;
|
||||
import javax.management.openmbean.OpenDataException;
|
||||
import javax.management.openmbean.OpenType;
|
||||
|
||||
/**
|
||||
* <p>A custom mapping between Java types and Open types for use in MXBeans.
|
||||
* To define such a mapping, subclass this class and define at least the
|
||||
* {@link #fromOpenValue fromOpenValue} and {@link #toOpenValue toOpenValue}
|
||||
* methods, and optionally the {@link #checkReconstructible} method.
|
||||
* Then either use an {@link MXBeanMappingClass} annotation on your custom
|
||||
* Java types, or include this MXBeanMapping in an
|
||||
* {@link MXBeanMappingFactory}.</p>
|
||||
*
|
||||
* <p>For example, suppose we have a class {@code MyLinkedList}, which looks
|
||||
* like this:</p>
|
||||
*
|
||||
* <pre>
|
||||
* public class MyLinkedList {
|
||||
* public MyLinkedList(String name, MyLinkedList next) {...}
|
||||
* public String getName() {...}
|
||||
* public MyLinkedList getNext() {...}
|
||||
* }
|
||||
* </pre>
|
||||
*
|
||||
* <p>This is not a valid type for MXBeans, because it contains a
|
||||
* self-referential property "next" defined by the {@code getNext()}
|
||||
* method. MXBeans do not support recursive types. So we would like
|
||||
* to specify a mapping for {@code MyLinkedList} explicitly. When an
|
||||
* MXBean interface contains {@code MyLinkedList}, that will be mapped
|
||||
* into a {@code String[]}, which is a valid Open Type.</p>
|
||||
*
|
||||
* <p>To define this mapping, we first subclass {@code MXBeanMapping}:</p>
|
||||
*
|
||||
* <pre>
|
||||
* public class MyLinkedListMapping extends MXBeanMapping {
|
||||
* public MyLinkedListMapping(Type type) throws OpenDataException {
|
||||
* super(MyLinkedList.class, ArrayType.getArrayType(SimpleType.STRING));
|
||||
* if (type != MyLinkedList.class)
|
||||
* throw new OpenDataException("Mapping only valid for MyLinkedList");
|
||||
* }
|
||||
*
|
||||
* {@literal @Override}
|
||||
* public Object fromOpenValue(Object openValue) throws InvalidObjectException {
|
||||
* String[] array = (String[]) openValue;
|
||||
* MyLinkedList list = null;
|
||||
* for (int i = array.length - 1; i >= 0; i--)
|
||||
* list = new MyLinkedList(array[i], list);
|
||||
* return list;
|
||||
* }
|
||||
*
|
||||
* {@literal @Override}
|
||||
* public Object toOpenValue(Object javaValue) throws OpenDataException {
|
||||
* ArrayList<String> array = new ArrayList<String>();
|
||||
* for (MyLinkedList list = (MyLinkedList) javaValue; list != null;
|
||||
* list = list.getNext())
|
||||
* array.add(list.getName());
|
||||
* return array.toArray(new String[0]);
|
||||
* }
|
||||
* }
|
||||
* </pre>
|
||||
*
|
||||
* <p>The call to the superclass constructor specifies what the
|
||||
* original Java type is ({@code MyLinkedList.class}) and what Open
|
||||
* Type it is mapped to ({@code
|
||||
* ArrayType.getArrayType(SimpleType.STRING)}). The {@code
|
||||
* fromOpenValue} method says how we go from the Open Type ({@code
|
||||
* String[]}) to the Java type ({@code MyLinkedList}), and the {@code
|
||||
* toOpenValue} method says how we go from the Java type to the Open
|
||||
* Type.</p>
|
||||
*
|
||||
* <p>With this mapping defined, we can annotate the {@code MyLinkedList}
|
||||
* class appropriately:</p>
|
||||
*
|
||||
* <pre>
|
||||
* {@literal @MXBeanMappingClass}(MyLinkedListMapping.class)
|
||||
* public class MyLinkedList {...}
|
||||
* </pre>
|
||||
*
|
||||
* <p>Now we can use {@code MyLinkedList} in an MXBean interface and it
|
||||
* will work.</p>
|
||||
*
|
||||
* <p>If we are unable to modify the {@code MyLinkedList} class,
|
||||
* we can define an {@link MXBeanMappingFactory}. See the documentation
|
||||
* of that class for further details.</p>
|
||||
*
|
||||
* @see <a href="../MXBean.html#custom">MXBean specification, section
|
||||
* "Custom MXBean type mappings"</a>
|
||||
*/
|
||||
public abstract class MXBeanMapping {
|
||||
private final Type javaType;
|
||||
private final OpenType<?> openType;
|
||||
private final Class<?> openClass;
|
||||
|
||||
/**
|
||||
* <p>Construct a mapping between the given Java type and the given
|
||||
* Open Type.</p>
|
||||
*
|
||||
* @param javaType the Java type (for example, {@code MyLinkedList}).
|
||||
* @param openType the Open Type (for example, {@code
|
||||
* ArrayType.getArrayType(SimpleType.STRING)})
|
||||
*
|
||||
* @throws NullPointerException if either argument is null.
|
||||
*/
|
||||
protected MXBeanMapping(Type javaType, OpenType<?> openType) {
|
||||
if (javaType == null || openType == null)
|
||||
throw new NullPointerException("Null argument");
|
||||
this.javaType = javaType;
|
||||
this.openType = openType;
|
||||
this.openClass = makeOpenClass(javaType, openType);
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>The Java type that was supplied to the constructor.</p>
|
||||
* @return the Java type that was supplied to the constructor.
|
||||
*/
|
||||
public final Type getJavaType() {
|
||||
return javaType;
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>The Open Type that was supplied to the constructor.</p>
|
||||
* @return the Open Type that was supplied to the constructor.
|
||||
*/
|
||||
public final OpenType<?> getOpenType() {
|
||||
return openType;
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>The Java class that corresponds to instances of the
|
||||
* {@linkplain #getOpenType() Open Type} for this mapping.</p>
|
||||
* @return the Java class that corresponds to instances of the
|
||||
* Open Type for this mapping.
|
||||
* @see OpenType#getClassName
|
||||
*/
|
||||
public final Class<?> getOpenClass() {
|
||||
return openClass;
|
||||
}
|
||||
|
||||
private static Class<?> makeOpenClass(Type javaType, OpenType<?> openType) {
|
||||
if (javaType instanceof Class<?> && ((Class<?>) javaType).isPrimitive())
|
||||
return (Class<?>) javaType;
|
||||
try {
|
||||
String className = openType.getClassName();
|
||||
return Class.forName(className, false, MXBeanMapping.class.getClassLoader());
|
||||
} catch (ClassNotFoundException e) {
|
||||
throw new RuntimeException(e); // should not happen
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Convert an instance of the Open Type into the Java type.
|
||||
* @param openValue the value to be converted.
|
||||
* @return the converted value.
|
||||
* @throws InvalidObjectException if the value cannot be converted.
|
||||
*/
|
||||
public abstract Object fromOpenValue(Object openValue)
|
||||
throws InvalidObjectException;
|
||||
|
||||
/**
|
||||
* <p>Convert an instance of the Java type into the Open Type.
|
||||
* @param javaValue the value to be converted.
|
||||
* @return the converted value.
|
||||
* @throws OpenDataException if the value cannot be converted.
|
||||
*/
|
||||
public abstract Object toOpenValue(Object javaValue)
|
||||
throws OpenDataException;
|
||||
|
||||
|
||||
/**
|
||||
* <p>Throw an appropriate InvalidObjectException if we will not
|
||||
* be able to convert back from the open data to the original Java
|
||||
* object. The {@link #fromOpenValue fromOpenValue} throws an
|
||||
* exception if a given open data value cannot be converted. This
|
||||
* method throws an exception if <em>no</em> open data values can
|
||||
* be converted. The default implementation of this method never
|
||||
* throws an exception. Subclasses can override it as
|
||||
* appropriate.</p>
|
||||
* @throws InvalidObjectException if {@code fromOpenValue} will throw
|
||||
* an exception no matter what its argument is.
|
||||
*/
|
||||
public void checkReconstructible() throws InvalidObjectException {}
|
||||
}
|
||||
124
jdkSrc/jdk8/com/sun/jmx/mbeanserver/MXBeanMappingFactory.java
Normal file
124
jdkSrc/jdk8/com/sun/jmx/mbeanserver/MXBeanMappingFactory.java
Normal file
@@ -0,0 +1,124 @@
|
||||
/*
|
||||
* Copyright (c) 2007, 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.mbeanserver;
|
||||
|
||||
import javax.management.openmbean.*;
|
||||
import com.sun.jmx.mbeanserver.MXBeanMapping;
|
||||
import com.sun.jmx.mbeanserver.DefaultMXBeanMappingFactory;
|
||||
import java.lang.reflect.Type;
|
||||
|
||||
/**
|
||||
* <p>Defines how types are mapped for a given MXBean or set of MXBeans.
|
||||
* An {@code MXBeanMappingFactory} can be specified either through the
|
||||
* {@link MXBeanMappingFactoryClass} annotation, or through the
|
||||
* {@link javax.management.JMX.MBeanOptions JMX.MBeanOptions} argument to a
|
||||
* {@link javax.management.StandardMBean StandardMBean} constructor or MXBean
|
||||
* proxy.</p>
|
||||
*
|
||||
* <p>An {@code MXBeanMappingFactory} must return an {@code MXBeanMapping}
|
||||
* for any Java type that appears in the MXBeans that the factory is being
|
||||
* used for. Usually it does that by handling any custom types, and
|
||||
* forwarding everything else to the {@linkplain #DEFAULT default mapping
|
||||
* factory}.</p>
|
||||
*
|
||||
* <p>Consider the {@code MyLinkedList} example from the {@link MXBeanMapping}
|
||||
* documentation. If we are unable to change the {@code MyLinkedList} class
|
||||
* to add an {@link MXBeanMappingClass} annotation, we could achieve the same
|
||||
* effect by defining {@code MyLinkedListMappingFactory} as follows:</p>
|
||||
*
|
||||
* <pre>
|
||||
* public class MyLinkedListMappingFactory extends MXBeanMappingFactory {
|
||||
* public MyLinkedListMappingFactory() {}
|
||||
*
|
||||
* public MXBeanMapping mappingForType(Type t, MXBeanMappingFactory f)
|
||||
* throws OpenDataException {
|
||||
* if (t == MyLinkedList.class)
|
||||
* return new MyLinkedListMapping(t);
|
||||
* else
|
||||
* return MXBeanMappingFactory.DEFAULT.mappingForType(t, f);
|
||||
* }
|
||||
* }
|
||||
* </pre>
|
||||
*
|
||||
* <p>The mapping factory handles only the {@code MyLinkedList} class.
|
||||
* Every other type is forwarded to the default mapping factory.
|
||||
* This includes types such as {@code MyLinkedList[]} and
|
||||
* {@code List<MyLinkedList>}; the default mapping factory will recursively
|
||||
* invoke {@code MyLinkedListMappingFactory} to map the contained
|
||||
* {@code MyLinkedList} type.</p>
|
||||
*
|
||||
* <p>Once we have defined {@code MyLinkedListMappingFactory}, we can use
|
||||
* it in an MXBean interface like this:</p>
|
||||
*
|
||||
* <pre>
|
||||
* {@literal @MXBeanMappingFactoryClass}(MyLinkedListMappingFactory.class)
|
||||
* public interface SomethingMXBean {
|
||||
* public MyLinkedList getSomething();
|
||||
* }
|
||||
* </pre>
|
||||
*
|
||||
* <p>Alternatively we can annotate the package that {@code SomethingMXBean}
|
||||
* appears in, or we can supply the factory to a {@link
|
||||
* javax.management.StandardMBean StandardMBean} constructor or MXBean
|
||||
* proxy.</p>
|
||||
*
|
||||
* @see <a href="../MXBean.html#custom">MXBean specification, section
|
||||
* "Custom MXBean type mappings"</a>
|
||||
*/
|
||||
public abstract class MXBeanMappingFactory {
|
||||
/**
|
||||
* <p>Construct an instance of this class.</p>
|
||||
*/
|
||||
protected MXBeanMappingFactory() {}
|
||||
|
||||
/**
|
||||
* <p>Mapping factory that applies the default rules for MXBean
|
||||
* mappings, as described in the <a
|
||||
* href="../MXBean.html#MXBean-spec">MXBean specification</a>.</p>
|
||||
*/
|
||||
public static final MXBeanMappingFactory DEFAULT =
|
||||
new DefaultMXBeanMappingFactory();
|
||||
|
||||
/**
|
||||
* <p>Return the mapping for the given Java type. Typically, a
|
||||
* mapping factory will return mappings for types it handles, and
|
||||
* forward other types to another mapping factory, most often
|
||||
* the {@linkplain #DEFAULT default one}.</p>
|
||||
* @param t the Java type to be mapped.
|
||||
* @param f the original mapping factory that was consulted to do
|
||||
* the mapping. A mapping factory should pass this parameter intact
|
||||
* if it forwards a type to another mapping factory. In the example,
|
||||
* this is how {@code MyLinkedListMappingFactory} works for types
|
||||
* like {@code MyLinkedList[]} and {@code List<MyLinkedList>}.
|
||||
* @return the mapping for the given type.
|
||||
* @throws OpenDataException if this type cannot be mapped. This
|
||||
* exception is appropriate if the factory is supposed to handle
|
||||
* all types of this sort (for example, all linked lists), but
|
||||
* cannot handle this particular type.
|
||||
*/
|
||||
public abstract MXBeanMapping mappingForType(Type t, MXBeanMappingFactory f)
|
||||
throws OpenDataException;
|
||||
}
|
||||
175
jdkSrc/jdk8/com/sun/jmx/mbeanserver/MXBeanProxy.java
Normal file
175
jdkSrc/jdk8/com/sun/jmx/mbeanserver/MXBeanProxy.java
Normal file
@@ -0,0 +1,175 @@
|
||||
/*
|
||||
* Copyright (c) 2005, 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.mbeanserver;
|
||||
|
||||
import static com.sun.jmx.mbeanserver.Util.*;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.management.Attribute;
|
||||
import javax.management.MBeanServerConnection;
|
||||
import javax.management.NotCompliantMBeanException;
|
||||
import javax.management.ObjectName;
|
||||
|
||||
/**
|
||||
<p>Helper class for an {@link InvocationHandler} that forwards methods from an
|
||||
MXBean interface to a named
|
||||
MXBean in an MBean Server and handles translation between the
|
||||
arbitrary Java types in the interface and the Open Types used
|
||||
by the MXBean.</p>
|
||||
|
||||
@since 1.6
|
||||
*/
|
||||
public class MXBeanProxy {
|
||||
public MXBeanProxy(Class<?> mxbeanInterface) {
|
||||
|
||||
if (mxbeanInterface == null)
|
||||
throw new IllegalArgumentException("Null parameter");
|
||||
|
||||
final MBeanAnalyzer<ConvertingMethod> analyzer;
|
||||
try {
|
||||
analyzer =
|
||||
MXBeanIntrospector.getInstance().getAnalyzer(mxbeanInterface);
|
||||
} catch (NotCompliantMBeanException e) {
|
||||
throw new IllegalArgumentException(e);
|
||||
}
|
||||
analyzer.visit(new Visitor());
|
||||
}
|
||||
|
||||
private class Visitor
|
||||
implements MBeanAnalyzer.MBeanVisitor<ConvertingMethod> {
|
||||
public void visitAttribute(String attributeName,
|
||||
ConvertingMethod getter,
|
||||
ConvertingMethod setter) {
|
||||
if (getter != null) {
|
||||
getter.checkCallToOpen();
|
||||
Method getterMethod = getter.getMethod();
|
||||
handlerMap.put(getterMethod,
|
||||
new GetHandler(attributeName, getter));
|
||||
}
|
||||
if (setter != null) {
|
||||
// return type is void, no need for checkCallToOpen
|
||||
Method setterMethod = setter.getMethod();
|
||||
handlerMap.put(setterMethod,
|
||||
new SetHandler(attributeName, setter));
|
||||
}
|
||||
}
|
||||
|
||||
public void visitOperation(String operationName,
|
||||
ConvertingMethod operation) {
|
||||
operation.checkCallToOpen();
|
||||
Method operationMethod = operation.getMethod();
|
||||
String[] sig = operation.getOpenSignature();
|
||||
handlerMap.put(operationMethod,
|
||||
new InvokeHandler(operationName, sig, operation));
|
||||
}
|
||||
}
|
||||
|
||||
private static abstract class Handler {
|
||||
Handler(String name, ConvertingMethod cm) {
|
||||
this.name = name;
|
||||
this.convertingMethod = cm;
|
||||
}
|
||||
|
||||
String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
ConvertingMethod getConvertingMethod() {
|
||||
return convertingMethod;
|
||||
}
|
||||
|
||||
abstract Object invoke(MBeanServerConnection mbsc,
|
||||
ObjectName name, Object[] args) throws Exception;
|
||||
|
||||
private final String name;
|
||||
private final ConvertingMethod convertingMethod;
|
||||
}
|
||||
|
||||
private static class GetHandler extends Handler {
|
||||
GetHandler(String attributeName, ConvertingMethod cm) {
|
||||
super(attributeName, cm);
|
||||
}
|
||||
|
||||
@Override
|
||||
Object invoke(MBeanServerConnection mbsc, ObjectName name, Object[] args)
|
||||
throws Exception {
|
||||
assert(args == null || args.length == 0);
|
||||
return mbsc.getAttribute(name, getName());
|
||||
}
|
||||
}
|
||||
|
||||
private static class SetHandler extends Handler {
|
||||
SetHandler(String attributeName, ConvertingMethod cm) {
|
||||
super(attributeName, cm);
|
||||
}
|
||||
|
||||
@Override
|
||||
Object invoke(MBeanServerConnection mbsc, ObjectName name, Object[] args)
|
||||
throws Exception {
|
||||
assert(args.length == 1);
|
||||
Attribute attr = new Attribute(getName(), args[0]);
|
||||
mbsc.setAttribute(name, attr);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private static class InvokeHandler extends Handler {
|
||||
InvokeHandler(String operationName, String[] signature,
|
||||
ConvertingMethod cm) {
|
||||
super(operationName, cm);
|
||||
this.signature = signature;
|
||||
}
|
||||
|
||||
Object invoke(MBeanServerConnection mbsc, ObjectName name, Object[] args)
|
||||
throws Exception {
|
||||
return mbsc.invoke(name, getName(), args, signature);
|
||||
}
|
||||
|
||||
private final String[] signature;
|
||||
}
|
||||
|
||||
public Object invoke(MBeanServerConnection mbsc, ObjectName name,
|
||||
Method method, Object[] args)
|
||||
throws Throwable {
|
||||
|
||||
Handler handler = handlerMap.get(method);
|
||||
ConvertingMethod cm = handler.getConvertingMethod();
|
||||
MXBeanLookup lookup = MXBeanLookup.lookupFor(mbsc);
|
||||
MXBeanLookup oldLookup = MXBeanLookup.getLookup();
|
||||
try {
|
||||
MXBeanLookup.setLookup(lookup);
|
||||
Object[] openArgs = cm.toOpenParameters(lookup, args);
|
||||
Object result = handler.invoke(mbsc, name, openArgs);
|
||||
return cm.fromOpenReturnValue(lookup, result);
|
||||
} finally {
|
||||
MXBeanLookup.setLookup(oldLookup);
|
||||
}
|
||||
}
|
||||
|
||||
private final Map<Method, Handler> handlerMap = newMap();
|
||||
}
|
||||
178
jdkSrc/jdk8/com/sun/jmx/mbeanserver/MXBeanSupport.java
Normal file
178
jdkSrc/jdk8/com/sun/jmx/mbeanserver/MXBeanSupport.java
Normal file
@@ -0,0 +1,178 @@
|
||||
/*
|
||||
* Copyright (c) 2005, 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.mbeanserver;
|
||||
|
||||
import static com.sun.jmx.mbeanserver.Util.*;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.management.InstanceAlreadyExistsException;
|
||||
import javax.management.JMX;
|
||||
import javax.management.MBeanServer;
|
||||
import javax.management.NotCompliantMBeanException;
|
||||
import javax.management.ObjectName;
|
||||
|
||||
/**
|
||||
* Base class for MXBeans.
|
||||
*
|
||||
* @since 1.6
|
||||
*/
|
||||
public class MXBeanSupport extends MBeanSupport<ConvertingMethod> {
|
||||
|
||||
/**
|
||||
<p>Construct an MXBean that wraps the given resource using the
|
||||
given MXBean interface.</p>
|
||||
|
||||
@param resource the underlying resource for the new MXBean.
|
||||
|
||||
@param mxbeanInterface the interface to be used to determine
|
||||
the MXBean's management interface.
|
||||
|
||||
@param <T> a type parameter that allows the compiler to check
|
||||
that {@code resource} implements {@code mxbeanInterface},
|
||||
provided that {@code mxbeanInterface} is a class constant like
|
||||
{@code SomeMXBean.class}.
|
||||
|
||||
@throws IllegalArgumentException if {@code resource} is null or
|
||||
if it does not implement the class {@code mxbeanInterface} or if
|
||||
that class is not a valid MXBean interface.
|
||||
*/
|
||||
public <T> MXBeanSupport(T resource, Class<T> mxbeanInterface)
|
||||
throws NotCompliantMBeanException {
|
||||
super(resource, mxbeanInterface);
|
||||
}
|
||||
|
||||
@Override
|
||||
MBeanIntrospector<ConvertingMethod> getMBeanIntrospector() {
|
||||
return MXBeanIntrospector.getInstance();
|
||||
}
|
||||
|
||||
@Override
|
||||
Object getCookie() {
|
||||
return mxbeanLookup;
|
||||
}
|
||||
|
||||
static <T> Class<? super T> findMXBeanInterface(Class<T> resourceClass) {
|
||||
if (resourceClass == null)
|
||||
throw new IllegalArgumentException("Null resource class");
|
||||
final Set<Class<?>> intfs = transitiveInterfaces(resourceClass);
|
||||
final Set<Class<?>> candidates = newSet();
|
||||
for (Class<?> intf : intfs) {
|
||||
if (JMX.isMXBeanInterface(intf))
|
||||
candidates.add(intf);
|
||||
}
|
||||
reduce:
|
||||
while (candidates.size() > 1) {
|
||||
for (Class<?> intf : candidates) {
|
||||
for (Iterator<Class<?>> it = candidates.iterator(); it.hasNext();
|
||||
) {
|
||||
final Class<?> intf2 = it.next();
|
||||
if (intf != intf2 && intf2.isAssignableFrom(intf)) {
|
||||
it.remove();
|
||||
continue reduce;
|
||||
}
|
||||
}
|
||||
}
|
||||
final String msg =
|
||||
"Class " + resourceClass.getName() + " implements more than " +
|
||||
"one MXBean interface: " + candidates;
|
||||
throw new IllegalArgumentException(msg);
|
||||
}
|
||||
if (candidates.iterator().hasNext()) {
|
||||
return Util.cast(candidates.iterator().next());
|
||||
} else {
|
||||
final String msg =
|
||||
"Class " + resourceClass.getName() +
|
||||
" is not a JMX compliant MXBean";
|
||||
throw new IllegalArgumentException(msg);
|
||||
}
|
||||
}
|
||||
|
||||
/* Return all interfaces inherited by this class, directly or
|
||||
* indirectly through the parent class and interfaces.
|
||||
*/
|
||||
private static Set<Class<?>> transitiveInterfaces(Class<?> c) {
|
||||
Set<Class<?>> set = newSet();
|
||||
transitiveInterfaces(c, set);
|
||||
return set;
|
||||
}
|
||||
private static void transitiveInterfaces(Class<?> c, Set<Class<?>> intfs) {
|
||||
if (c == null)
|
||||
return;
|
||||
if (c.isInterface())
|
||||
intfs.add(c);
|
||||
transitiveInterfaces(c.getSuperclass(), intfs);
|
||||
for (Class<?> sup : c.getInterfaces())
|
||||
transitiveInterfaces(sup, intfs);
|
||||
}
|
||||
|
||||
/*
|
||||
* The sequence of events for tracking inter-MXBean references is
|
||||
* relatively complicated. We use the magical preRegister2 method
|
||||
* which the MBeanServer knows about. The steps during registration
|
||||
* are:
|
||||
* (1) Call user preRegister, if any. If exception, abandon.
|
||||
* (2) Call preRegister2 and hence this register method. If exception,
|
||||
* call postRegister(false) and abandon.
|
||||
* (3) Try to register the MBean. If exception, call registerFailed()
|
||||
* which will call the unregister method. (Also call postRegister(false).)
|
||||
* (4) If we get this far, we can call postRegister(true).
|
||||
*
|
||||
* When we are wrapped in an instance of javax.management.StandardMBean,
|
||||
* things are simpler. That class calls this method from its preRegister,
|
||||
* and propagates any exception. There is no user preRegister in this case.
|
||||
* If this method succeeds but registration subsequently fails,
|
||||
* StandardMBean calls unregister from its postRegister(false) method.
|
||||
*/
|
||||
@Override
|
||||
public void register(MBeanServer server, ObjectName name)
|
||||
throws InstanceAlreadyExistsException {
|
||||
if (name == null)
|
||||
throw new IllegalArgumentException("Null object name");
|
||||
// eventually we could have some logic to supply a default name
|
||||
|
||||
synchronized (lock) {
|
||||
this.mxbeanLookup = MXBeanLookup.lookupFor(server);
|
||||
this.mxbeanLookup.addReference(name, getResource());
|
||||
this.objectName = name;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unregister() {
|
||||
synchronized (lock) {
|
||||
if (mxbeanLookup != null) {
|
||||
if (mxbeanLookup.removeReference(objectName, getResource()))
|
||||
objectName = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
private final Object lock = new Object(); // for mxbeanLookup and objectName
|
||||
|
||||
private MXBeanLookup mxbeanLookup;
|
||||
private ObjectName objectName;
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
/*
|
||||
* Copyright (c) 2002, 2007, 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.mbeanserver;
|
||||
|
||||
|
||||
// JMX import
|
||||
import javax.management.ObjectName;
|
||||
import javax.management.loading.ClassLoaderRepository;
|
||||
|
||||
/**
|
||||
* This interface keeps the list of Class Loaders registered in the
|
||||
* MBean Server.
|
||||
* It provides the necessary methods to load classes using the
|
||||
* registered Class Loaders, and to add/remove class loaders from the
|
||||
* list.
|
||||
*
|
||||
* @since 1.5
|
||||
*/
|
||||
public interface ModifiableClassLoaderRepository
|
||||
extends ClassLoaderRepository {
|
||||
|
||||
/**
|
||||
* Add an anonymous ClassLoader to the repository.
|
||||
**/
|
||||
public void addClassLoader(ClassLoader loader);
|
||||
|
||||
/**
|
||||
* Remove the specified ClassLoader to the repository.
|
||||
* The class loader may or may not be anonymous.
|
||||
**/
|
||||
public void removeClassLoader(ClassLoader loader);
|
||||
|
||||
/**
|
||||
* Add a named ClassLoader to the repository.
|
||||
**/
|
||||
public void addClassLoader(ObjectName name, ClassLoader loader);
|
||||
|
||||
/**
|
||||
* Remove a named ClassLoader from the repository.
|
||||
**/
|
||||
public void removeClassLoader(ObjectName name);
|
||||
|
||||
/**
|
||||
* Get a named ClassLoader from the repository.
|
||||
**/
|
||||
public ClassLoader getClassLoader(ObjectName name);
|
||||
}
|
||||
122
jdkSrc/jdk8/com/sun/jmx/mbeanserver/NamedObject.java
Normal file
122
jdkSrc/jdk8/com/sun/jmx/mbeanserver/NamedObject.java
Normal file
@@ -0,0 +1,122 @@
|
||||
/*
|
||||
* Copyright (c) 1999, 2007, 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.mbeanserver;
|
||||
|
||||
import javax.management.* ;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* This class is used for storing a pair (name, object) where name is
|
||||
* an object name and object is a reference to the object.
|
||||
*
|
||||
* @since 1.5
|
||||
*/
|
||||
public class NamedObject {
|
||||
|
||||
|
||||
/**
|
||||
* Object name.
|
||||
*/
|
||||
private final ObjectName name;
|
||||
|
||||
/**
|
||||
* Object reference.
|
||||
*/
|
||||
private final DynamicMBean object;
|
||||
|
||||
|
||||
/**
|
||||
* Allows a named object to be created.
|
||||
*
|
||||
*@param objectName The object name of the object.
|
||||
*@param object A reference to the object.
|
||||
*/
|
||||
public NamedObject(ObjectName objectName, DynamicMBean object) {
|
||||
if (objectName.isPattern()) {
|
||||
throw new RuntimeOperationsException(new IllegalArgumentException("Invalid name->"+ objectName.toString()));
|
||||
}
|
||||
this.name= objectName;
|
||||
this.object= object;
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows a named object to be created.
|
||||
*
|
||||
*@param objectName The string representation of the object name of the object.
|
||||
*@param object A reference to the object.
|
||||
*
|
||||
*@exception MalformedObjectNameException The string passed does not have the format of a valid ObjectName
|
||||
*/
|
||||
public NamedObject(String objectName, DynamicMBean object) throws MalformedObjectNameException{
|
||||
ObjectName objName= new ObjectName(objectName);
|
||||
if (objName.isPattern()) {
|
||||
throw new RuntimeOperationsException(new IllegalArgumentException("Invalid name->"+ objName.toString()));
|
||||
}
|
||||
this.name= objName;
|
||||
this.object= object;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compares the current object name with another object name.
|
||||
*
|
||||
* @param object The Named Object that the current object name is to be
|
||||
* compared with.
|
||||
*
|
||||
* @return True if the two named objects are equal, otherwise false.
|
||||
*/
|
||||
public boolean equals(Object object) {
|
||||
if (this == object) return true;
|
||||
if (object == null) return false;
|
||||
if (!(object instanceof NamedObject)) return false;
|
||||
NamedObject no = (NamedObject) object;
|
||||
return name.equals(no.getName());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns a hash code for this named object.
|
||||
*
|
||||
*/
|
||||
public int hashCode() {
|
||||
return name.hashCode();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the object name.
|
||||
*/
|
||||
public ObjectName getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the object
|
||||
*/
|
||||
public DynamicMBean getObject() {
|
||||
return object;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
* Copyright (c) 1999, 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 com.sun.jmx.mbeanserver;
|
||||
|
||||
// Java import
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.ObjectInputStream;
|
||||
import java.io.ObjectStreamClass;
|
||||
import sun.reflect.misc.ReflectUtil;
|
||||
|
||||
/**
|
||||
* This class deserializes an object in the context of a specific class loader.
|
||||
*
|
||||
* @since 1.5
|
||||
*/
|
||||
class ObjectInputStreamWithLoader extends ObjectInputStream {
|
||||
|
||||
|
||||
private ClassLoader loader;
|
||||
|
||||
|
||||
/**
|
||||
* @exception IOException Signals that an I/O exception of some
|
||||
* sort has occurred.
|
||||
* @exception StreamCorruptedException The object stream is corrupt.
|
||||
*/
|
||||
public ObjectInputStreamWithLoader(InputStream in, ClassLoader theLoader)
|
||||
throws IOException {
|
||||
super(in);
|
||||
this.loader = theLoader;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Class<?> resolveClass(ObjectStreamClass aClass)
|
||||
throws IOException, ClassNotFoundException {
|
||||
if (loader == null) {
|
||||
return super.resolveClass(aClass);
|
||||
} else {
|
||||
String name = aClass.getName();
|
||||
ReflectUtil.checkPackageAccess(name);
|
||||
// Query the class loader ...
|
||||
return Class.forName(name, false, loader);
|
||||
}
|
||||
}
|
||||
}
|
||||
280
jdkSrc/jdk8/com/sun/jmx/mbeanserver/PerInterface.java
Normal file
280
jdkSrc/jdk8/com/sun/jmx/mbeanserver/PerInterface.java
Normal file
@@ -0,0 +1,280 @@
|
||||
/*
|
||||
* Copyright (c) 2005, 2006, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package com.sun.jmx.mbeanserver;
|
||||
|
||||
import java.security.AccessController;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import javax.management.AttributeNotFoundException;
|
||||
import javax.management.InvalidAttributeValueException;
|
||||
import javax.management.MBeanException;
|
||||
import javax.management.MBeanInfo;
|
||||
import javax.management.ReflectionException;
|
||||
|
||||
import static com.sun.jmx.mbeanserver.Util.*;
|
||||
|
||||
/**
|
||||
* Per-MBean-interface behavior. A single instance of this class can be shared
|
||||
* by all MBeans of the same kind (Standard MBean or MXBean) that have the same
|
||||
* MBean interface.
|
||||
*
|
||||
* @since 1.6
|
||||
*/
|
||||
final class PerInterface<M> {
|
||||
PerInterface(Class<?> mbeanInterface, MBeanIntrospector<M> introspector,
|
||||
MBeanAnalyzer<M> analyzer, MBeanInfo mbeanInfo) {
|
||||
this.mbeanInterface = mbeanInterface;
|
||||
this.introspector = introspector;
|
||||
this.mbeanInfo = mbeanInfo;
|
||||
analyzer.visit(new InitMaps());
|
||||
}
|
||||
|
||||
Class<?> getMBeanInterface() {
|
||||
return mbeanInterface;
|
||||
}
|
||||
|
||||
MBeanInfo getMBeanInfo() {
|
||||
return mbeanInfo;
|
||||
}
|
||||
|
||||
boolean isMXBean() {
|
||||
return introspector.isMXBean();
|
||||
}
|
||||
|
||||
Object getAttribute(Object resource, String attribute, Object cookie)
|
||||
throws AttributeNotFoundException,
|
||||
MBeanException,
|
||||
ReflectionException {
|
||||
|
||||
final M cm = getters.get(attribute);
|
||||
if (cm == null) {
|
||||
final String msg;
|
||||
if (setters.containsKey(attribute))
|
||||
msg = "Write-only attribute: " + attribute;
|
||||
else
|
||||
msg = "No such attribute: " + attribute;
|
||||
throw new AttributeNotFoundException(msg);
|
||||
}
|
||||
return introspector.invokeM(cm, resource, (Object[]) null, cookie);
|
||||
}
|
||||
|
||||
void setAttribute(Object resource, String attribute, Object value,
|
||||
Object cookie)
|
||||
throws AttributeNotFoundException,
|
||||
InvalidAttributeValueException,
|
||||
MBeanException,
|
||||
ReflectionException {
|
||||
|
||||
final M cm = setters.get(attribute);
|
||||
if (cm == null) {
|
||||
final String msg;
|
||||
if (getters.containsKey(attribute))
|
||||
msg = "Read-only attribute: " + attribute;
|
||||
else
|
||||
msg = "No such attribute: " + attribute;
|
||||
throw new AttributeNotFoundException(msg);
|
||||
}
|
||||
introspector.invokeSetter(attribute, cm, resource, value, cookie);
|
||||
}
|
||||
|
||||
Object invoke(Object resource, String operation, Object[] params,
|
||||
String[] signature, Object cookie)
|
||||
throws MBeanException, ReflectionException {
|
||||
|
||||
final List<MethodAndSig> list = ops.get(operation);
|
||||
if (list == null) {
|
||||
final String msg = "No such operation: " + operation;
|
||||
return noSuchMethod(msg, resource, operation, params, signature,
|
||||
cookie);
|
||||
}
|
||||
if (signature == null)
|
||||
signature = new String[0];
|
||||
MethodAndSig found = null;
|
||||
for (MethodAndSig mas : list) {
|
||||
if (Arrays.equals(mas.signature, signature)) {
|
||||
found = mas;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (found == null) {
|
||||
final String badSig = sigString(signature);
|
||||
final String msg;
|
||||
if (list.size() == 1) { // helpful exception message
|
||||
msg = "Signature mismatch for operation " + operation +
|
||||
": " + badSig + " should be " +
|
||||
sigString(list.get(0).signature);
|
||||
} else {
|
||||
msg = "Operation " + operation + " exists but not with " +
|
||||
"this signature: " + badSig;
|
||||
}
|
||||
return noSuchMethod(msg, resource, operation, params, signature,
|
||||
cookie);
|
||||
}
|
||||
return introspector.invokeM(found.method, resource, params, cookie);
|
||||
}
|
||||
|
||||
/*
|
||||
* This method is called when invoke doesn't find the named method.
|
||||
* Before throwing an exception, we check to see whether the
|
||||
* jmx.invoke.getters property is set, and if so whether the method
|
||||
* being invoked might be a getter or a setter. If so we invoke it
|
||||
* and return the result. This is for compatibility
|
||||
* with code based on JMX RI 1.0 or 1.1 which allowed invoking getters
|
||||
* and setters. It is *not* recommended that new code use this feature.
|
||||
*
|
||||
* Since this method is either going to throw an exception or use
|
||||
* functionality that is strongly discouraged, we consider that its
|
||||
* performance is not very important.
|
||||
*
|
||||
* A simpler way to implement the functionality would be to add the getters
|
||||
* and setters to the operations map when jmx.invoke.getters is set.
|
||||
* However, that means that the property is consulted when an MBean
|
||||
* interface is being introspected and not thereafter. Previously,
|
||||
* the property was consulted on every invocation. So this simpler
|
||||
* implementation could potentially break code that sets and unsets
|
||||
* the property at different times.
|
||||
*/
|
||||
private Object noSuchMethod(String msg, Object resource, String operation,
|
||||
Object[] params, String[] signature,
|
||||
Object cookie)
|
||||
throws MBeanException, ReflectionException {
|
||||
|
||||
// Construct the exception that we will probably throw
|
||||
final NoSuchMethodException nsme =
|
||||
new NoSuchMethodException(operation + sigString(signature));
|
||||
final ReflectionException exception =
|
||||
new ReflectionException(nsme, msg);
|
||||
|
||||
if (introspector.isMXBean())
|
||||
throw exception; // No compatibility requirement here
|
||||
|
||||
// Is the compatibility property set?
|
||||
GetPropertyAction act = new GetPropertyAction("jmx.invoke.getters");
|
||||
String invokeGettersS;
|
||||
try {
|
||||
invokeGettersS = AccessController.doPrivileged(act);
|
||||
} catch (Exception e) {
|
||||
// We don't expect an exception here but if we get one then
|
||||
// we'll simply assume that the property is not set.
|
||||
invokeGettersS = null;
|
||||
}
|
||||
if (invokeGettersS == null)
|
||||
throw exception;
|
||||
|
||||
int rest = 0;
|
||||
Map<String, M> methods = null;
|
||||
if (signature == null || signature.length == 0) {
|
||||
if (operation.startsWith("get"))
|
||||
rest = 3;
|
||||
else if (operation.startsWith("is"))
|
||||
rest = 2;
|
||||
if (rest != 0)
|
||||
methods = getters;
|
||||
} else if (signature.length == 1 &&
|
||||
operation.startsWith("set")) {
|
||||
rest = 3;
|
||||
methods = setters;
|
||||
}
|
||||
|
||||
if (rest != 0) {
|
||||
String attrName = operation.substring(rest);
|
||||
M method = methods.get(attrName);
|
||||
if (method != null && introspector.getName(method).equals(operation)) {
|
||||
String[] msig = introspector.getSignature(method);
|
||||
if ((signature == null && msig.length == 0) ||
|
||||
Arrays.equals(signature, msig)) {
|
||||
return introspector.invokeM(method, resource, params, cookie);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
throw exception;
|
||||
}
|
||||
|
||||
private String sigString(String[] signature) {
|
||||
StringBuilder b = new StringBuilder("(");
|
||||
if (signature != null) {
|
||||
for (String s : signature) {
|
||||
if (b.length() > 1)
|
||||
b.append(", ");
|
||||
b.append(s);
|
||||
}
|
||||
}
|
||||
return b.append(")").toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Visitor that sets up the method maps (operations, getters, setters).
|
||||
*/
|
||||
private class InitMaps implements MBeanAnalyzer.MBeanVisitor<M> {
|
||||
public void visitAttribute(String attributeName,
|
||||
M getter,
|
||||
M setter) {
|
||||
if (getter != null) {
|
||||
introspector.checkMethod(getter);
|
||||
final Object old = getters.put(attributeName, getter);
|
||||
assert(old == null);
|
||||
}
|
||||
if (setter != null) {
|
||||
introspector.checkMethod(setter);
|
||||
final Object old = setters.put(attributeName, setter);
|
||||
assert(old == null);
|
||||
}
|
||||
}
|
||||
|
||||
public void visitOperation(String operationName,
|
||||
M operation) {
|
||||
introspector.checkMethod(operation);
|
||||
final String[] sig = introspector.getSignature(operation);
|
||||
final MethodAndSig mas = new MethodAndSig();
|
||||
mas.method = operation;
|
||||
mas.signature = sig;
|
||||
List<MethodAndSig> list = ops.get(operationName);
|
||||
if (list == null)
|
||||
list = Collections.singletonList(mas);
|
||||
else {
|
||||
if (list.size() == 1)
|
||||
list = newList(list);
|
||||
list.add(mas);
|
||||
}
|
||||
ops.put(operationName, list);
|
||||
}
|
||||
}
|
||||
|
||||
private class MethodAndSig {
|
||||
M method;
|
||||
String[] signature;
|
||||
}
|
||||
|
||||
private final Class<?> mbeanInterface;
|
||||
private final MBeanIntrospector<M> introspector;
|
||||
private final MBeanInfo mbeanInfo;
|
||||
private final Map<String, M> getters = newMap();
|
||||
private final Map<String, M> setters = newMap();
|
||||
private final Map<String, List<MethodAndSig>> ops = newMap();
|
||||
}
|
||||
678
jdkSrc/jdk8/com/sun/jmx/mbeanserver/Repository.java
Normal file
678
jdkSrc/jdk8/com/sun/jmx/mbeanserver/Repository.java
Normal file
@@ -0,0 +1,678 @@
|
||||
/*
|
||||
* Copyright (c) 1999, 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.mbeanserver;
|
||||
|
||||
import com.sun.jmx.defaults.ServiceName;
|
||||
import static com.sun.jmx.defaults.JmxProperties.MBEANSERVER_LOGGER;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.locks.ReentrantReadWriteLock;
|
||||
import java.util.logging.Level;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import javax.management.DynamicMBean;
|
||||
import javax.management.InstanceAlreadyExistsException;
|
||||
import javax.management.InstanceNotFoundException;
|
||||
import javax.management.ObjectName;
|
||||
import javax.management.QueryExp;
|
||||
import javax.management.RuntimeOperationsException;
|
||||
|
||||
/**
|
||||
* This repository does not support persistency.
|
||||
*
|
||||
* @since 1.5
|
||||
*/
|
||||
public class Repository {
|
||||
|
||||
/**
|
||||
* An interface that allows the caller to get some control
|
||||
* over the registration.
|
||||
* @see #addMBean
|
||||
* @see #remove
|
||||
*/
|
||||
public interface RegistrationContext {
|
||||
/**
|
||||
* Called by {@link #addMBean}.
|
||||
* Can throw a RuntimeOperationsException to cancel the
|
||||
* registration.
|
||||
*/
|
||||
public void registering();
|
||||
|
||||
/**
|
||||
* Called by {@link #remove}.
|
||||
* Any exception thrown by this method will be ignored.
|
||||
*/
|
||||
public void unregistered();
|
||||
}
|
||||
|
||||
// Private fields -------------------------------------------->
|
||||
|
||||
/**
|
||||
* The structure for storing the objects is very basic.
|
||||
* A Hashtable is used for storing the different domains
|
||||
* For each domain, a hashtable contains the instances with
|
||||
* canonical key property list string as key and named object
|
||||
* aggregated from given object name and mbean instance as value.
|
||||
*/
|
||||
private final Map<String,Map<String,NamedObject>> domainTb;
|
||||
|
||||
/**
|
||||
* Number of elements contained in the Repository
|
||||
*/
|
||||
private volatile int nbElements = 0;
|
||||
|
||||
/**
|
||||
* Domain name of the server the repository is attached to.
|
||||
* It is quicker to store the information in the repository rather
|
||||
* than querying the framework each time the info is required.
|
||||
*/
|
||||
private final String domain;
|
||||
|
||||
/**
|
||||
* We use a global reentrant read write lock to protect the repository.
|
||||
* This seems safer and more efficient: we are using Maps of Maps,
|
||||
* Guaranteing consistency while using Concurent objects at each level
|
||||
* may be more difficult.
|
||||
**/
|
||||
private final ReentrantReadWriteLock lock;
|
||||
|
||||
// Private fields <=============================================
|
||||
|
||||
// Private methods --------------------------------------------->
|
||||
|
||||
/* This class is used to match an ObjectName against a pattern. */
|
||||
private final static class ObjectNamePattern {
|
||||
private final String[] keys;
|
||||
private final String[] values;
|
||||
private final String properties;
|
||||
private final boolean isPropertyListPattern;
|
||||
private final boolean isPropertyValuePattern;
|
||||
|
||||
/**
|
||||
* The ObjectName pattern against which ObjectNames are matched.
|
||||
**/
|
||||
public final ObjectName pattern;
|
||||
|
||||
/**
|
||||
* Builds a new ObjectNamePattern object from an ObjectName pattern.
|
||||
* @param pattern The ObjectName pattern under examination.
|
||||
**/
|
||||
public ObjectNamePattern(ObjectName pattern) {
|
||||
this(pattern.isPropertyListPattern(),
|
||||
pattern.isPropertyValuePattern(),
|
||||
pattern.getCanonicalKeyPropertyListString(),
|
||||
pattern.getKeyPropertyList(),
|
||||
pattern);
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds a new ObjectNamePattern object from an ObjectName pattern
|
||||
* constituents.
|
||||
* @param propertyListPattern pattern.isPropertyListPattern().
|
||||
* @param propertyValuePattern pattern.isPropertyValuePattern().
|
||||
* @param canonicalProps pattern.getCanonicalKeyPropertyListString().
|
||||
* @param keyPropertyList pattern.getKeyPropertyList().
|
||||
* @param pattern The ObjectName pattern under examination.
|
||||
**/
|
||||
ObjectNamePattern(boolean propertyListPattern,
|
||||
boolean propertyValuePattern,
|
||||
String canonicalProps,
|
||||
Map<String,String> keyPropertyList,
|
||||
ObjectName pattern) {
|
||||
this.isPropertyListPattern = propertyListPattern;
|
||||
this.isPropertyValuePattern = propertyValuePattern;
|
||||
this.properties = canonicalProps;
|
||||
final int len = keyPropertyList.size();
|
||||
this.keys = new String[len];
|
||||
this.values = new String[len];
|
||||
int i = 0;
|
||||
for (Map.Entry<String,String> entry : keyPropertyList.entrySet()) {
|
||||
keys[i] = entry.getKey();
|
||||
values[i] = entry.getValue();
|
||||
i++;
|
||||
}
|
||||
this.pattern = pattern;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if the given ObjectName matches the ObjectName pattern
|
||||
* for which this object has been built.
|
||||
* WARNING: domain name is not considered here because it is supposed
|
||||
* not to be wildcard when called. PropertyList is also
|
||||
* supposed not to be zero-length.
|
||||
* @param name The ObjectName we want to match against the pattern.
|
||||
* @return true if <code>name</code> matches the pattern.
|
||||
**/
|
||||
public boolean matchKeys(ObjectName name) {
|
||||
// If key property value pattern but not key property list
|
||||
// pattern, then the number of key properties must be equal
|
||||
//
|
||||
if (isPropertyValuePattern &&
|
||||
!isPropertyListPattern &&
|
||||
(name.getKeyPropertyList().size() != keys.length))
|
||||
return false;
|
||||
|
||||
// If key property value pattern or key property list pattern,
|
||||
// then every property inside pattern should exist in name
|
||||
//
|
||||
if (isPropertyValuePattern || isPropertyListPattern) {
|
||||
for (int i = keys.length - 1; i >= 0 ; i--) {
|
||||
// Find value in given object name for key at current
|
||||
// index in receiver
|
||||
//
|
||||
String v = name.getKeyProperty(keys[i]);
|
||||
// Did we find a value for this key ?
|
||||
//
|
||||
if (v == null) return false;
|
||||
// If this property is ok (same key, same value), go to next
|
||||
//
|
||||
if (isPropertyValuePattern &&
|
||||
pattern.isPropertyValuePattern(keys[i])) {
|
||||
// wildmatch key property values
|
||||
// values[i] is the pattern;
|
||||
// v is the string
|
||||
if (Util.wildmatch(v,values[i]))
|
||||
continue;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
if (v.equals(values[i])) continue;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// If no pattern, then canonical names must be equal
|
||||
//
|
||||
final String p1 = name.getCanonicalKeyPropertyListString();
|
||||
final String p2 = properties;
|
||||
return (p1.equals(p2));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add all the matching objects from the given hashtable in the
|
||||
* result set for the given ObjectNamePattern
|
||||
* Do not check whether the domains match (only check for matching
|
||||
* key property lists - see <i>matchKeys()</i>)
|
||||
**/
|
||||
private void addAllMatching(final Map<String,NamedObject> moiTb,
|
||||
final Set<NamedObject> result,
|
||||
final ObjectNamePattern pattern) {
|
||||
synchronized (moiTb) {
|
||||
for (NamedObject no : moiTb.values()) {
|
||||
final ObjectName on = no.getName();
|
||||
// if all couples (property, value) are contained
|
||||
if (pattern.matchKeys(on)) result.add(no);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void addNewDomMoi(final DynamicMBean object,
|
||||
final String dom,
|
||||
final ObjectName name,
|
||||
final RegistrationContext context) {
|
||||
final Map<String,NamedObject> moiTb =
|
||||
new HashMap<String,NamedObject>();
|
||||
final String key = name.getCanonicalKeyPropertyListString();
|
||||
addMoiToTb(object,name,key,moiTb,context);
|
||||
domainTb.put(dom, moiTb);
|
||||
nbElements++;
|
||||
}
|
||||
|
||||
private void registering(RegistrationContext context) {
|
||||
if (context == null) return;
|
||||
try {
|
||||
context.registering();
|
||||
} catch (RuntimeOperationsException x) {
|
||||
throw x;
|
||||
} catch (RuntimeException x) {
|
||||
throw new RuntimeOperationsException(x);
|
||||
}
|
||||
}
|
||||
|
||||
private void unregistering(RegistrationContext context, ObjectName name) {
|
||||
if (context == null) return;
|
||||
try {
|
||||
context.unregistered();
|
||||
} catch (Exception x) {
|
||||
// shouldn't come here...
|
||||
MBEANSERVER_LOGGER.log(Level.FINE,
|
||||
"Unexpected exception while unregistering "+name,
|
||||
x);
|
||||
}
|
||||
}
|
||||
|
||||
private void addMoiToTb(final DynamicMBean object,
|
||||
final ObjectName name,
|
||||
final String key,
|
||||
final Map<String,NamedObject> moiTb,
|
||||
final RegistrationContext context) {
|
||||
registering(context);
|
||||
moiTb.put(key,new NamedObject(name, object));
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the named object contained in repository
|
||||
* from the given objectname.
|
||||
*/
|
||||
private NamedObject retrieveNamedObject(ObjectName name) {
|
||||
|
||||
// No patterns inside reposit
|
||||
if (name.isPattern()) return null;
|
||||
|
||||
// Extract the domain name.
|
||||
String dom = name.getDomain().intern();
|
||||
|
||||
// Default domain case
|
||||
if (dom.length() == 0) {
|
||||
dom = domain;
|
||||
}
|
||||
|
||||
Map<String,NamedObject> moiTb = domainTb.get(dom);
|
||||
if (moiTb == null) {
|
||||
return null; // No domain containing registered object names
|
||||
}
|
||||
|
||||
return moiTb.get(name.getCanonicalKeyPropertyListString());
|
||||
}
|
||||
|
||||
// Private methods <=============================================
|
||||
|
||||
// Protected methods --------------------------------------------->
|
||||
|
||||
// Protected methods <=============================================
|
||||
|
||||
// Public methods --------------------------------------------->
|
||||
|
||||
/**
|
||||
* Construct a new repository with the given default domain.
|
||||
*/
|
||||
public Repository(String domain) {
|
||||
this(domain,true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct a new repository with the given default domain.
|
||||
*/
|
||||
public Repository(String domain, boolean fairLock) {
|
||||
lock = new ReentrantReadWriteLock(fairLock);
|
||||
|
||||
domainTb = new HashMap<String,Map<String,NamedObject>>(5);
|
||||
|
||||
if (domain != null && domain.length() != 0)
|
||||
this.domain = domain.intern(); // we use == domain later on...
|
||||
else
|
||||
this.domain = ServiceName.DOMAIN;
|
||||
|
||||
// Creates a new hashtable for the default domain
|
||||
domainTb.put(this.domain, new HashMap<String,NamedObject>());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the list of domains in which any MBean is currently
|
||||
* registered.
|
||||
*
|
||||
*/
|
||||
public String[] getDomains() {
|
||||
|
||||
lock.readLock().lock();
|
||||
final List<String> result;
|
||||
try {
|
||||
// Temporary list
|
||||
result = new ArrayList<String>(domainTb.size());
|
||||
for (Map.Entry<String,Map<String,NamedObject>> entry :
|
||||
domainTb.entrySet()) {
|
||||
// Skip domains that are in the table but have no
|
||||
// MBean registered in them
|
||||
// in particular the default domain may be like this
|
||||
Map<String,NamedObject> t = entry.getValue();
|
||||
if (t != null && t.size() != 0)
|
||||
result.add(entry.getKey());
|
||||
}
|
||||
} finally {
|
||||
lock.readLock().unlock();
|
||||
}
|
||||
|
||||
// Make an array from result.
|
||||
return result.toArray(new String[result.size()]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Stores an MBean associated with its object name in the repository.
|
||||
*
|
||||
* @param object MBean to be stored in the repository.
|
||||
* @param name MBean object name.
|
||||
* @param context A registration context. If non null, the repository
|
||||
* will call {@link RegistrationContext#registering()
|
||||
* context.registering()} from within the repository
|
||||
* lock, when it has determined that the {@code object}
|
||||
* can be stored in the repository with that {@code name}.
|
||||
* If {@link RegistrationContext#registering()
|
||||
* context.registering()} throws an exception, the
|
||||
* operation is abandonned, the MBean is not added to the
|
||||
* repository, and a {@link RuntimeOperationsException}
|
||||
* is thrown.
|
||||
*/
|
||||
public void addMBean(final DynamicMBean object, ObjectName name,
|
||||
final RegistrationContext context)
|
||||
throws InstanceAlreadyExistsException {
|
||||
|
||||
if (MBEANSERVER_LOGGER.isLoggable(Level.FINER)) {
|
||||
MBEANSERVER_LOGGER.logp(Level.FINER, Repository.class.getName(),
|
||||
"addMBean", "name = " + name);
|
||||
}
|
||||
|
||||
// Extract the domain name.
|
||||
String dom = name.getDomain().intern();
|
||||
boolean to_default_domain = false;
|
||||
|
||||
// Set domain to default if domain is empty and not already set
|
||||
if (dom.length() == 0)
|
||||
name = Util.newObjectName(domain + name.toString());
|
||||
|
||||
// Do we have default domain ?
|
||||
if (dom == domain) { // ES: OK (dom & domain are interned)
|
||||
to_default_domain = true;
|
||||
dom = domain;
|
||||
} else {
|
||||
to_default_domain = false;
|
||||
}
|
||||
|
||||
// Validate name for an object
|
||||
if (name.isPattern()) {
|
||||
throw new RuntimeOperationsException(
|
||||
new IllegalArgumentException("Repository: cannot add mbean for " +
|
||||
"pattern name " + name.toString()));
|
||||
}
|
||||
|
||||
lock.writeLock().lock();
|
||||
try {
|
||||
// Domain cannot be JMImplementation if entry does not exist
|
||||
if ( !to_default_domain &&
|
||||
dom.equals("JMImplementation") &&
|
||||
domainTb.containsKey("JMImplementation")) {
|
||||
throw new RuntimeOperationsException(
|
||||
new IllegalArgumentException(
|
||||
"Repository: domain name cannot be JMImplementation"));
|
||||
}
|
||||
|
||||
// If domain does not already exist, add it to the hash table
|
||||
final Map<String,NamedObject> moiTb = domainTb.get(dom);
|
||||
if (moiTb == null) {
|
||||
addNewDomMoi(object, dom, name, context);
|
||||
return;
|
||||
} else {
|
||||
// Add instance if not already present
|
||||
String cstr = name.getCanonicalKeyPropertyListString();
|
||||
NamedObject elmt= moiTb.get(cstr);
|
||||
if (elmt != null) {
|
||||
throw new InstanceAlreadyExistsException(name.toString());
|
||||
} else {
|
||||
nbElements++;
|
||||
addMoiToTb(object,name,cstr,moiTb,context);
|
||||
}
|
||||
}
|
||||
|
||||
} finally {
|
||||
lock.writeLock().unlock();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether an MBean of the name specified is already stored in
|
||||
* the repository.
|
||||
*
|
||||
* @param name name of the MBean to find.
|
||||
*
|
||||
* @return true if the MBean is stored in the repository,
|
||||
* false otherwise.
|
||||
*/
|
||||
public boolean contains(ObjectName name) {
|
||||
if (MBEANSERVER_LOGGER.isLoggable(Level.FINER)) {
|
||||
MBEANSERVER_LOGGER.logp(Level.FINER, Repository.class.getName(),
|
||||
"contains", " name = " + name);
|
||||
}
|
||||
lock.readLock().lock();
|
||||
try {
|
||||
return (retrieveNamedObject(name) != null);
|
||||
} finally {
|
||||
lock.readLock().unlock();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the MBean of the name specified from the repository. The
|
||||
* object name must match exactly.
|
||||
*
|
||||
* @param name name of the MBean to retrieve.
|
||||
*
|
||||
* @return The retrieved MBean if it is contained in the repository,
|
||||
* null otherwise.
|
||||
*/
|
||||
public DynamicMBean retrieve(ObjectName name) {
|
||||
if (MBEANSERVER_LOGGER.isLoggable(Level.FINER)) {
|
||||
MBEANSERVER_LOGGER.logp(Level.FINER, Repository.class.getName(),
|
||||
"retrieve", "name = " + name);
|
||||
}
|
||||
|
||||
// Calls internal retrieve method to get the named object
|
||||
lock.readLock().lock();
|
||||
try {
|
||||
NamedObject no = retrieveNamedObject(name);
|
||||
if (no == null) return null;
|
||||
else return no.getObject();
|
||||
} finally {
|
||||
lock.readLock().unlock();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Selects and retrieves the list of MBeans whose names match the specified
|
||||
* object name pattern and which match the specified query expression
|
||||
* (optionally).
|
||||
*
|
||||
* @param pattern The name of the MBean(s) to retrieve - may be a specific
|
||||
* object or a name pattern allowing multiple MBeans to be selected.
|
||||
* @param query query expression to apply when selecting objects - this
|
||||
* parameter will be ignored when the Repository Service does not
|
||||
* support filtering.
|
||||
*
|
||||
* @return The list of MBeans selected. There may be zero, one or many
|
||||
* MBeans returned in the set.
|
||||
*/
|
||||
public Set<NamedObject> query(ObjectName pattern, QueryExp query) {
|
||||
|
||||
final Set<NamedObject> result = new HashSet<NamedObject>();
|
||||
|
||||
// The following filter cases are considered:
|
||||
// null, "", "*:*" : names in all domains
|
||||
// ":*", ":[key=value],*" : names in defaultDomain
|
||||
// "domain:*", "domain:[key=value],*" : names in the specified domain
|
||||
|
||||
// Surely one of the most frequent cases ... query on the whole world
|
||||
ObjectName name;
|
||||
if (pattern == null ||
|
||||
pattern.getCanonicalName().length() == 0 ||
|
||||
pattern.equals(ObjectName.WILDCARD))
|
||||
name = ObjectName.WILDCARD;
|
||||
else name = pattern;
|
||||
|
||||
lock.readLock().lock();
|
||||
try {
|
||||
|
||||
// If pattern is not a pattern, retrieve this mbean !
|
||||
if (!name.isPattern()) {
|
||||
final NamedObject no = retrieveNamedObject(name);
|
||||
if (no != null) result.add(no);
|
||||
return result;
|
||||
}
|
||||
|
||||
// All names in all domains
|
||||
if (name == ObjectName.WILDCARD) {
|
||||
for (Map<String,NamedObject> moiTb : domainTb.values()) {
|
||||
result.addAll(moiTb.values());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
final String canonical_key_property_list_string =
|
||||
name.getCanonicalKeyPropertyListString();
|
||||
final boolean allNames =
|
||||
(canonical_key_property_list_string.length()==0);
|
||||
final ObjectNamePattern namePattern =
|
||||
(allNames?null:new ObjectNamePattern(name));
|
||||
|
||||
// All names in default domain
|
||||
if (name.getDomain().length() == 0) {
|
||||
final Map<String,NamedObject> moiTb = domainTb.get(domain);
|
||||
if (allNames)
|
||||
result.addAll(moiTb.values());
|
||||
else
|
||||
addAllMatching(moiTb, result, namePattern);
|
||||
return result;
|
||||
}
|
||||
|
||||
if (!name.isDomainPattern()) {
|
||||
final Map<String,NamedObject> moiTb = domainTb.get(name.getDomain());
|
||||
if (moiTb == null) return Collections.emptySet();
|
||||
if (allNames)
|
||||
result.addAll(moiTb.values());
|
||||
else
|
||||
addAllMatching(moiTb, result, namePattern);
|
||||
return result;
|
||||
}
|
||||
|
||||
// Pattern matching in the domain name (*, ?)
|
||||
final String dom2Match = name.getDomain();
|
||||
for (String dom : domainTb.keySet()) {
|
||||
if (Util.wildmatch(dom, dom2Match)) {
|
||||
final Map<String,NamedObject> moiTb = domainTb.get(dom);
|
||||
if (allNames)
|
||||
result.addAll(moiTb.values());
|
||||
else
|
||||
addAllMatching(moiTb, result, namePattern);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
} finally {
|
||||
lock.readLock().unlock();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes an MBean from the repository.
|
||||
*
|
||||
* @param name name of the MBean to remove.
|
||||
* @param context A registration context. If non null, the repository
|
||||
* will call {@link RegistrationContext#unregistered()
|
||||
* context.unregistered()} from within the repository
|
||||
* lock, just after the mbean associated with
|
||||
* {@code name} is removed from the repository.
|
||||
* If {@link RegistrationContext#unregistered()
|
||||
* context.unregistered()} is not expected to throw any
|
||||
* exception. If it does, the exception is logged
|
||||
* and swallowed.
|
||||
*
|
||||
* @exception InstanceNotFoundException The MBean does not exist in
|
||||
* the repository.
|
||||
*/
|
||||
public void remove(final ObjectName name,
|
||||
final RegistrationContext context)
|
||||
throws InstanceNotFoundException {
|
||||
|
||||
// Debugging stuff
|
||||
if (MBEANSERVER_LOGGER.isLoggable(Level.FINER)) {
|
||||
MBEANSERVER_LOGGER.logp(Level.FINER, Repository.class.getName(),
|
||||
"remove", "name = " + name);
|
||||
}
|
||||
|
||||
// Extract domain name.
|
||||
String dom= name.getDomain().intern();
|
||||
|
||||
// Default domain case
|
||||
if (dom.length() == 0) dom = domain;
|
||||
|
||||
lock.writeLock().lock();
|
||||
try {
|
||||
// Find the domain subtable
|
||||
final Map<String,NamedObject> moiTb = domainTb.get(dom);
|
||||
if (moiTb == null) {
|
||||
throw new InstanceNotFoundException(name.toString());
|
||||
}
|
||||
|
||||
// Remove the corresponding element
|
||||
if (moiTb.remove(name.getCanonicalKeyPropertyListString())==null) {
|
||||
throw new InstanceNotFoundException(name.toString());
|
||||
}
|
||||
|
||||
// We removed it !
|
||||
nbElements--;
|
||||
|
||||
// No more object for this domain, we remove this domain hashtable
|
||||
if (moiTb.isEmpty()) {
|
||||
domainTb.remove(dom);
|
||||
|
||||
// set a new default domain table (always present)
|
||||
// need to reinstantiate a hashtable because of possible
|
||||
// big buckets array size inside table, never cleared,
|
||||
// thus the new !
|
||||
if (dom == domain) // ES: OK dom and domain are interned.
|
||||
domainTb.put(domain, new HashMap<String,NamedObject>());
|
||||
}
|
||||
|
||||
unregistering(context,name);
|
||||
|
||||
} finally {
|
||||
lock.writeLock().unlock();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the number of MBeans stored in the repository.
|
||||
*
|
||||
* @return Number of MBeans.
|
||||
*/
|
||||
public Integer getCount() {
|
||||
return nbElements;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the name of the domain currently used by default in the
|
||||
* repository.
|
||||
*
|
||||
* @return A string giving the name of the default domain name.
|
||||
*/
|
||||
public String getDefaultDomain() {
|
||||
return domain;
|
||||
}
|
||||
|
||||
// Public methods <=============================================
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
/*
|
||||
* Copyright (c) 2002, 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.mbeanserver;
|
||||
|
||||
import javax.management.loading.ClassLoaderRepository;
|
||||
|
||||
/**
|
||||
* Fix security hole in ClassLoaderRepository. This class wraps
|
||||
* the actual ClassLoaderRepository implementation so that
|
||||
* only the methods from {@link javax.management.loading.ClassLoaderRepository}
|
||||
* can be accessed (read-only).
|
||||
*
|
||||
* @since 1.5
|
||||
*/
|
||||
final class SecureClassLoaderRepository
|
||||
implements ClassLoaderRepository {
|
||||
|
||||
private final ClassLoaderRepository clr;
|
||||
/**
|
||||
* Creates a new secure ClassLoaderRepository wrapping an
|
||||
* unsecure implementation.
|
||||
* @param clr Unsecure {@link ClassLoaderRepository} implementation
|
||||
* to wrap.
|
||||
**/
|
||||
public SecureClassLoaderRepository(ClassLoaderRepository clr) {
|
||||
this.clr=clr;
|
||||
}
|
||||
public final Class<?> loadClass(String className)
|
||||
throws ClassNotFoundException {
|
||||
return clr.loadClass(className);
|
||||
}
|
||||
public final Class<?> loadClassWithout(ClassLoader loader,
|
||||
String className)
|
||||
throws ClassNotFoundException {
|
||||
return clr.loadClassWithout(loader,className);
|
||||
}
|
||||
public final Class<?> loadClassBefore(ClassLoader loader,
|
||||
String className)
|
||||
throws ClassNotFoundException {
|
||||
return clr.loadClassBefore(loader,className);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,193 @@
|
||||
/*
|
||||
* Copyright (c) 2005, 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 com.sun.jmx.mbeanserver;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.WeakHashMap;
|
||||
import javax.management.Descriptor;
|
||||
import javax.management.ImmutableDescriptor;
|
||||
import javax.management.IntrospectionException;
|
||||
import javax.management.MBeanAttributeInfo;
|
||||
import javax.management.MBeanException;
|
||||
import javax.management.MBeanOperationInfo;
|
||||
import javax.management.NotCompliantMBeanException;
|
||||
import javax.management.NotificationBroadcaster;
|
||||
import javax.management.NotificationBroadcasterSupport;
|
||||
import sun.reflect.misc.MethodUtil;
|
||||
|
||||
/**
|
||||
* @since 1.6
|
||||
*/
|
||||
class StandardMBeanIntrospector extends MBeanIntrospector<Method> {
|
||||
private static final StandardMBeanIntrospector instance =
|
||||
new StandardMBeanIntrospector();
|
||||
|
||||
static StandardMBeanIntrospector getInstance() {
|
||||
return instance;
|
||||
}
|
||||
|
||||
@Override
|
||||
PerInterfaceMap<Method> getPerInterfaceMap() {
|
||||
return perInterfaceMap;
|
||||
}
|
||||
|
||||
@Override
|
||||
MBeanInfoMap getMBeanInfoMap() {
|
||||
return mbeanInfoMap;
|
||||
}
|
||||
|
||||
@Override
|
||||
MBeanAnalyzer<Method> getAnalyzer(Class<?> mbeanInterface)
|
||||
throws NotCompliantMBeanException {
|
||||
return MBeanAnalyzer.analyzer(mbeanInterface, this);
|
||||
}
|
||||
|
||||
@Override
|
||||
boolean isMXBean() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
Method mFrom(Method m) {
|
||||
return m;
|
||||
}
|
||||
|
||||
@Override
|
||||
String getName(Method m) {
|
||||
return m.getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
Type getGenericReturnType(Method m) {
|
||||
return m.getGenericReturnType();
|
||||
}
|
||||
|
||||
@Override
|
||||
Type[] getGenericParameterTypes(Method m) {
|
||||
return m.getGenericParameterTypes();
|
||||
}
|
||||
|
||||
@Override
|
||||
String[] getSignature(Method m) {
|
||||
Class<?>[] params = m.getParameterTypes();
|
||||
String[] sig = new String[params.length];
|
||||
for (int i = 0; i < params.length; i++)
|
||||
sig[i] = params[i].getName();
|
||||
return sig;
|
||||
}
|
||||
|
||||
@Override
|
||||
void checkMethod(Method m) {
|
||||
}
|
||||
|
||||
@Override
|
||||
Object invokeM2(Method m, Object target, Object[] args, Object cookie)
|
||||
throws InvocationTargetException, IllegalAccessException,
|
||||
MBeanException {
|
||||
return MethodUtil.invoke(m, target, args);
|
||||
}
|
||||
|
||||
@Override
|
||||
boolean validParameter(Method m, Object value, int paramNo, Object cookie) {
|
||||
return isValidParameter(m, value, paramNo);
|
||||
}
|
||||
|
||||
@Override
|
||||
MBeanAttributeInfo getMBeanAttributeInfo(String attributeName,
|
||||
Method getter, Method setter) {
|
||||
|
||||
final String description = "Attribute exposed for management";
|
||||
try {
|
||||
return new MBeanAttributeInfo(attributeName, description,
|
||||
getter, setter);
|
||||
} catch (IntrospectionException e) {
|
||||
throw new RuntimeException(e); // should not happen
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
MBeanOperationInfo getMBeanOperationInfo(String operationName,
|
||||
Method operation) {
|
||||
final String description = "Operation exposed for management";
|
||||
return new MBeanOperationInfo(description, operation);
|
||||
}
|
||||
|
||||
@Override
|
||||
Descriptor getBasicMBeanDescriptor() {
|
||||
/* We don't bother saying mxbean=false, and we can't know whether
|
||||
the info is immutable until we know whether the MBean class
|
||||
(not interface) is a NotificationBroadcaster. */
|
||||
return ImmutableDescriptor.EMPTY_DESCRIPTOR;
|
||||
}
|
||||
|
||||
@Override
|
||||
Descriptor getMBeanDescriptor(Class<?> resourceClass) {
|
||||
boolean immutable = isDefinitelyImmutableInfo(resourceClass);
|
||||
return new ImmutableDescriptor("mxbean=false",
|
||||
"immutableInfo=" + immutable);
|
||||
}
|
||||
|
||||
/* Return true if and only if we can be sure that the given MBean implementation
|
||||
* class has immutable MBeanInfo. A Standard MBean that is a
|
||||
* NotificationBroadcaster is allowed to return different values at
|
||||
* different times from its getNotificationInfo() method, which is when
|
||||
* we might not know if it is immutable. But if it is a subclass of
|
||||
* NotificationBroadcasterSupport and does not override
|
||||
* getNotificationInfo(), then we know it won't change.
|
||||
*/
|
||||
static boolean isDefinitelyImmutableInfo(Class<?> implClass) {
|
||||
if (!NotificationBroadcaster.class.isAssignableFrom(implClass))
|
||||
return true;
|
||||
synchronized (definitelyImmutable) {
|
||||
Boolean immutable = definitelyImmutable.get(implClass);
|
||||
if (immutable == null) {
|
||||
final Class<NotificationBroadcasterSupport> nbs =
|
||||
NotificationBroadcasterSupport.class;
|
||||
if (nbs.isAssignableFrom(implClass)) {
|
||||
try {
|
||||
Method m = implClass.getMethod("getNotificationInfo");
|
||||
immutable = (m.getDeclaringClass() == nbs);
|
||||
} catch (Exception e) {
|
||||
// Too bad, we'll say no for now.
|
||||
return false;
|
||||
}
|
||||
} else
|
||||
immutable = false;
|
||||
definitelyImmutable.put(implClass, immutable);
|
||||
}
|
||||
return immutable;
|
||||
}
|
||||
}
|
||||
private static final WeakHashMap<Class<?>, Boolean> definitelyImmutable =
|
||||
new WeakHashMap<Class<?>, Boolean>();
|
||||
|
||||
private static final PerInterfaceMap<Method>
|
||||
perInterfaceMap = new PerInterfaceMap<Method>();
|
||||
|
||||
private static final MBeanInfoMap mbeanInfoMap = new MBeanInfoMap();
|
||||
}
|
||||
@@ -0,0 +1,95 @@
|
||||
/*
|
||||
* Copyright (c) 2005, 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.mbeanserver;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
import javax.management.MBeanInfo;
|
||||
import javax.management.MBeanServer;
|
||||
import javax.management.NotCompliantMBeanException;
|
||||
import javax.management.ObjectName;
|
||||
|
||||
/**
|
||||
* Base class for Standard MBeans.
|
||||
*
|
||||
* @since 1.6
|
||||
*/
|
||||
public class StandardMBeanSupport extends MBeanSupport<Method> {
|
||||
|
||||
/**
|
||||
* <p>Construct a Standard MBean that wraps the given resource using the
|
||||
* given Standard MBean interface.</p>
|
||||
*
|
||||
* @param resource the underlying resource for the new MBean.
|
||||
* @param mbeanInterfaceType the class or interface to be used to determine
|
||||
* the MBean's management interface. An interface if this is a
|
||||
* classic Standard MBean; a class if this is a {@code @ManagedResource}.
|
||||
* @param <T> a type parameter that allows the compiler to check
|
||||
* that {@code resource} implements {@code mbeanInterfaceType},
|
||||
* provided that {@code mbeanInterfaceType} is a class constant like
|
||||
* {@code SomeMBean.class}.
|
||||
* @throws IllegalArgumentException if {@code resource} is null or
|
||||
* if it does not implement the class {@code mbeanInterfaceType} or if
|
||||
* that class is not a valid Standard MBean interface.
|
||||
*/
|
||||
public <T> StandardMBeanSupport(T resource, Class<T> mbeanInterfaceType)
|
||||
throws NotCompliantMBeanException {
|
||||
super(resource, mbeanInterfaceType);
|
||||
}
|
||||
|
||||
@Override
|
||||
MBeanIntrospector<Method> getMBeanIntrospector() {
|
||||
return StandardMBeanIntrospector.getInstance();
|
||||
}
|
||||
|
||||
@Override
|
||||
Object getCookie() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void register(MBeanServer mbs, ObjectName name) {}
|
||||
|
||||
@Override
|
||||
public void unregister() {}
|
||||
|
||||
/* Standard MBeans that are NotificationBroadcasters can return a different
|
||||
* MBeanNotificationInfo[] every time getMBeanInfo() is called, so we have
|
||||
* to reconstruct this MBeanInfo if necessary.
|
||||
*/
|
||||
@Override
|
||||
public MBeanInfo getMBeanInfo() {
|
||||
MBeanInfo mbi = super.getMBeanInfo();
|
||||
Class<?> resourceClass = getResource().getClass();
|
||||
if (StandardMBeanIntrospector.isDefinitelyImmutableInfo(resourceClass))
|
||||
return mbi;
|
||||
return new MBeanInfo(mbi.getClassName(), mbi.getDescription(),
|
||||
mbi.getAttributes(), mbi.getConstructors(),
|
||||
mbi.getOperations(),
|
||||
MBeanIntrospector.findNotifications(getResource()),
|
||||
mbi.getDescriptor());
|
||||
}
|
||||
}
|
||||
90
jdkSrc/jdk8/com/sun/jmx/mbeanserver/SunJmxMBeanServer.java
Normal file
90
jdkSrc/jdk8/com/sun/jmx/mbeanserver/SunJmxMBeanServer.java
Normal file
@@ -0,0 +1,90 @@
|
||||
/*
|
||||
* Copyright (c) 2000, 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.mbeanserver;
|
||||
|
||||
import javax.management.MBeanServer;
|
||||
import javax.management.MBeanServerDelegate;
|
||||
|
||||
|
||||
/**
|
||||
* Extends the MBeanServer interface to
|
||||
* provide methods for getting the MetaData and MBeanServerInstantiator
|
||||
* objects associated with an MBeanServer.
|
||||
*
|
||||
* @since 1.5
|
||||
*/
|
||||
public interface SunJmxMBeanServer
|
||||
extends MBeanServer {
|
||||
|
||||
/**
|
||||
* Return the MBeanInstantiator associated to this MBeanServer.
|
||||
* @exception UnsupportedOperationException if
|
||||
* {@link MBeanServerInterceptor}s
|
||||
* are not enabled on this object.
|
||||
* @see #interceptorsEnabled
|
||||
*/
|
||||
public MBeanInstantiator getMBeanInstantiator();
|
||||
|
||||
/**
|
||||
* Tell whether {@link MBeanServerInterceptor}s are enabled on this
|
||||
* object.
|
||||
* @return <code>true</code> if {@link MBeanServerInterceptor}s are
|
||||
* enabled.
|
||||
* @see #getMBeanServerInterceptor
|
||||
* @see #setMBeanServerInterceptor
|
||||
* @see #getMBeanInstantiator
|
||||
* @see com.sun.jmx.mbeanserver.JmxMBeanServerBuilder
|
||||
**/
|
||||
public boolean interceptorsEnabled();
|
||||
|
||||
/**
|
||||
* Return the MBeanServerInterceptor.
|
||||
* @exception UnsupportedOperationException if
|
||||
* {@link MBeanServerInterceptor}s
|
||||
* are not enabled on this object.
|
||||
* @see #interceptorsEnabled
|
||||
**/
|
||||
public MBeanServer getMBeanServerInterceptor();
|
||||
|
||||
/**
|
||||
* Set the MBeanServerInterceptor.
|
||||
* @exception UnsupportedOperationException if
|
||||
* {@link MBeanServerInterceptor}s
|
||||
* are not enabled on this object.
|
||||
* @see #interceptorsEnabled
|
||||
**/
|
||||
public void setMBeanServerInterceptor(MBeanServer interceptor);
|
||||
|
||||
/**
|
||||
* <p>Return the MBeanServerDelegate representing the MBeanServer.
|
||||
* Notifications can be sent from the MBean server delegate using
|
||||
* the method {@link MBeanServerDelegate#sendNotification}
|
||||
* in the returned object.</p>
|
||||
*
|
||||
*/
|
||||
public MBeanServerDelegate getMBeanServerDelegate();
|
||||
|
||||
}
|
||||
241
jdkSrc/jdk8/com/sun/jmx/mbeanserver/Util.java
Normal file
241
jdkSrc/jdk8/com/sun/jmx/mbeanserver/Util.java
Normal file
@@ -0,0 +1,241 @@
|
||||
/*
|
||||
* Copyright (c) 2005, 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.mbeanserver;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.IdentityHashMap;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.SortedMap;
|
||||
import java.util.TreeMap;
|
||||
import javax.management.MalformedObjectNameException;
|
||||
import javax.management.ObjectName;
|
||||
|
||||
public class Util {
|
||||
public static ObjectName newObjectName(String string) {
|
||||
try {
|
||||
return new ObjectName(string);
|
||||
} catch (MalformedObjectNameException e) {
|
||||
throw new IllegalArgumentException(e);
|
||||
}
|
||||
}
|
||||
|
||||
static <K, V> Map<K, V> newMap() {
|
||||
return new HashMap<K, V>();
|
||||
}
|
||||
|
||||
static <K, V> Map<K, V> newSynchronizedMap() {
|
||||
return Collections.synchronizedMap(Util.<K, V>newMap());
|
||||
}
|
||||
|
||||
static <K, V> IdentityHashMap<K, V> newIdentityHashMap() {
|
||||
return new IdentityHashMap<K, V>();
|
||||
}
|
||||
|
||||
static <K, V> Map<K, V> newSynchronizedIdentityHashMap() {
|
||||
Map<K, V> map = newIdentityHashMap();
|
||||
return Collections.synchronizedMap(map);
|
||||
}
|
||||
|
||||
static <K, V> SortedMap<K, V> newSortedMap() {
|
||||
return new TreeMap<K, V>();
|
||||
}
|
||||
|
||||
static <K, V> SortedMap<K, V> newSortedMap(Comparator<? super K> comp) {
|
||||
return new TreeMap<K, V>(comp);
|
||||
}
|
||||
|
||||
static <K, V> Map<K, V> newInsertionOrderMap() {
|
||||
return new LinkedHashMap<K, V>();
|
||||
}
|
||||
|
||||
static <E> Set<E> newSet() {
|
||||
return new HashSet<E>();
|
||||
}
|
||||
|
||||
static <E> Set<E> newSet(Collection<E> c) {
|
||||
return new HashSet<E>(c);
|
||||
}
|
||||
|
||||
static <E> List<E> newList() {
|
||||
return new ArrayList<E>();
|
||||
}
|
||||
|
||||
static <E> List<E> newList(Collection<E> c) {
|
||||
return new ArrayList<E>(c);
|
||||
}
|
||||
|
||||
/* This method can be used by code that is deliberately violating the
|
||||
* allowed checked casts. Rather than marking the whole method containing
|
||||
* the code with @SuppressWarnings, you can use a call to this method for
|
||||
* the exact place where you need to escape the constraints. Typically
|
||||
* you will "import static" this method and then write either
|
||||
* X x = cast(y);
|
||||
* or, if that doesn't work (e.g. X is a type variable)
|
||||
* Util.<X>cast(y);
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public static <T> T cast(Object x) {
|
||||
return (T) x;
|
||||
}
|
||||
|
||||
/**
|
||||
* Computes a descriptor hashcode from its names and values.
|
||||
* @param names the sorted array of descriptor names.
|
||||
* @param values the array of descriptor values.
|
||||
* @return a hash code value, as described in {@link #hashCode(Descriptor)}
|
||||
*/
|
||||
public static int hashCode(String[] names, Object[] values) {
|
||||
int hash = 0;
|
||||
for (int i = 0; i < names.length; i++) {
|
||||
Object v = values[i];
|
||||
int h;
|
||||
if (v == null) {
|
||||
h = 0;
|
||||
} else if (v instanceof Object[]) {
|
||||
h = Arrays.deepHashCode((Object[]) v);
|
||||
} else if (v.getClass().isArray()) {
|
||||
h = Arrays.deepHashCode(new Object[]{v}) - 31;
|
||||
// hashcode of a list containing just v is
|
||||
// v.hashCode() + 31, see List.hashCode()
|
||||
} else {
|
||||
h = v.hashCode();
|
||||
}
|
||||
hash += names[i].toLowerCase().hashCode() ^ h;
|
||||
}
|
||||
return hash;
|
||||
}
|
||||
|
||||
/** Match a part of a string against a shell-style pattern.
|
||||
The only pattern characters recognized are <code>?</code>,
|
||||
standing for any one character,
|
||||
and <code>*</code>, standing for any string of
|
||||
characters, including the empty string. For instance,
|
||||
{@code wildmatch("sandwich","sa?d*ch",1,4,1,4)} will match
|
||||
{@code "and"} against {@code "a?d"}.
|
||||
|
||||
@param str the string containing the sequence to match.
|
||||
@param pat a string containing a pattern to match the sub string
|
||||
against.
|
||||
@param stri the index in the string at which matching should begin.
|
||||
@param strend the index in the string at which the matching should
|
||||
end.
|
||||
@param pati the index in the pattern at which matching should begin.
|
||||
@param patend the index in the pattern at which the matching should
|
||||
end.
|
||||
|
||||
@return true if and only if the string matches the pattern.
|
||||
*/
|
||||
/* The algorithm is a classical one. We advance pointers in
|
||||
parallel through str and pat. If we encounter a star in pat,
|
||||
we remember its position and continue advancing. If at any
|
||||
stage we get a mismatch between str and pat, we look to see if
|
||||
there is a remembered star. If not, we fail. If so, we
|
||||
retreat pat to just past that star and str to the position
|
||||
after the last one we tried, and we let the match advance
|
||||
again.
|
||||
|
||||
Even though there is only one remembered star position, the
|
||||
algorithm works when there are several stars in the pattern.
|
||||
When we encounter the second star, we forget the first one.
|
||||
This is OK, because if we get to the second star in A*B*C
|
||||
(where A etc are arbitrary strings), we have already seen AXB.
|
||||
We're therefore setting up a match of *C against the remainder
|
||||
of the string, which will match if that remainder looks like
|
||||
YC, so the whole string looks like AXBYC.
|
||||
*/
|
||||
private static boolean wildmatch(final String str, final String pat,
|
||||
int stri, final int strend, int pati, final int patend) {
|
||||
|
||||
// System.out.println("matching "+pat.substring(pati,patend)+
|
||||
// " against "+str.substring(stri, strend));
|
||||
int starstri; // index for backtrack if "*" attempt fails
|
||||
int starpati; // index for backtrack if "*" attempt fails, +1
|
||||
|
||||
starstri = starpati = -1;
|
||||
|
||||
/* On each pass through this loop, we either advance pati,
|
||||
or we backtrack pati and advance starstri. Since starstri
|
||||
is only ever assigned from pati, the loop must terminate. */
|
||||
while (true) {
|
||||
if (pati < patend) {
|
||||
final char patc = pat.charAt(pati);
|
||||
switch (patc) {
|
||||
case '?':
|
||||
if (stri == strend)
|
||||
break;
|
||||
stri++;
|
||||
pati++;
|
||||
continue;
|
||||
case '*':
|
||||
pati++;
|
||||
starpati = pati;
|
||||
starstri = stri;
|
||||
continue;
|
||||
default:
|
||||
if (stri < strend && str.charAt(stri) == patc) {
|
||||
stri++;
|
||||
pati++;
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
} else if (stri == strend)
|
||||
return true;
|
||||
|
||||
// Mismatched, can we backtrack to a "*"?
|
||||
if (starpati < 0 || starstri == strend)
|
||||
return false;
|
||||
|
||||
// Retry the match one position later in str
|
||||
pati = starpati;
|
||||
starstri++;
|
||||
stri = starstri;
|
||||
}
|
||||
}
|
||||
|
||||
/** Match a string against a shell-style pattern. The only pattern
|
||||
characters recognized are <code>?</code>, standing for any one
|
||||
character, and <code>*</code>, standing for any string of
|
||||
characters, including the empty string.
|
||||
|
||||
@param str the string to match.
|
||||
@param pat the pattern to match the string against.
|
||||
|
||||
@return true if and only if the string matches the pattern.
|
||||
*/
|
||||
public static boolean wildmatch(String str, String pat) {
|
||||
return wildmatch(str,pat,0,str.length(),0,pat.length());
|
||||
}
|
||||
}
|
||||
137
jdkSrc/jdk8/com/sun/jmx/mbeanserver/WeakIdentityHashMap.java
Normal file
137
jdkSrc/jdk8/com/sun/jmx/mbeanserver/WeakIdentityHashMap.java
Normal file
@@ -0,0 +1,137 @@
|
||||
/*
|
||||
* Copyright (c) 2005, 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.mbeanserver;
|
||||
|
||||
import static com.sun.jmx.mbeanserver.Util.*;
|
||||
|
||||
import java.lang.ref.Reference;
|
||||
import java.lang.ref.ReferenceQueue;
|
||||
import java.lang.ref.WeakReference;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
|
||||
/**
|
||||
* <p>A map where keys are compared using identity comparison (like
|
||||
* IdentityHashMap) but where the presence of an object as a key in
|
||||
* the map does not prevent it being garbage collected (like
|
||||
* WeakHashMap). This class does not implement the Map interface
|
||||
* because it is difficult to ensure correct semantics for iterators
|
||||
* over the entrySet().</p>
|
||||
*
|
||||
* <p>Because we do not implement Map, we do not copy the questionable
|
||||
* interface where you can call get(k) or remove(k) for any type of k,
|
||||
* which of course can only have an effect if k is of type K.</p>
|
||||
*
|
||||
* <p>This map does not support null keys.</p>
|
||||
*/
|
||||
/*
|
||||
* The approach
|
||||
* is to wrap each key in a WeakReference and use the wrapped value as
|
||||
* a key in an ordinary HashMap. The WeakReference has to be a
|
||||
* subclass IdentityWeakReference (IWR) where two IWRs are equal if
|
||||
* they refer to the same object. This enables us to find the entry
|
||||
* again.
|
||||
*/
|
||||
class WeakIdentityHashMap<K, V> {
|
||||
private WeakIdentityHashMap() {}
|
||||
|
||||
static <K, V> WeakIdentityHashMap<K, V> make() {
|
||||
return new WeakIdentityHashMap<K, V>();
|
||||
}
|
||||
|
||||
V get(K key) {
|
||||
expunge();
|
||||
WeakReference<K> keyref = makeReference(key);
|
||||
return map.get(keyref);
|
||||
}
|
||||
|
||||
public V put(K key, V value) {
|
||||
expunge();
|
||||
if (key == null)
|
||||
throw new IllegalArgumentException("Null key");
|
||||
WeakReference<K> keyref = makeReference(key, refQueue);
|
||||
return map.put(keyref, value);
|
||||
}
|
||||
|
||||
public V remove(K key) {
|
||||
expunge();
|
||||
WeakReference<K> keyref = makeReference(key);
|
||||
return map.remove(keyref);
|
||||
}
|
||||
|
||||
private void expunge() {
|
||||
Reference<? extends K> ref;
|
||||
while ((ref = refQueue.poll()) != null)
|
||||
map.remove(ref);
|
||||
}
|
||||
|
||||
private WeakReference<K> makeReference(K referent) {
|
||||
return new IdentityWeakReference<K>(referent);
|
||||
}
|
||||
|
||||
private WeakReference<K> makeReference(K referent, ReferenceQueue<K> q) {
|
||||
return new IdentityWeakReference<K>(referent, q);
|
||||
}
|
||||
|
||||
/**
|
||||
* WeakReference where equals and hashCode are based on the
|
||||
* referent. More precisely, two objects are equal if they are
|
||||
* identical or if they both have the same non-null referent. The
|
||||
* hashCode is the value the original referent had. Even if the
|
||||
* referent is cleared, the hashCode remains. Thus, objects of
|
||||
* this class can be used as keys in hash-based maps and sets.
|
||||
*/
|
||||
private static class IdentityWeakReference<T> extends WeakReference<T> {
|
||||
IdentityWeakReference(T o) {
|
||||
this(o, null);
|
||||
}
|
||||
|
||||
IdentityWeakReference(T o, ReferenceQueue<T> q) {
|
||||
super(o, q);
|
||||
this.hashCode = (o == null) ? 0 : System.identityHashCode(o);
|
||||
}
|
||||
|
||||
public boolean equals(Object o) {
|
||||
if (this == o)
|
||||
return true;
|
||||
if (!(o instanceof IdentityWeakReference<?>))
|
||||
return false;
|
||||
IdentityWeakReference<?> wr = (IdentityWeakReference<?>) o;
|
||||
Object got = get();
|
||||
return (got != null && got == wr.get());
|
||||
}
|
||||
|
||||
public int hashCode() {
|
||||
return hashCode;
|
||||
}
|
||||
|
||||
private final int hashCode;
|
||||
}
|
||||
|
||||
private Map<WeakReference<K>, V> map = newMap();
|
||||
private ReferenceQueue<K> refQueue = new ReferenceQueue<K>();
|
||||
}
|
||||
@@ -0,0 +1,852 @@
|
||||
/*
|
||||
* 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 com.sun.jmx.remote.internal;
|
||||
|
||||
import java.security.AccessController;
|
||||
import java.security.PrivilegedAction;
|
||||
import java.security.PrivilegedActionException;
|
||||
import java.security.PrivilegedExceptionAction;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.management.InstanceNotFoundException;
|
||||
import javax.management.MBeanServer;
|
||||
import javax.management.MBeanServerDelegate;
|
||||
import javax.management.MBeanServerNotification;
|
||||
import javax.management.Notification;
|
||||
import javax.management.NotificationBroadcaster;
|
||||
import javax.management.NotificationFilter;
|
||||
import javax.management.NotificationFilterSupport;
|
||||
import javax.management.NotificationListener;
|
||||
import javax.management.ObjectName;
|
||||
import javax.management.QueryEval;
|
||||
import javax.management.QueryExp;
|
||||
|
||||
import javax.management.remote.NotificationResult;
|
||||
import javax.management.remote.TargetedNotification;
|
||||
|
||||
import com.sun.jmx.remote.util.EnvHelp;
|
||||
import com.sun.jmx.remote.util.ClassLogger;
|
||||
|
||||
/** A circular buffer of notifications received from an MBean server. */
|
||||
/*
|
||||
There is one instance of ArrayNotificationBuffer for every
|
||||
MBeanServer object that has an attached ConnectorServer. Then, for
|
||||
every ConnectorServer attached to a given MBeanServer, there is an
|
||||
instance of the inner class ShareBuffer. So for example with two
|
||||
ConnectorServers it looks like this:
|
||||
|
||||
ConnectorServer1 -> ShareBuffer1 -\
|
||||
}-> ArrayNotificationBuffer
|
||||
ConnectorServer2 -> ShareBuffer2 -/ |
|
||||
|
|
||||
v
|
||||
MBeanServer
|
||||
|
||||
The ArrayNotificationBuffer has a circular buffer of
|
||||
NamedNotification objects. Each ConnectorServer defines a
|
||||
notification buffer size, and this size is recorded by the
|
||||
corresponding ShareBuffer. The buffer size of the
|
||||
ArrayNotificationBuffer is the maximum of all of its ShareBuffers.
|
||||
When a ShareBuffer is added or removed, the ArrayNotificationBuffer
|
||||
size is adjusted accordingly.
|
||||
|
||||
An ArrayNotificationBuffer also has a BufferListener (which is a
|
||||
NotificationListener) registered on every NotificationBroadcaster
|
||||
MBean in the MBeanServer to which it is attached. The cost of this
|
||||
potentially large set of listeners is the principal motivation for
|
||||
sharing the ArrayNotificationBuffer between ConnectorServers, and
|
||||
also the reason that we are careful to discard the
|
||||
ArrayNotificationBuffer (and its BufferListeners) when there are no
|
||||
longer any ConnectorServers using it.
|
||||
|
||||
The synchronization of this class is inherently complex. In an attempt
|
||||
to limit the complexity, we use just two locks:
|
||||
|
||||
- globalLock controls access to the mapping between an MBeanServer
|
||||
and its ArrayNotificationBuffer and to the set of ShareBuffers for
|
||||
each ArrayNotificationBuffer.
|
||||
|
||||
- the instance lock of each ArrayNotificationBuffer controls access
|
||||
to the array of notifications, including its size, and to the
|
||||
dispose flag of the ArrayNotificationBuffer. The wait/notify
|
||||
mechanism is used to indicate changes to the array.
|
||||
|
||||
If both locks are held at the same time, the globalLock must be
|
||||
taken first.
|
||||
|
||||
Since adding or removing a BufferListener to an MBean can involve
|
||||
calling user code, we are careful not to hold any locks while it is
|
||||
done.
|
||||
*/
|
||||
public class ArrayNotificationBuffer implements NotificationBuffer {
|
||||
private boolean disposed = false;
|
||||
|
||||
// FACTORY STUFF, INCLUDING SHARING
|
||||
|
||||
private static final Object globalLock = new Object();
|
||||
private static final
|
||||
HashMap<MBeanServer,ArrayNotificationBuffer> mbsToBuffer =
|
||||
new HashMap<MBeanServer,ArrayNotificationBuffer>(1);
|
||||
private final Collection<ShareBuffer> sharers = new HashSet<ShareBuffer>(1);
|
||||
|
||||
public static NotificationBuffer getNotificationBuffer(
|
||||
MBeanServer mbs, Map<String, ?> env) {
|
||||
|
||||
if (env == null)
|
||||
env = Collections.emptyMap();
|
||||
|
||||
//Find out queue size
|
||||
int queueSize = EnvHelp.getNotifBufferSize(env);
|
||||
|
||||
ArrayNotificationBuffer buf;
|
||||
boolean create;
|
||||
NotificationBuffer sharer;
|
||||
synchronized (globalLock) {
|
||||
buf = mbsToBuffer.get(mbs);
|
||||
create = (buf == null);
|
||||
if (create) {
|
||||
buf = new ArrayNotificationBuffer(mbs, queueSize);
|
||||
mbsToBuffer.put(mbs, buf);
|
||||
}
|
||||
sharer = buf.new ShareBuffer(queueSize);
|
||||
}
|
||||
/* We avoid holding any locks while calling createListeners.
|
||||
* This prevents possible deadlocks involving user code, but
|
||||
* does mean that a second ConnectorServer created and started
|
||||
* in this window will return before all the listeners are ready,
|
||||
* which could lead to surprising behaviour. The alternative
|
||||
* would be to block the second ConnectorServer until the first
|
||||
* one has finished adding all the listeners, but that would then
|
||||
* be subject to deadlock.
|
||||
*/
|
||||
if (create)
|
||||
buf.createListeners();
|
||||
return sharer;
|
||||
}
|
||||
|
||||
/* Ensure that this buffer is no longer the one that will be returned by
|
||||
* getNotificationBuffer. This method is idempotent - calling it more
|
||||
* than once has no effect beyond that of calling it once.
|
||||
*/
|
||||
static void removeNotificationBuffer(MBeanServer mbs) {
|
||||
synchronized (globalLock) {
|
||||
mbsToBuffer.remove(mbs);
|
||||
}
|
||||
}
|
||||
|
||||
void addSharer(ShareBuffer sharer) {
|
||||
synchronized (globalLock) {
|
||||
synchronized (this) {
|
||||
if (sharer.getSize() > queueSize)
|
||||
resize(sharer.getSize());
|
||||
}
|
||||
sharers.add(sharer);
|
||||
}
|
||||
}
|
||||
|
||||
private void removeSharer(ShareBuffer sharer) {
|
||||
boolean empty;
|
||||
synchronized (globalLock) {
|
||||
sharers.remove(sharer);
|
||||
empty = sharers.isEmpty();
|
||||
if (empty)
|
||||
removeNotificationBuffer(mBeanServer);
|
||||
else {
|
||||
int max = 0;
|
||||
for (ShareBuffer buf : sharers) {
|
||||
int bufsize = buf.getSize();
|
||||
if (bufsize > max)
|
||||
max = bufsize;
|
||||
}
|
||||
if (max < queueSize)
|
||||
resize(max);
|
||||
}
|
||||
}
|
||||
if (empty) {
|
||||
synchronized (this) {
|
||||
disposed = true;
|
||||
// Notify potential waiting fetchNotification call
|
||||
notifyAll();
|
||||
}
|
||||
destroyListeners();
|
||||
}
|
||||
}
|
||||
|
||||
private synchronized void resize(int newSize) {
|
||||
if (newSize == queueSize)
|
||||
return;
|
||||
while (queue.size() > newSize)
|
||||
dropNotification();
|
||||
queue.resize(newSize);
|
||||
queueSize = newSize;
|
||||
}
|
||||
|
||||
private class ShareBuffer implements NotificationBuffer {
|
||||
ShareBuffer(int size) {
|
||||
this.size = size;
|
||||
addSharer(this);
|
||||
}
|
||||
|
||||
public NotificationResult
|
||||
fetchNotifications(NotificationBufferFilter filter,
|
||||
long startSequenceNumber,
|
||||
long timeout,
|
||||
int maxNotifications)
|
||||
throws InterruptedException {
|
||||
NotificationBuffer buf = ArrayNotificationBuffer.this;
|
||||
return buf.fetchNotifications(filter, startSequenceNumber,
|
||||
timeout, maxNotifications);
|
||||
}
|
||||
|
||||
public void dispose() {
|
||||
ArrayNotificationBuffer.this.removeSharer(this);
|
||||
}
|
||||
|
||||
int getSize() {
|
||||
return size;
|
||||
}
|
||||
|
||||
private final int size;
|
||||
}
|
||||
|
||||
|
||||
// ARRAYNOTIFICATIONBUFFER IMPLEMENTATION
|
||||
|
||||
private ArrayNotificationBuffer(MBeanServer mbs, int queueSize) {
|
||||
if (logger.traceOn())
|
||||
logger.trace("Constructor", "queueSize=" + queueSize);
|
||||
|
||||
if (mbs == null || queueSize < 1)
|
||||
throw new IllegalArgumentException("Bad args");
|
||||
|
||||
this.mBeanServer = mbs;
|
||||
this.queueSize = queueSize;
|
||||
this.queue = new ArrayQueue<NamedNotification>(queueSize);
|
||||
this.earliestSequenceNumber = System.currentTimeMillis();
|
||||
this.nextSequenceNumber = this.earliestSequenceNumber;
|
||||
|
||||
logger.trace("Constructor", "ends");
|
||||
}
|
||||
|
||||
private synchronized boolean isDisposed() {
|
||||
return disposed;
|
||||
}
|
||||
|
||||
// We no longer support calling this method from outside.
|
||||
// The JDK doesn't contain any such calls and users are not
|
||||
// supposed to be accessing this class.
|
||||
public void dispose() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Fetch notifications that match the given listeners.</p>
|
||||
*
|
||||
* <p>The operation only considers notifications with a sequence
|
||||
* number at least <code>startSequenceNumber</code>. It will take
|
||||
* no longer than <code>timeout</code>, and will return no more
|
||||
* than <code>maxNotifications</code> different notifications.</p>
|
||||
*
|
||||
* <p>If there are no notifications matching the criteria, the
|
||||
* operation will block until one arrives, subject to the
|
||||
* timeout.</p>
|
||||
*
|
||||
* @param filter an object that will add notifications to a
|
||||
* {@code List<TargetedNotification>} if they match the current
|
||||
* listeners with their filters.
|
||||
* @param startSequenceNumber the first sequence number to
|
||||
* consider.
|
||||
* @param timeout the maximum time to wait. May be 0 to indicate
|
||||
* not to wait if there are no notifications.
|
||||
* @param maxNotifications the maximum number of notifications to
|
||||
* return. May be 0 to indicate a wait for eligible notifications
|
||||
* that will return a usable <code>nextSequenceNumber</code>. The
|
||||
* {@link TargetedNotification} array in the returned {@link
|
||||
* NotificationResult} may contain more than this number of
|
||||
* elements but will not contain more than this number of
|
||||
* different notifications.
|
||||
*/
|
||||
public NotificationResult
|
||||
fetchNotifications(NotificationBufferFilter filter,
|
||||
long startSequenceNumber,
|
||||
long timeout,
|
||||
int maxNotifications)
|
||||
throws InterruptedException {
|
||||
|
||||
logger.trace("fetchNotifications", "starts");
|
||||
|
||||
if (startSequenceNumber < 0 || isDisposed()) {
|
||||
synchronized(this) {
|
||||
return new NotificationResult(earliestSequenceNumber(),
|
||||
nextSequenceNumber(),
|
||||
new TargetedNotification[0]);
|
||||
}
|
||||
}
|
||||
|
||||
// Check arg validity
|
||||
if (filter == null
|
||||
|| startSequenceNumber < 0 || timeout < 0
|
||||
|| maxNotifications < 0) {
|
||||
logger.trace("fetchNotifications", "Bad args");
|
||||
throw new IllegalArgumentException("Bad args to fetch");
|
||||
}
|
||||
|
||||
if (logger.debugOn()) {
|
||||
logger.trace("fetchNotifications",
|
||||
"filter=" + filter + "; startSeq=" +
|
||||
startSequenceNumber + "; timeout=" + timeout +
|
||||
"; max=" + maxNotifications);
|
||||
}
|
||||
|
||||
if (startSequenceNumber > nextSequenceNumber()) {
|
||||
final String msg = "Start sequence number too big: " +
|
||||
startSequenceNumber + " > " + nextSequenceNumber();
|
||||
logger.trace("fetchNotifications", msg);
|
||||
throw new IllegalArgumentException(msg);
|
||||
}
|
||||
|
||||
/* Determine the end time corresponding to the timeout value.
|
||||
Caller may legitimately supply Long.MAX_VALUE to indicate no
|
||||
timeout. In that case the addition will overflow and produce
|
||||
a negative end time. Set end time to Long.MAX_VALUE in that
|
||||
case. We assume System.currentTimeMillis() is positive. */
|
||||
long endTime = System.currentTimeMillis() + timeout;
|
||||
if (endTime < 0) // overflow
|
||||
endTime = Long.MAX_VALUE;
|
||||
|
||||
if (logger.debugOn())
|
||||
logger.debug("fetchNotifications", "endTime=" + endTime);
|
||||
|
||||
/* We set earliestSeq the first time through the loop. If we
|
||||
set it here, notifications could be dropped before we
|
||||
started examining them, so earliestSeq might not correspond
|
||||
to the earliest notification we examined. */
|
||||
long earliestSeq = -1;
|
||||
long nextSeq = startSequenceNumber;
|
||||
List<TargetedNotification> notifs =
|
||||
new ArrayList<TargetedNotification>();
|
||||
|
||||
/* On exit from this loop, notifs, earliestSeq, and nextSeq must
|
||||
all be correct values for the returned NotificationResult. */
|
||||
while (true) {
|
||||
logger.debug("fetchNotifications", "main loop starts");
|
||||
|
||||
NamedNotification candidate;
|
||||
|
||||
/* Get the next available notification regardless of filters,
|
||||
or wait for one to arrive if there is none. */
|
||||
synchronized (this) {
|
||||
|
||||
/* First time through. The current earliestSequenceNumber
|
||||
is the first one we could have examined. */
|
||||
if (earliestSeq < 0) {
|
||||
earliestSeq = earliestSequenceNumber();
|
||||
if (logger.debugOn()) {
|
||||
logger.debug("fetchNotifications",
|
||||
"earliestSeq=" + earliestSeq);
|
||||
}
|
||||
if (nextSeq < earliestSeq) {
|
||||
nextSeq = earliestSeq;
|
||||
logger.debug("fetchNotifications",
|
||||
"nextSeq=earliestSeq");
|
||||
}
|
||||
} else
|
||||
earliestSeq = earliestSequenceNumber();
|
||||
|
||||
/* If many notifications have been dropped since the
|
||||
last time through, nextSeq could now be earlier
|
||||
than the current earliest. If so, notifications
|
||||
may have been lost and we return now so the caller
|
||||
can see this next time it calls. */
|
||||
if (nextSeq < earliestSeq) {
|
||||
logger.trace("fetchNotifications",
|
||||
"nextSeq=" + nextSeq + " < " + "earliestSeq=" +
|
||||
earliestSeq + " so may have lost notifs");
|
||||
break;
|
||||
}
|
||||
|
||||
if (nextSeq < nextSequenceNumber()) {
|
||||
candidate = notificationAt(nextSeq);
|
||||
// Skip security check if NotificationBufferFilter is not overloaded
|
||||
if (!(filter instanceof ServerNotifForwarder.NotifForwarderBufferFilter)) {
|
||||
try {
|
||||
ServerNotifForwarder.checkMBeanPermission(this.mBeanServer,
|
||||
candidate.getObjectName(),"addNotificationListener");
|
||||
} catch (InstanceNotFoundException | SecurityException e) {
|
||||
if (logger.debugOn()) {
|
||||
logger.debug("fetchNotifications", "candidate: " + candidate + " skipped. exception " + e);
|
||||
}
|
||||
++nextSeq;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (logger.debugOn()) {
|
||||
logger.debug("fetchNotifications", "candidate: " +
|
||||
candidate);
|
||||
logger.debug("fetchNotifications", "nextSeq now " +
|
||||
nextSeq);
|
||||
}
|
||||
} else {
|
||||
/* nextSeq is the largest sequence number. If we
|
||||
already got notifications, return them now.
|
||||
Otherwise wait for some to arrive, with
|
||||
timeout. */
|
||||
if (notifs.size() > 0) {
|
||||
logger.debug("fetchNotifications",
|
||||
"no more notifs but have some so don't wait");
|
||||
break;
|
||||
}
|
||||
long toWait = endTime - System.currentTimeMillis();
|
||||
if (toWait <= 0) {
|
||||
logger.debug("fetchNotifications", "timeout");
|
||||
break;
|
||||
}
|
||||
|
||||
/* dispose called */
|
||||
if (isDisposed()) {
|
||||
if (logger.debugOn())
|
||||
logger.debug("fetchNotifications",
|
||||
"dispose callled, no wait");
|
||||
return new NotificationResult(earliestSequenceNumber(),
|
||||
nextSequenceNumber(),
|
||||
new TargetedNotification[0]);
|
||||
}
|
||||
|
||||
if (logger.debugOn())
|
||||
logger.debug("fetchNotifications",
|
||||
"wait(" + toWait + ")");
|
||||
wait(toWait);
|
||||
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
/* We have a candidate notification. See if it matches
|
||||
our filters. We do this outside the synchronized block
|
||||
so we don't hold up everyone accessing the buffer
|
||||
(including notification senders) while we evaluate
|
||||
potentially slow filters. */
|
||||
ObjectName name = candidate.getObjectName();
|
||||
Notification notif = candidate.getNotification();
|
||||
List<TargetedNotification> matchedNotifs =
|
||||
new ArrayList<TargetedNotification>();
|
||||
logger.debug("fetchNotifications",
|
||||
"applying filter to candidate");
|
||||
filter.apply(matchedNotifs, name, notif);
|
||||
|
||||
if (matchedNotifs.size() > 0) {
|
||||
/* We only check the max size now, so that our
|
||||
returned nextSeq is as large as possible. This
|
||||
prevents the caller from thinking it missed
|
||||
interesting notifications when in fact we knew they
|
||||
weren't. */
|
||||
if (maxNotifications <= 0) {
|
||||
logger.debug("fetchNotifications",
|
||||
"reached maxNotifications");
|
||||
break;
|
||||
}
|
||||
--maxNotifications;
|
||||
if (logger.debugOn())
|
||||
logger.debug("fetchNotifications", "add: " +
|
||||
matchedNotifs);
|
||||
notifs.addAll(matchedNotifs);
|
||||
}
|
||||
|
||||
++nextSeq;
|
||||
} // end while
|
||||
|
||||
/* Construct and return the result. */
|
||||
int nnotifs = notifs.size();
|
||||
TargetedNotification[] resultNotifs =
|
||||
new TargetedNotification[nnotifs];
|
||||
notifs.toArray(resultNotifs);
|
||||
NotificationResult nr =
|
||||
new NotificationResult(earliestSeq, nextSeq, resultNotifs);
|
||||
if (logger.debugOn())
|
||||
logger.debug("fetchNotifications", nr.toString());
|
||||
logger.trace("fetchNotifications", "ends");
|
||||
|
||||
return nr;
|
||||
}
|
||||
|
||||
synchronized long earliestSequenceNumber() {
|
||||
return earliestSequenceNumber;
|
||||
}
|
||||
|
||||
synchronized long nextSequenceNumber() {
|
||||
return nextSequenceNumber;
|
||||
}
|
||||
|
||||
synchronized void addNotification(NamedNotification notif) {
|
||||
if (logger.traceOn())
|
||||
logger.trace("addNotification", notif.toString());
|
||||
|
||||
while (queue.size() >= queueSize) {
|
||||
dropNotification();
|
||||
if (logger.debugOn()) {
|
||||
logger.debug("addNotification",
|
||||
"dropped oldest notif, earliestSeq=" +
|
||||
earliestSequenceNumber);
|
||||
}
|
||||
}
|
||||
queue.add(notif);
|
||||
nextSequenceNumber++;
|
||||
if (logger.debugOn())
|
||||
logger.debug("addNotification", "nextSeq=" + nextSequenceNumber);
|
||||
notifyAll();
|
||||
}
|
||||
|
||||
private void dropNotification() {
|
||||
queue.remove(0);
|
||||
earliestSequenceNumber++;
|
||||
}
|
||||
|
||||
synchronized NamedNotification notificationAt(long seqNo) {
|
||||
long index = seqNo - earliestSequenceNumber;
|
||||
if (index < 0 || index > Integer.MAX_VALUE) {
|
||||
final String msg = "Bad sequence number: " + seqNo + " (earliest "
|
||||
+ earliestSequenceNumber + ")";
|
||||
logger.trace("notificationAt", msg);
|
||||
throw new IllegalArgumentException(msg);
|
||||
}
|
||||
return queue.get((int) index);
|
||||
}
|
||||
|
||||
private static class NamedNotification {
|
||||
NamedNotification(ObjectName sender, Notification notif) {
|
||||
this.sender = sender;
|
||||
this.notification = notif;
|
||||
}
|
||||
|
||||
ObjectName getObjectName() {
|
||||
return sender;
|
||||
}
|
||||
|
||||
Notification getNotification() {
|
||||
return notification;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return "NamedNotification(" + sender + ", " + notification + ")";
|
||||
}
|
||||
|
||||
private final ObjectName sender;
|
||||
private final Notification notification;
|
||||
}
|
||||
|
||||
/*
|
||||
* Add our listener to every NotificationBroadcaster MBean
|
||||
* currently in the MBean server and to every
|
||||
* NotificationBroadcaster later created.
|
||||
*
|
||||
* It would be really nice if we could just do
|
||||
* mbs.addNotificationListener(new ObjectName("*:*"), ...);
|
||||
* Definitely something for the next version of JMX.
|
||||
*
|
||||
* There is a nasty race condition that we must handle. We
|
||||
* first register for MBean-creation notifications so we can add
|
||||
* listeners to new MBeans, then we query the existing MBeans to
|
||||
* add listeners to them. The problem is that a new MBean could
|
||||
* arrive after we register for creations but before the query has
|
||||
* completed. Then we could see the MBean both in the query and
|
||||
* in an MBean-creation notification, and we would end up
|
||||
* registering our listener twice.
|
||||
*
|
||||
* To solve this problem, we arrange for new MBeans that arrive
|
||||
* while the query is being done to be added to the Set createdDuringQuery
|
||||
* and we do not add a listener immediately. When the query is done,
|
||||
* we atomically turn off the addition of new names to createdDuringQuery
|
||||
* and add all the names that were there to the result of the query.
|
||||
* Since we are dealing with Sets, the result is the same whether or not
|
||||
* the newly-created MBean was included in the query result.
|
||||
*
|
||||
* It is important not to hold any locks during the operation of adding
|
||||
* listeners to MBeans. An MBean's addNotificationListener can be
|
||||
* arbitrary user code, and this could deadlock with any locks we hold
|
||||
* (see bug 6239400). The corollary is that we must not do any operations
|
||||
* in this method or the methods it calls that require locks.
|
||||
*/
|
||||
private void createListeners() {
|
||||
logger.debug("createListeners", "starts");
|
||||
|
||||
synchronized (this) {
|
||||
createdDuringQuery = new HashSet<ObjectName>();
|
||||
}
|
||||
|
||||
try {
|
||||
addNotificationListener(MBeanServerDelegate.DELEGATE_NAME,
|
||||
creationListener, creationFilter, null);
|
||||
logger.debug("createListeners", "added creationListener");
|
||||
} catch (Exception e) {
|
||||
final String msg = "Can't add listener to MBean server delegate: ";
|
||||
RuntimeException re = new IllegalArgumentException(msg + e);
|
||||
EnvHelp.initCause(re, e);
|
||||
logger.fine("createListeners", msg + e);
|
||||
logger.debug("createListeners", e);
|
||||
throw re;
|
||||
}
|
||||
|
||||
/* Spec doesn't say whether Set returned by QueryNames can be modified
|
||||
so we clone it. */
|
||||
Set<ObjectName> names = queryNames(null, broadcasterQuery);
|
||||
names = new HashSet<ObjectName>(names);
|
||||
|
||||
synchronized (this) {
|
||||
names.addAll(createdDuringQuery);
|
||||
createdDuringQuery = null;
|
||||
}
|
||||
|
||||
for (ObjectName name : names)
|
||||
addBufferListener(name);
|
||||
logger.debug("createListeners", "ends");
|
||||
}
|
||||
|
||||
private void addBufferListener(ObjectName name) {
|
||||
checkNoLocks();
|
||||
if (logger.debugOn())
|
||||
logger.debug("addBufferListener", name.toString());
|
||||
try {
|
||||
addNotificationListener(name, bufferListener, null, name);
|
||||
} catch (Exception e) {
|
||||
logger.trace("addBufferListener", e);
|
||||
/* This can happen if the MBean was unregistered just
|
||||
after the query. Or user NotificationBroadcaster might
|
||||
throw unexpected exception. */
|
||||
}
|
||||
}
|
||||
|
||||
private void removeBufferListener(ObjectName name) {
|
||||
checkNoLocks();
|
||||
if (logger.debugOn())
|
||||
logger.debug("removeBufferListener", name.toString());
|
||||
try {
|
||||
removeNotificationListener(name, bufferListener);
|
||||
} catch (Exception e) {
|
||||
logger.trace("removeBufferListener", e);
|
||||
}
|
||||
}
|
||||
|
||||
private void addNotificationListener(final ObjectName name,
|
||||
final NotificationListener listener,
|
||||
final NotificationFilter filter,
|
||||
final Object handback)
|
||||
throws Exception {
|
||||
try {
|
||||
AccessController.doPrivileged(new PrivilegedExceptionAction<Void>() {
|
||||
public Void run() throws InstanceNotFoundException {
|
||||
mBeanServer.addNotificationListener(name,
|
||||
listener,
|
||||
filter,
|
||||
handback);
|
||||
return null;
|
||||
}
|
||||
});
|
||||
} catch (Exception e) {
|
||||
throw extractException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private void removeNotificationListener(final ObjectName name,
|
||||
final NotificationListener listener)
|
||||
throws Exception {
|
||||
try {
|
||||
AccessController.doPrivileged(new PrivilegedExceptionAction<Void>() {
|
||||
public Void run() throws Exception {
|
||||
mBeanServer.removeNotificationListener(name, listener);
|
||||
return null;
|
||||
}
|
||||
});
|
||||
} catch (Exception e) {
|
||||
throw extractException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private Set<ObjectName> queryNames(final ObjectName name,
|
||||
final QueryExp query) {
|
||||
PrivilegedAction<Set<ObjectName>> act =
|
||||
new PrivilegedAction<Set<ObjectName>>() {
|
||||
public Set<ObjectName> run() {
|
||||
return mBeanServer.queryNames(name, query);
|
||||
}
|
||||
};
|
||||
try {
|
||||
return AccessController.doPrivileged(act);
|
||||
} catch (RuntimeException e) {
|
||||
logger.fine("queryNames", "Failed to query names: " + e);
|
||||
logger.debug("queryNames", e);
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean isInstanceOf(final MBeanServer mbs,
|
||||
final ObjectName name,
|
||||
final String className) {
|
||||
PrivilegedExceptionAction<Boolean> act =
|
||||
new PrivilegedExceptionAction<Boolean>() {
|
||||
public Boolean run() throws InstanceNotFoundException {
|
||||
return mbs.isInstanceOf(name, className);
|
||||
}
|
||||
};
|
||||
try {
|
||||
return AccessController.doPrivileged(act);
|
||||
} catch (Exception e) {
|
||||
logger.fine("isInstanceOf", "failed: " + e);
|
||||
logger.debug("isInstanceOf", e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/* This method must not be synchronized. See the comment on the
|
||||
* createListeners method.
|
||||
*
|
||||
* The notification could arrive after our buffer has been destroyed
|
||||
* or even during its destruction. So we always add our listener
|
||||
* (without synchronization), then we check if the buffer has been
|
||||
* destroyed and if so remove the listener we just added.
|
||||
*/
|
||||
private void createdNotification(MBeanServerNotification n) {
|
||||
final String shouldEqual =
|
||||
MBeanServerNotification.REGISTRATION_NOTIFICATION;
|
||||
if (!n.getType().equals(shouldEqual)) {
|
||||
logger.warning("createNotification", "bad type: " + n.getType());
|
||||
return;
|
||||
}
|
||||
|
||||
ObjectName name = n.getMBeanName();
|
||||
if (logger.debugOn())
|
||||
logger.debug("createdNotification", "for: " + name);
|
||||
|
||||
synchronized (this) {
|
||||
if (createdDuringQuery != null) {
|
||||
createdDuringQuery.add(name);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (isInstanceOf(mBeanServer, name, broadcasterClass)) {
|
||||
addBufferListener(name);
|
||||
if (isDisposed())
|
||||
removeBufferListener(name);
|
||||
}
|
||||
}
|
||||
|
||||
private class BufferListener implements NotificationListener {
|
||||
public void handleNotification(Notification notif, Object handback) {
|
||||
if (logger.debugOn()) {
|
||||
logger.debug("BufferListener.handleNotification",
|
||||
"notif=" + notif + "; handback=" + handback);
|
||||
}
|
||||
ObjectName name = (ObjectName) handback;
|
||||
addNotification(new NamedNotification(name, notif));
|
||||
}
|
||||
}
|
||||
|
||||
private final NotificationListener bufferListener = new BufferListener();
|
||||
|
||||
private static class BroadcasterQuery
|
||||
extends QueryEval implements QueryExp {
|
||||
private static final long serialVersionUID = 7378487660587592048L;
|
||||
|
||||
public boolean apply(final ObjectName name) {
|
||||
final MBeanServer mbs = QueryEval.getMBeanServer();
|
||||
return isInstanceOf(mbs, name, broadcasterClass);
|
||||
}
|
||||
}
|
||||
private static final QueryExp broadcasterQuery = new BroadcasterQuery();
|
||||
|
||||
private static final NotificationFilter creationFilter;
|
||||
static {
|
||||
NotificationFilterSupport nfs = new NotificationFilterSupport();
|
||||
nfs.enableType(MBeanServerNotification.REGISTRATION_NOTIFICATION);
|
||||
creationFilter = nfs;
|
||||
}
|
||||
|
||||
private final NotificationListener creationListener =
|
||||
new NotificationListener() {
|
||||
public void handleNotification(Notification notif,
|
||||
Object handback) {
|
||||
logger.debug("creationListener", "handleNotification called");
|
||||
createdNotification((MBeanServerNotification) notif);
|
||||
}
|
||||
};
|
||||
|
||||
private void destroyListeners() {
|
||||
checkNoLocks();
|
||||
logger.debug("destroyListeners", "starts");
|
||||
try {
|
||||
removeNotificationListener(MBeanServerDelegate.DELEGATE_NAME,
|
||||
creationListener);
|
||||
} catch (Exception e) {
|
||||
logger.warning("remove listener from MBeanServer delegate", e);
|
||||
}
|
||||
Set<ObjectName> names = queryNames(null, broadcasterQuery);
|
||||
for (final ObjectName name : names) {
|
||||
if (logger.debugOn())
|
||||
logger.debug("destroyListeners",
|
||||
"remove listener from " + name);
|
||||
removeBufferListener(name);
|
||||
}
|
||||
logger.debug("destroyListeners", "ends");
|
||||
}
|
||||
|
||||
private void checkNoLocks() {
|
||||
if (Thread.holdsLock(this) || Thread.holdsLock(globalLock))
|
||||
logger.warning("checkNoLocks", "lock protocol violation");
|
||||
}
|
||||
|
||||
/**
|
||||
* Iterate until we extract the real exception
|
||||
* from a stack of PrivilegedActionExceptions.
|
||||
*/
|
||||
private static Exception extractException(Exception e) {
|
||||
while (e instanceof PrivilegedActionException) {
|
||||
e = ((PrivilegedActionException)e).getException();
|
||||
}
|
||||
return e;
|
||||
}
|
||||
|
||||
private static final ClassLogger logger =
|
||||
new ClassLogger("javax.management.remote.misc",
|
||||
"ArrayNotificationBuffer");
|
||||
|
||||
private final MBeanServer mBeanServer;
|
||||
private final ArrayQueue<NamedNotification> queue;
|
||||
private int queueSize;
|
||||
private long earliestSequenceNumber;
|
||||
private long nextSequenceNumber;
|
||||
private Set<ObjectName> createdDuringQuery;
|
||||
|
||||
static final String broadcasterClass =
|
||||
NotificationBroadcaster.class.getName();
|
||||
}
|
||||
102
jdkSrc/jdk8/com/sun/jmx/remote/internal/ArrayQueue.java
Normal file
102
jdkSrc/jdk8/com/sun/jmx/remote/internal/ArrayQueue.java
Normal file
@@ -0,0 +1,102 @@
|
||||
/*
|
||||
* Copyright (c) 2003, 2006, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package com.sun.jmx.remote.internal;
|
||||
|
||||
import java.util.AbstractList;
|
||||
import java.util.Iterator;
|
||||
|
||||
public class ArrayQueue<T> extends AbstractList<T> {
|
||||
public ArrayQueue(int capacity) {
|
||||
this.capacity = capacity + 1;
|
||||
this.queue = newArray(capacity + 1);
|
||||
this.head = 0;
|
||||
this.tail = 0;
|
||||
}
|
||||
|
||||
public void resize(int newcapacity) {
|
||||
int size = size();
|
||||
if (newcapacity < size)
|
||||
throw new IndexOutOfBoundsException("Resizing would lose data");
|
||||
newcapacity++;
|
||||
if (newcapacity == this.capacity)
|
||||
return;
|
||||
T[] newqueue = newArray(newcapacity);
|
||||
for (int i = 0; i < size; i++)
|
||||
newqueue[i] = get(i);
|
||||
this.capacity = newcapacity;
|
||||
this.queue = newqueue;
|
||||
this.head = 0;
|
||||
this.tail = size;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private T[] newArray(int size) {
|
||||
return (T[]) new Object[size];
|
||||
}
|
||||
|
||||
public boolean add(T o) {
|
||||
queue[tail] = o;
|
||||
int newtail = (tail + 1) % capacity;
|
||||
if (newtail == head)
|
||||
throw new IndexOutOfBoundsException("Queue full");
|
||||
tail = newtail;
|
||||
return true; // we did add something
|
||||
}
|
||||
|
||||
public T remove(int i) {
|
||||
if (i != 0)
|
||||
throw new IllegalArgumentException("Can only remove head of queue");
|
||||
if (head == tail)
|
||||
throw new IndexOutOfBoundsException("Queue empty");
|
||||
T removed = queue[head];
|
||||
queue[head] = null;
|
||||
head = (head + 1) % capacity;
|
||||
return removed;
|
||||
}
|
||||
|
||||
public T get(int i) {
|
||||
int size = size();
|
||||
if (i < 0 || i >= size) {
|
||||
final String msg = "Index " + i + ", queue size " + size;
|
||||
throw new IndexOutOfBoundsException(msg);
|
||||
}
|
||||
int index = (head + i) % capacity;
|
||||
return queue[index];
|
||||
}
|
||||
|
||||
public int size() {
|
||||
// Can't use % here because it's not mod: -3 % 2 is -1, not +1.
|
||||
int diff = tail - head;
|
||||
if (diff < 0)
|
||||
diff += capacity;
|
||||
return diff;
|
||||
}
|
||||
|
||||
private int capacity;
|
||||
private T[] queue;
|
||||
private int head;
|
||||
private int tail;
|
||||
}
|
||||
@@ -0,0 +1,253 @@
|
||||
/*
|
||||
* Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package com.sun.jmx.remote.internal;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InterruptedIOException;
|
||||
|
||||
import com.sun.jmx.remote.util.ClassLogger;
|
||||
import com.sun.jmx.remote.util.EnvHelp;
|
||||
|
||||
public abstract class ClientCommunicatorAdmin {
|
||||
private static volatile long threadNo = 1;
|
||||
|
||||
public ClientCommunicatorAdmin(long period) {
|
||||
this.period = period;
|
||||
|
||||
if (period > 0) {
|
||||
checker = new Checker();
|
||||
|
||||
Thread t = new Thread(checker, "JMX client heartbeat " + ++threadNo);
|
||||
t.setDaemon(true);
|
||||
t.start();
|
||||
} else
|
||||
checker = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called by a client to inform of getting an IOException.
|
||||
*/
|
||||
public void gotIOException (IOException ioe) throws IOException {
|
||||
restart(ioe);
|
||||
}
|
||||
|
||||
/**
|
||||
* Called by this class to check a client connection.
|
||||
*/
|
||||
protected abstract void checkConnection() throws IOException;
|
||||
|
||||
/**
|
||||
* Tells a client to re-start again.
|
||||
*/
|
||||
protected abstract void doStart() throws IOException;
|
||||
|
||||
/**
|
||||
* Tells a client to stop because failing to call checkConnection.
|
||||
*/
|
||||
protected abstract void doStop();
|
||||
|
||||
/**
|
||||
* Terminates this object.
|
||||
*/
|
||||
public void terminate() {
|
||||
synchronized(lock) {
|
||||
if (state == TERMINATED) {
|
||||
return;
|
||||
}
|
||||
|
||||
state = TERMINATED;
|
||||
|
||||
lock.notifyAll();
|
||||
|
||||
if (checker != null)
|
||||
checker.stop();
|
||||
}
|
||||
}
|
||||
|
||||
private void restart(IOException ioe) throws IOException {
|
||||
// check state
|
||||
synchronized(lock) {
|
||||
if (state == TERMINATED) {
|
||||
throw new IOException("The client has been closed.");
|
||||
} else if (state == FAILED) { // already failed to re-start by another thread
|
||||
throw ioe;
|
||||
} else if (state == RE_CONNECTING) {
|
||||
// restart process has been called by another thread
|
||||
// we need to wait
|
||||
while(state == RE_CONNECTING) {
|
||||
try {
|
||||
lock.wait();
|
||||
} catch (InterruptedException ire) {
|
||||
// be asked to give up
|
||||
InterruptedIOException iioe = new InterruptedIOException(ire.toString());
|
||||
EnvHelp.initCause(iioe, ire);
|
||||
|
||||
throw iioe;
|
||||
}
|
||||
}
|
||||
|
||||
if (state == TERMINATED) {
|
||||
throw new IOException("The client has been closed.");
|
||||
} else if (state != CONNECTED) {
|
||||
// restarted is failed by another thread
|
||||
throw ioe;
|
||||
}
|
||||
return;
|
||||
} else {
|
||||
state = RE_CONNECTING;
|
||||
lock.notifyAll();
|
||||
}
|
||||
}
|
||||
|
||||
// re-starting
|
||||
try {
|
||||
doStart();
|
||||
synchronized(lock) {
|
||||
if (state == TERMINATED) {
|
||||
throw new IOException("The client has been closed.");
|
||||
}
|
||||
|
||||
state = CONNECTED;
|
||||
|
||||
lock.notifyAll();
|
||||
}
|
||||
|
||||
return;
|
||||
} catch (Exception e) {
|
||||
logger.warning("restart", "Failed to restart: " + e);
|
||||
logger.debug("restart",e);
|
||||
|
||||
synchronized(lock) {
|
||||
if (state == TERMINATED) {
|
||||
throw new IOException("The client has been closed.");
|
||||
}
|
||||
|
||||
state = FAILED;
|
||||
|
||||
lock.notifyAll();
|
||||
}
|
||||
|
||||
try {
|
||||
doStop();
|
||||
} catch (Exception eee) {
|
||||
// OK.
|
||||
// We know there is a problem.
|
||||
}
|
||||
|
||||
terminate();
|
||||
|
||||
throw ioe;
|
||||
}
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------
|
||||
// private varaibles
|
||||
// --------------------------------------------------------------
|
||||
private class Checker implements Runnable {
|
||||
public void run() {
|
||||
myThread = Thread.currentThread();
|
||||
|
||||
while (state != TERMINATED && !myThread.isInterrupted()) {
|
||||
try {
|
||||
Thread.sleep(period);
|
||||
} catch (InterruptedException ire) {
|
||||
// OK.
|
||||
// We will check the state at the following steps
|
||||
}
|
||||
|
||||
if (state == TERMINATED || myThread.isInterrupted()) {
|
||||
break;
|
||||
}
|
||||
|
||||
try {
|
||||
checkConnection();
|
||||
} catch (Exception e) {
|
||||
synchronized(lock) {
|
||||
if (state == TERMINATED || myThread.isInterrupted()) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
e = (Exception)EnvHelp.getCause(e);
|
||||
|
||||
if (e instanceof IOException &&
|
||||
!(e instanceof InterruptedIOException)) {
|
||||
try {
|
||||
gotIOException((IOException)e);
|
||||
} catch (Exception ee) {
|
||||
logger.warning("Checker-run",
|
||||
"Failed to check connection: "+ e);
|
||||
logger.warning("Checker-run", "stopping");
|
||||
logger.debug("Checker-run",e);
|
||||
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
logger.warning("Checker-run",
|
||||
"Failed to check the connection: " + e);
|
||||
logger.debug("Checker-run",e);
|
||||
|
||||
// XXX stop checking?
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (logger.traceOn()) {
|
||||
logger.trace("Checker-run", "Finished.");
|
||||
}
|
||||
}
|
||||
|
||||
private void stop() {
|
||||
if (myThread != null && myThread != Thread.currentThread()) {
|
||||
myThread.interrupt();
|
||||
}
|
||||
}
|
||||
|
||||
private Thread myThread;
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------
|
||||
// private variables
|
||||
// --------------------------------------------------------------
|
||||
private final Checker checker;
|
||||
private long period;
|
||||
|
||||
// state
|
||||
private final static int CONNECTED = 0;
|
||||
private final static int RE_CONNECTING = 1;
|
||||
private final static int FAILED = 2;
|
||||
private final static int TERMINATED = 3;
|
||||
|
||||
private int state = CONNECTED;
|
||||
|
||||
private final int[] lock = new int[0];
|
||||
|
||||
private static final ClassLogger logger =
|
||||
new ClassLogger("javax.management.remote.misc",
|
||||
"ClientCommunicatorAdmin");
|
||||
}
|
||||
106
jdkSrc/jdk8/com/sun/jmx/remote/internal/ClientListenerInfo.java
Normal file
106
jdkSrc/jdk8/com/sun/jmx/remote/internal/ClientListenerInfo.java
Normal file
@@ -0,0 +1,106 @@
|
||||
/*
|
||||
* Copyright (c) 2003, 2006, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package com.sun.jmx.remote.internal;
|
||||
|
||||
import javax.management.NotificationFilter;
|
||||
import javax.management.NotificationListener;
|
||||
import javax.management.ObjectName;
|
||||
|
||||
import javax.security.auth.Subject;
|
||||
|
||||
|
||||
/**
|
||||
* <p>An identified listener. A listener has an Integer id that is
|
||||
* unique per connector server. It selects notifications based on the
|
||||
* ObjectName of the originator and an optional
|
||||
* NotificationFilter.</p>
|
||||
*/
|
||||
public class ClientListenerInfo {
|
||||
public ClientListenerInfo(Integer listenerID,
|
||||
ObjectName name,
|
||||
NotificationListener listener,
|
||||
NotificationFilter filter,
|
||||
Object handback,
|
||||
Subject delegationSubject) {
|
||||
this.listenerID = listenerID;
|
||||
this.name = name;
|
||||
this.listener = listener;
|
||||
this.filter = filter;
|
||||
this.handback = handback;
|
||||
this.delegationSubject = delegationSubject;
|
||||
}
|
||||
|
||||
public ObjectName getObjectName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public Integer getListenerID() {
|
||||
return listenerID;
|
||||
}
|
||||
|
||||
public NotificationFilter getNotificationFilter() {
|
||||
return filter;
|
||||
}
|
||||
|
||||
public NotificationListener getListener() {
|
||||
return listener;
|
||||
}
|
||||
|
||||
public Object getHandback() {
|
||||
return handback;
|
||||
}
|
||||
|
||||
public Subject getDelegationSubject() {
|
||||
return delegationSubject;
|
||||
}
|
||||
|
||||
|
||||
public boolean sameAs(ObjectName name) {
|
||||
return (getObjectName().equals(name));
|
||||
}
|
||||
|
||||
|
||||
public boolean sameAs(ObjectName name, NotificationListener listener) {
|
||||
return ( getObjectName().equals(name) &&
|
||||
getListener() == listener);
|
||||
}
|
||||
|
||||
|
||||
public boolean sameAs(ObjectName name, NotificationListener listener, NotificationFilter filter, Object handback) {
|
||||
return ( getObjectName().equals(name) &&
|
||||
getListener() == listener &&
|
||||
getNotificationFilter() == filter &&
|
||||
getHandback() == handback);
|
||||
}
|
||||
|
||||
private final ObjectName name;
|
||||
private final Integer listenerID;
|
||||
private final NotificationFilter filter;
|
||||
|
||||
private final NotificationListener listener;
|
||||
private final Object handback;
|
||||
private final Subject delegationSubject;
|
||||
}
|
||||
@@ -0,0 +1,921 @@
|
||||
/*
|
||||
* Copyright (c) 2002, 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 com.sun.jmx.remote.internal;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.NotSerializableException;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.Executor;
|
||||
|
||||
import java.security.AccessControlContext;
|
||||
import java.security.AccessController;
|
||||
import java.security.PrivilegedAction;
|
||||
import javax.security.auth.Subject;
|
||||
|
||||
import javax.management.Notification;
|
||||
import javax.management.NotificationListener;
|
||||
import javax.management.NotificationFilter;
|
||||
import javax.management.ObjectName;
|
||||
import javax.management.MBeanServerNotification;
|
||||
import javax.management.InstanceNotFoundException;
|
||||
import javax.management.ListenerNotFoundException;
|
||||
|
||||
import javax.management.remote.NotificationResult;
|
||||
import javax.management.remote.TargetedNotification;
|
||||
|
||||
import com.sun.jmx.remote.util.ClassLogger;
|
||||
import com.sun.jmx.remote.util.EnvHelp;
|
||||
import java.rmi.UnmarshalException;
|
||||
|
||||
|
||||
public abstract class ClientNotifForwarder {
|
||||
|
||||
private final AccessControlContext acc;
|
||||
|
||||
public ClientNotifForwarder(Map env) {
|
||||
this(null, env);
|
||||
}
|
||||
|
||||
private static int threadId;
|
||||
|
||||
/* An Executor that allows at most one executing and one pending
|
||||
Runnable. It uses at most one thread -- as soon as there is
|
||||
no pending Runnable the thread can exit. Another thread is
|
||||
created as soon as there is a new pending Runnable. This
|
||||
Executor is adapted for use in a situation where each Runnable
|
||||
usually schedules up another Runnable. On return from the
|
||||
first one, the second one is immediately executed. So this
|
||||
just becomes a complicated way to write a while loop, but with
|
||||
the advantage that you can replace it with another Executor,
|
||||
for instance one that you are using to execute a bunch of other
|
||||
unrelated work.
|
||||
|
||||
You might expect that a java.util.concurrent.ThreadPoolExecutor
|
||||
with corePoolSize=0 and maximumPoolSize=1 would have the same
|
||||
behavior, but it does not. A ThreadPoolExecutor only creates
|
||||
a new thread when a new task is submitted and the number of
|
||||
existing threads is < corePoolSize. This can never happen when
|
||||
corePoolSize=0, so new threads are never created. Surprising,
|
||||
but there you are.
|
||||
*/
|
||||
private static class LinearExecutor implements Executor {
|
||||
public synchronized void execute(Runnable command) {
|
||||
if (this.command != null)
|
||||
throw new IllegalArgumentException("More than one command");
|
||||
this.command = command;
|
||||
if (thread == null) {
|
||||
thread = new Thread() {
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
while (true) {
|
||||
Runnable r;
|
||||
synchronized (LinearExecutor.this) {
|
||||
if (LinearExecutor.this.command == null) {
|
||||
thread = null;
|
||||
return;
|
||||
} else {
|
||||
r = LinearExecutor.this.command;
|
||||
LinearExecutor.this.command = null;
|
||||
}
|
||||
}
|
||||
r.run();
|
||||
}
|
||||
}
|
||||
};
|
||||
thread.setDaemon(true);
|
||||
thread.setName("ClientNotifForwarder-" + ++threadId);
|
||||
thread.start();
|
||||
}
|
||||
}
|
||||
|
||||
private Runnable command;
|
||||
private Thread thread;
|
||||
}
|
||||
|
||||
public ClientNotifForwarder(ClassLoader defaultClassLoader, Map<String, ?> env) {
|
||||
maxNotifications = EnvHelp.getMaxFetchNotifNumber(env);
|
||||
timeout = EnvHelp.getFetchTimeout(env);
|
||||
|
||||
/* You can supply an Executor in which the remote call to
|
||||
fetchNotifications will be made. The Executor's execute
|
||||
method reschedules another task, so you must not use
|
||||
an Executor that executes tasks in the caller's thread. */
|
||||
Executor ex = (Executor)
|
||||
env.get("jmx.remote.x.fetch.notifications.executor");
|
||||
if (ex == null)
|
||||
ex = new LinearExecutor();
|
||||
else if (logger.traceOn())
|
||||
logger.trace("ClientNotifForwarder", "executor is " + ex);
|
||||
|
||||
this.defaultClassLoader = defaultClassLoader;
|
||||
this.executor = ex;
|
||||
this.acc = AccessController.getContext();
|
||||
}
|
||||
|
||||
/**
|
||||
* Called to to fetch notifications from a server.
|
||||
*/
|
||||
abstract protected NotificationResult fetchNotifs(long clientSequenceNumber,
|
||||
int maxNotifications,
|
||||
long timeout)
|
||||
throws IOException, ClassNotFoundException;
|
||||
|
||||
abstract protected Integer addListenerForMBeanRemovedNotif()
|
||||
throws IOException, InstanceNotFoundException;
|
||||
|
||||
abstract protected void removeListenerForMBeanRemovedNotif(Integer id)
|
||||
throws IOException, InstanceNotFoundException,
|
||||
ListenerNotFoundException;
|
||||
|
||||
/**
|
||||
* Used to send out a notification about lost notifs
|
||||
*/
|
||||
abstract protected void lostNotifs(String message, long number);
|
||||
|
||||
|
||||
public synchronized void addNotificationListener(Integer listenerID,
|
||||
ObjectName name,
|
||||
NotificationListener listener,
|
||||
NotificationFilter filter,
|
||||
Object handback,
|
||||
Subject delegationSubject)
|
||||
throws IOException, InstanceNotFoundException {
|
||||
|
||||
if (logger.traceOn()) {
|
||||
logger.trace("addNotificationListener",
|
||||
"Add the listener "+listener+" at "+name);
|
||||
}
|
||||
|
||||
infoList.put(listenerID,
|
||||
new ClientListenerInfo(listenerID,
|
||||
name,
|
||||
listener,
|
||||
filter,
|
||||
handback,
|
||||
delegationSubject));
|
||||
|
||||
|
||||
init(false);
|
||||
}
|
||||
|
||||
public synchronized Integer[]
|
||||
removeNotificationListener(ObjectName name,
|
||||
NotificationListener listener)
|
||||
throws ListenerNotFoundException, IOException {
|
||||
|
||||
beforeRemove();
|
||||
|
||||
if (logger.traceOn()) {
|
||||
logger.trace("removeNotificationListener",
|
||||
"Remove the listener "+listener+" from "+name);
|
||||
}
|
||||
|
||||
List<Integer> ids = new ArrayList<Integer>();
|
||||
List<ClientListenerInfo> values =
|
||||
new ArrayList<ClientListenerInfo>(infoList.values());
|
||||
for (int i=values.size()-1; i>=0; i--) {
|
||||
ClientListenerInfo li = values.get(i);
|
||||
|
||||
if (li.sameAs(name, listener)) {
|
||||
ids.add(li.getListenerID());
|
||||
|
||||
infoList.remove(li.getListenerID());
|
||||
}
|
||||
}
|
||||
|
||||
if (ids.isEmpty())
|
||||
throw new ListenerNotFoundException("Listener not found");
|
||||
|
||||
return ids.toArray(new Integer[0]);
|
||||
}
|
||||
|
||||
public synchronized Integer
|
||||
removeNotificationListener(ObjectName name,
|
||||
NotificationListener listener,
|
||||
NotificationFilter filter,
|
||||
Object handback)
|
||||
throws ListenerNotFoundException, IOException {
|
||||
|
||||
if (logger.traceOn()) {
|
||||
logger.trace("removeNotificationListener",
|
||||
"Remove the listener "+listener+" from "+name);
|
||||
}
|
||||
|
||||
beforeRemove();
|
||||
|
||||
Integer id = null;
|
||||
|
||||
List<ClientListenerInfo> values =
|
||||
new ArrayList<ClientListenerInfo>(infoList.values());
|
||||
for (int i=values.size()-1; i>=0; i--) {
|
||||
ClientListenerInfo li = values.get(i);
|
||||
if (li.sameAs(name, listener, filter, handback)) {
|
||||
id=li.getListenerID();
|
||||
|
||||
infoList.remove(id);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (id == null)
|
||||
throw new ListenerNotFoundException("Listener not found");
|
||||
|
||||
return id;
|
||||
}
|
||||
|
||||
public synchronized Integer[] removeNotificationListener(ObjectName name) {
|
||||
if (logger.traceOn()) {
|
||||
logger.trace("removeNotificationListener",
|
||||
"Remove all listeners registered at "+name);
|
||||
}
|
||||
|
||||
List<Integer> ids = new ArrayList<Integer>();
|
||||
|
||||
List<ClientListenerInfo> values =
|
||||
new ArrayList<ClientListenerInfo>(infoList.values());
|
||||
for (int i=values.size()-1; i>=0; i--) {
|
||||
ClientListenerInfo li = values.get(i);
|
||||
if (li.sameAs(name)) {
|
||||
ids.add(li.getListenerID());
|
||||
|
||||
infoList.remove(li.getListenerID());
|
||||
}
|
||||
}
|
||||
|
||||
return ids.toArray(new Integer[0]);
|
||||
}
|
||||
|
||||
/*
|
||||
* Called when a connector is doing reconnection. Like <code>postReconnection</code>,
|
||||
* this method is intended to be called only by a client connector:
|
||||
* <code>RMIConnector</code> and <code>ClientIntermediary</code>.
|
||||
* Call this method will set the flag beingReconnection to <code>true</code>,
|
||||
* and the thread used to fetch notifis will be stopped, a new thread can be
|
||||
* created only after the method <code>postReconnection</code> is called.
|
||||
*
|
||||
* It is caller's responsiblity to not re-call this method before calling
|
||||
* <code>postReconnection</code>.
|
||||
*/
|
||||
public synchronized ClientListenerInfo[] preReconnection() throws IOException {
|
||||
if (state == TERMINATED || beingReconnected) { // should never
|
||||
throw new IOException("Illegal state.");
|
||||
}
|
||||
|
||||
final ClientListenerInfo[] tmp =
|
||||
infoList.values().toArray(new ClientListenerInfo[0]);
|
||||
|
||||
|
||||
beingReconnected = true;
|
||||
|
||||
infoList.clear();
|
||||
|
||||
return tmp;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called after reconnection is finished.
|
||||
* This method is intended to be called only by a client connector:
|
||||
* <code>RMIConnector</code> and <code>ClientIntermediary</code>.
|
||||
*/
|
||||
public synchronized void postReconnection(ClientListenerInfo[] listenerInfos)
|
||||
throws IOException {
|
||||
|
||||
if (state == TERMINATED) {
|
||||
return;
|
||||
}
|
||||
|
||||
while (state == STOPPING) {
|
||||
try {
|
||||
wait();
|
||||
} catch (InterruptedException ire) {
|
||||
IOException ioe = new IOException(ire.toString());
|
||||
EnvHelp.initCause(ioe, ire);
|
||||
throw ioe;
|
||||
}
|
||||
}
|
||||
|
||||
final boolean trace = logger.traceOn();
|
||||
final int len = listenerInfos.length;
|
||||
|
||||
for (int i=0; i<len; i++) {
|
||||
if (trace) {
|
||||
logger.trace("addNotificationListeners",
|
||||
"Add a listener at "+
|
||||
listenerInfos[i].getListenerID());
|
||||
}
|
||||
|
||||
infoList.put(listenerInfos[i].getListenerID(), listenerInfos[i]);
|
||||
}
|
||||
|
||||
beingReconnected = false;
|
||||
notifyAll();
|
||||
|
||||
if (currentFetchThread == Thread.currentThread() ||
|
||||
state == STARTING || state == STARTED) { // doing or waiting reconnection
|
||||
// only update mbeanRemovedNotifID
|
||||
try {
|
||||
mbeanRemovedNotifID = addListenerForMBeanRemovedNotif();
|
||||
} catch (Exception e) {
|
||||
final String msg =
|
||||
"Failed to register a listener to the mbean " +
|
||||
"server: the client will not do clean when an MBean " +
|
||||
"is unregistered";
|
||||
if (logger.traceOn()) {
|
||||
logger.trace("init", msg, e);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
while (state == STOPPING) {
|
||||
try {
|
||||
wait();
|
||||
} catch (InterruptedException ire) {
|
||||
IOException ioe = new IOException(ire.toString());
|
||||
EnvHelp.initCause(ioe, ire);
|
||||
throw ioe;
|
||||
}
|
||||
}
|
||||
|
||||
if (listenerInfos.length > 0) { // old listeners are re-added
|
||||
init(true); // not update clientSequenceNumber
|
||||
} else if (infoList.size() > 0) { // only new listeners added during reconnection
|
||||
init(false); // need update clientSequenceNumber
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public synchronized void terminate() {
|
||||
if (state == TERMINATED) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (logger.traceOn()) {
|
||||
logger.trace("terminate", "Terminating...");
|
||||
}
|
||||
|
||||
if (state == STARTED) {
|
||||
infoList.clear();
|
||||
}
|
||||
|
||||
setState(TERMINATED);
|
||||
}
|
||||
|
||||
|
||||
// -------------------------------------------------
|
||||
// private classes
|
||||
// -------------------------------------------------
|
||||
//
|
||||
|
||||
private class NotifFetcher implements Runnable {
|
||||
|
||||
private volatile boolean alreadyLogged = false;
|
||||
|
||||
private void logOnce(String msg, SecurityException x) {
|
||||
if (alreadyLogged) return;
|
||||
// Log only once.
|
||||
logger.config("setContextClassLoader",msg);
|
||||
if (x != null) logger.fine("setContextClassLoader", x);
|
||||
alreadyLogged = true;
|
||||
}
|
||||
|
||||
// Set new context class loader, returns previous one.
|
||||
private final ClassLoader setContextClassLoader(final ClassLoader loader) {
|
||||
final AccessControlContext ctxt = ClientNotifForwarder.this.acc;
|
||||
// if ctxt is null, log a config message and throw a
|
||||
// SecurityException.
|
||||
if (ctxt == null) {
|
||||
logOnce("AccessControlContext must not be null.",null);
|
||||
throw new SecurityException("AccessControlContext must not be null");
|
||||
}
|
||||
return AccessController.doPrivileged(
|
||||
new PrivilegedAction<ClassLoader>() {
|
||||
public ClassLoader run() {
|
||||
try {
|
||||
// get context class loader - may throw
|
||||
// SecurityException - though unlikely.
|
||||
final ClassLoader previous =
|
||||
Thread.currentThread().getContextClassLoader();
|
||||
|
||||
// if nothing needs to be done, break here...
|
||||
if (loader == previous) return previous;
|
||||
|
||||
// reset context class loader - may throw
|
||||
// SecurityException
|
||||
Thread.currentThread().setContextClassLoader(loader);
|
||||
return previous;
|
||||
} catch (SecurityException x) {
|
||||
logOnce("Permission to set ContextClassLoader missing. " +
|
||||
"Notifications will not be dispatched. " +
|
||||
"Please check your Java policy configuration: " +
|
||||
x, x);
|
||||
throw x;
|
||||
}
|
||||
}
|
||||
}, ctxt);
|
||||
}
|
||||
|
||||
public void run() {
|
||||
final ClassLoader previous;
|
||||
if (defaultClassLoader != null) {
|
||||
previous = setContextClassLoader(defaultClassLoader);
|
||||
} else {
|
||||
previous = null;
|
||||
}
|
||||
try {
|
||||
doRun();
|
||||
} finally {
|
||||
if (defaultClassLoader != null) {
|
||||
setContextClassLoader(previous);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void doRun() {
|
||||
synchronized (ClientNotifForwarder.this) {
|
||||
currentFetchThread = Thread.currentThread();
|
||||
|
||||
if (state == STARTING) {
|
||||
setState(STARTED);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
NotificationResult nr = null;
|
||||
if (!shouldStop() && (nr = fetchNotifs()) != null) {
|
||||
// nr == null means got exception
|
||||
|
||||
final TargetedNotification[] notifs =
|
||||
nr.getTargetedNotifications();
|
||||
final int len = notifs.length;
|
||||
final Map<Integer, ClientListenerInfo> listeners;
|
||||
final Integer myListenerID;
|
||||
|
||||
long missed = 0;
|
||||
|
||||
synchronized(ClientNotifForwarder.this) {
|
||||
// check sequence number.
|
||||
//
|
||||
if (clientSequenceNumber >= 0) {
|
||||
missed = nr.getEarliestSequenceNumber() -
|
||||
clientSequenceNumber;
|
||||
}
|
||||
|
||||
clientSequenceNumber = nr.getNextSequenceNumber();
|
||||
|
||||
listeners = new HashMap<Integer, ClientListenerInfo>();
|
||||
|
||||
for (int i = 0 ; i < len ; i++) {
|
||||
final TargetedNotification tn = notifs[i];
|
||||
final Integer listenerID = tn.getListenerID();
|
||||
|
||||
// check if an mbean unregistration notif
|
||||
if (!listenerID.equals(mbeanRemovedNotifID)) {
|
||||
final ClientListenerInfo li = infoList.get(listenerID);
|
||||
if (li != null) {
|
||||
listeners.put(listenerID, li);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
final Notification notif = tn.getNotification();
|
||||
final String unreg =
|
||||
MBeanServerNotification.UNREGISTRATION_NOTIFICATION;
|
||||
if (notif instanceof MBeanServerNotification &&
|
||||
notif.getType().equals(unreg)) {
|
||||
|
||||
MBeanServerNotification mbsn =
|
||||
(MBeanServerNotification) notif;
|
||||
ObjectName name = mbsn.getMBeanName();
|
||||
|
||||
removeNotificationListener(name);
|
||||
}
|
||||
}
|
||||
myListenerID = mbeanRemovedNotifID;
|
||||
}
|
||||
|
||||
if (missed > 0) {
|
||||
final String msg =
|
||||
"May have lost up to " + missed +
|
||||
" notification" + (missed == 1 ? "" : "s");
|
||||
lostNotifs(msg, missed);
|
||||
logger.trace("NotifFetcher.run", msg);
|
||||
}
|
||||
|
||||
// forward
|
||||
for (int i = 0 ; i < len ; i++) {
|
||||
final TargetedNotification tn = notifs[i];
|
||||
dispatchNotification(tn,myListenerID,listeners);
|
||||
}
|
||||
}
|
||||
|
||||
synchronized (ClientNotifForwarder.this) {
|
||||
currentFetchThread = null;
|
||||
}
|
||||
|
||||
if (nr == null) {
|
||||
if (logger.traceOn()) {
|
||||
logger.trace("NotifFetcher-run",
|
||||
"Recieved null object as notifs, stops fetching because the "
|
||||
+ "notification server is terminated.");
|
||||
}
|
||||
}
|
||||
if (nr == null || shouldStop()) {
|
||||
// tell that the thread is REALLY stopped
|
||||
setState(STOPPED);
|
||||
|
||||
try {
|
||||
removeListenerForMBeanRemovedNotif(mbeanRemovedNotifID);
|
||||
} catch (Exception e) {
|
||||
if (logger.traceOn()) {
|
||||
logger.trace("NotifFetcher-run",
|
||||
"removeListenerForMBeanRemovedNotif", e);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
executor.execute(this);
|
||||
}
|
||||
}
|
||||
|
||||
void dispatchNotification(TargetedNotification tn,
|
||||
Integer myListenerID,
|
||||
Map<Integer, ClientListenerInfo> listeners) {
|
||||
final Notification notif = tn.getNotification();
|
||||
final Integer listenerID = tn.getListenerID();
|
||||
|
||||
if (listenerID.equals(myListenerID)) return;
|
||||
final ClientListenerInfo li = listeners.get(listenerID);
|
||||
|
||||
if (li == null) {
|
||||
logger.trace("NotifFetcher.dispatch",
|
||||
"Listener ID not in map");
|
||||
return;
|
||||
}
|
||||
|
||||
NotificationListener l = li.getListener();
|
||||
Object h = li.getHandback();
|
||||
try {
|
||||
l.handleNotification(notif, h);
|
||||
} catch (RuntimeException e) {
|
||||
final String msg =
|
||||
"Failed to forward a notification " +
|
||||
"to a listener";
|
||||
logger.trace("NotifFetcher-run", msg, e);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private NotificationResult fetchNotifs() {
|
||||
try {
|
||||
NotificationResult nr = ClientNotifForwarder.this.
|
||||
fetchNotifs(clientSequenceNumber,maxNotifications,
|
||||
timeout);
|
||||
|
||||
if (logger.traceOn()) {
|
||||
logger.trace("NotifFetcher-run",
|
||||
"Got notifications from the server: "+nr);
|
||||
}
|
||||
|
||||
return nr;
|
||||
} catch (ClassNotFoundException | NotSerializableException | UnmarshalException e) {
|
||||
logger.trace("NotifFetcher.fetchNotifs", e);
|
||||
return fetchOneNotif();
|
||||
} catch (IOException ioe) {
|
||||
if (!shouldStop()) {
|
||||
logger.error("NotifFetcher-run",
|
||||
"Failed to fetch notification, " +
|
||||
"stopping thread. Error is: " + ioe, ioe);
|
||||
logger.debug("NotifFetcher-run",ioe);
|
||||
}
|
||||
|
||||
// no more fetching
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/* Fetch one notification when we suspect that it might be a
|
||||
notification that we can't deserialize (because of a
|
||||
missing class). First we ask for 0 notifications with 0
|
||||
timeout. This allows us to skip sequence numbers for
|
||||
notifications that don't match our filters. Then we ask
|
||||
for one notification. If that produces a
|
||||
ClassNotFoundException, NotSerializableException or
|
||||
UnmarshalException, we increase our sequence number and ask again.
|
||||
Eventually we will either get a successful notification, or a
|
||||
return with 0 notifications. In either case we can return a
|
||||
NotificationResult. This algorithm works (albeit less
|
||||
well) even if the server implementation doesn't optimize a
|
||||
request for 0 notifications to skip sequence numbers for
|
||||
notifications that don't match our filters.
|
||||
|
||||
If we had at least one
|
||||
ClassNotFoundException/NotSerializableException/UnmarshalException,
|
||||
then we must emit a JMXConnectionNotification.LOST_NOTIFS.
|
||||
*/
|
||||
private NotificationResult fetchOneNotif() {
|
||||
ClientNotifForwarder cnf = ClientNotifForwarder.this;
|
||||
|
||||
long startSequenceNumber = clientSequenceNumber;
|
||||
|
||||
int notFoundCount = 0;
|
||||
|
||||
NotificationResult result = null;
|
||||
long firstEarliest = -1;
|
||||
|
||||
while (result == null && !shouldStop()) {
|
||||
NotificationResult nr;
|
||||
|
||||
try {
|
||||
// 0 notifs to update startSequenceNumber
|
||||
nr = cnf.fetchNotifs(startSequenceNumber, 0, 0L);
|
||||
} catch (ClassNotFoundException e) {
|
||||
logger.warning("NotifFetcher.fetchOneNotif",
|
||||
"Impossible exception: " + e);
|
||||
logger.debug("NotifFetcher.fetchOneNotif",e);
|
||||
return null;
|
||||
} catch (IOException e) {
|
||||
if (!shouldStop())
|
||||
logger.trace("NotifFetcher.fetchOneNotif", e);
|
||||
return null;
|
||||
}
|
||||
|
||||
if (shouldStop() || nr == null)
|
||||
return null;
|
||||
|
||||
startSequenceNumber = nr.getNextSequenceNumber();
|
||||
if (firstEarliest < 0)
|
||||
firstEarliest = nr.getEarliestSequenceNumber();
|
||||
|
||||
try {
|
||||
// 1 notif to skip possible missing class
|
||||
result = cnf.fetchNotifs(startSequenceNumber, 1, 0L);
|
||||
} catch (ClassNotFoundException | NotSerializableException | UnmarshalException e) {
|
||||
logger.warning("NotifFetcher.fetchOneNotif",
|
||||
"Failed to deserialize a notification: "+e.toString());
|
||||
if (logger.traceOn()) {
|
||||
logger.trace("NotifFetcher.fetchOneNotif",
|
||||
"Failed to deserialize a notification.", e);
|
||||
}
|
||||
|
||||
notFoundCount++;
|
||||
startSequenceNumber++;
|
||||
} catch (Exception e) {
|
||||
if (!shouldStop())
|
||||
logger.trace("NotifFetcher.fetchOneNotif", e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
if (notFoundCount > 0) {
|
||||
final String msg =
|
||||
"Dropped " + notFoundCount + " notification" +
|
||||
(notFoundCount == 1 ? "" : "s") +
|
||||
" because classes were missing locally or incompatible";
|
||||
lostNotifs(msg, notFoundCount);
|
||||
// Even if result.getEarliestSequenceNumber() is now greater than
|
||||
// it was initially, meaning some notifs have been dropped
|
||||
// from the buffer, we don't want the caller to see that
|
||||
// because it is then likely to renotify about the lost notifs.
|
||||
// So we put back the first value of earliestSequenceNumber
|
||||
// that we saw.
|
||||
if (result != null) {
|
||||
result = new NotificationResult(
|
||||
firstEarliest, result.getNextSequenceNumber(),
|
||||
result.getTargetedNotifications());
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private boolean shouldStop() {
|
||||
synchronized (ClientNotifForwarder.this) {
|
||||
if (state != STARTED) {
|
||||
return true;
|
||||
} else if (infoList.size() == 0) {
|
||||
// no more listener, stop fetching
|
||||
setState(STOPPING);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// -------------------------------------------------
|
||||
// private methods
|
||||
// -------------------------------------------------
|
||||
private synchronized void setState(int newState) {
|
||||
if (state == TERMINATED) {
|
||||
return;
|
||||
}
|
||||
|
||||
state = newState;
|
||||
this.notifyAll();
|
||||
}
|
||||
|
||||
/*
|
||||
* Called to decide whether need to start a thread for fetching notifs.
|
||||
* <P>The parameter reconnected will decide whether to initilize the clientSequenceNumber,
|
||||
* initilaizing the clientSequenceNumber means to ignore all notifications arrived before.
|
||||
* If it is reconnected, we will not initialize in order to get all notifications arrived
|
||||
* during the reconnection. It may cause the newly registered listeners to receive some
|
||||
* notifications arrived before its registray.
|
||||
*/
|
||||
private synchronized void init(boolean reconnected) throws IOException {
|
||||
switch (state) {
|
||||
case STARTED:
|
||||
return;
|
||||
case STARTING:
|
||||
return;
|
||||
case TERMINATED:
|
||||
throw new IOException("The ClientNotifForwarder has been terminated.");
|
||||
case STOPPING:
|
||||
if (beingReconnected == true) {
|
||||
// wait for another thread to do, which is doing reconnection
|
||||
return;
|
||||
}
|
||||
|
||||
while (state == STOPPING) { // make sure only one fetching thread.
|
||||
try {
|
||||
wait();
|
||||
} catch (InterruptedException ire) {
|
||||
IOException ioe = new IOException(ire.toString());
|
||||
EnvHelp.initCause(ioe, ire);
|
||||
|
||||
throw ioe;
|
||||
}
|
||||
}
|
||||
|
||||
// re-call this method to check the state again,
|
||||
// the state can be other value like TERMINATED.
|
||||
init(reconnected);
|
||||
|
||||
return;
|
||||
case STOPPED:
|
||||
if (beingReconnected == true) {
|
||||
// wait for another thread to do, which is doing reconnection
|
||||
return;
|
||||
}
|
||||
|
||||
if (logger.traceOn()) {
|
||||
logger.trace("init", "Initializing...");
|
||||
}
|
||||
|
||||
// init the clientSequenceNumber if not reconnected.
|
||||
if (!reconnected) {
|
||||
try {
|
||||
NotificationResult nr = fetchNotifs(-1, 0, 0);
|
||||
|
||||
if (state != STOPPED) { // JDK-8038940
|
||||
// reconnection must happen during
|
||||
// fetchNotifs(-1, 0, 0), and a new
|
||||
// thread takes over the fetching job
|
||||
return;
|
||||
}
|
||||
|
||||
clientSequenceNumber = nr.getNextSequenceNumber();
|
||||
} catch (ClassNotFoundException e) {
|
||||
// can't happen
|
||||
logger.warning("init", "Impossible exception: "+ e);
|
||||
logger.debug("init",e);
|
||||
}
|
||||
}
|
||||
|
||||
// for cleaning
|
||||
try {
|
||||
mbeanRemovedNotifID = addListenerForMBeanRemovedNotif();
|
||||
} catch (Exception e) {
|
||||
final String msg =
|
||||
"Failed to register a listener to the mbean " +
|
||||
"server: the client will not do clean when an MBean " +
|
||||
"is unregistered";
|
||||
if (logger.traceOn()) {
|
||||
logger.trace("init", msg, e);
|
||||
}
|
||||
}
|
||||
|
||||
setState(STARTING);
|
||||
|
||||
// start fetching
|
||||
executor.execute(new NotifFetcher());
|
||||
|
||||
return;
|
||||
default:
|
||||
// should not
|
||||
throw new IOException("Unknown state.");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Import: should not remove a listener during reconnection, the reconnection
|
||||
* needs to change the listener list and that will possibly make removal fail.
|
||||
*/
|
||||
private synchronized void beforeRemove() throws IOException {
|
||||
while (beingReconnected) {
|
||||
if (state == TERMINATED) {
|
||||
throw new IOException("Terminated.");
|
||||
}
|
||||
|
||||
try {
|
||||
wait();
|
||||
} catch (InterruptedException ire) {
|
||||
IOException ioe = new IOException(ire.toString());
|
||||
EnvHelp.initCause(ioe, ire);
|
||||
|
||||
throw ioe;
|
||||
}
|
||||
}
|
||||
|
||||
if (state == TERMINATED) {
|
||||
throw new IOException("Terminated.");
|
||||
}
|
||||
}
|
||||
|
||||
// -------------------------------------------------
|
||||
// private variables
|
||||
// -------------------------------------------------
|
||||
|
||||
private final ClassLoader defaultClassLoader;
|
||||
private final Executor executor;
|
||||
|
||||
private final Map<Integer, ClientListenerInfo> infoList =
|
||||
new HashMap<Integer, ClientListenerInfo>();
|
||||
|
||||
// notif stuff
|
||||
private long clientSequenceNumber = -1;
|
||||
private final int maxNotifications;
|
||||
private final long timeout;
|
||||
private Integer mbeanRemovedNotifID = null;
|
||||
private Thread currentFetchThread;
|
||||
|
||||
// state
|
||||
/**
|
||||
* This state means that a thread is being created for fetching and forwarding notifications.
|
||||
*/
|
||||
private static final int STARTING = 0;
|
||||
|
||||
/**
|
||||
* This state tells that a thread has been started for fetching and forwarding notifications.
|
||||
*/
|
||||
private static final int STARTED = 1;
|
||||
|
||||
/**
|
||||
* This state means that the fetching thread is informed to stop.
|
||||
*/
|
||||
private static final int STOPPING = 2;
|
||||
|
||||
/**
|
||||
* This state means that the fetching thread is already stopped.
|
||||
*/
|
||||
private static final int STOPPED = 3;
|
||||
|
||||
/**
|
||||
* This state means that this object is terminated and no more thread will be created
|
||||
* for fetching notifications.
|
||||
*/
|
||||
private static final int TERMINATED = 4;
|
||||
|
||||
private int state = STOPPED;
|
||||
|
||||
/**
|
||||
* This variable is used to tell whether a connector (RMIConnector or ClientIntermediary)
|
||||
* is doing reconnection.
|
||||
* This variable will be set to true by the method <code>preReconnection</code>, and set
|
||||
* to false by <code>postReconnection</code>.
|
||||
* When beingReconnected == true, no thread will be created for fetching notifications.
|
||||
*/
|
||||
private boolean beingReconnected = false;
|
||||
|
||||
private static final ClassLogger logger =
|
||||
new ClassLogger("javax.management.remote.misc",
|
||||
"ClientNotifForwarder");
|
||||
}
|
||||
190
jdkSrc/jdk8/com/sun/jmx/remote/internal/IIOPHelper.java
Normal file
190
jdkSrc/jdk8/com/sun/jmx/remote/internal/IIOPHelper.java
Normal file
@@ -0,0 +1,190 @@
|
||||
/*
|
||||
* Copyright (c) 2009, 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package com.sun.jmx.remote.internal;
|
||||
|
||||
import java.util.Properties;
|
||||
import java.io.IOException;
|
||||
import java.rmi.Remote;
|
||||
import java.rmi.NoSuchObjectException;
|
||||
|
||||
import java.security.AccessController;
|
||||
import java.security.PrivilegedAction;
|
||||
|
||||
/**
|
||||
* A helper class for RMI-IIOP and CORBA APIs.
|
||||
*/
|
||||
|
||||
public final class IIOPHelper {
|
||||
private IIOPHelper() { }
|
||||
|
||||
// loads IIOPProxy implementation class if available
|
||||
private static final String IMPL_CLASS =
|
||||
"com.sun.jmx.remote.protocol.iiop.IIOPProxyImpl";
|
||||
private static final IIOPProxy proxy =
|
||||
AccessController.doPrivileged(new PrivilegedAction<IIOPProxy>() {
|
||||
public IIOPProxy run() {
|
||||
try {
|
||||
Class<?> c = Class.forName(IMPL_CLASS, true,
|
||||
IIOPHelper.class.getClassLoader());
|
||||
return (IIOPProxy)c.newInstance();
|
||||
} catch (ClassNotFoundException cnf) {
|
||||
return null;
|
||||
} catch (InstantiationException e) {
|
||||
throw new AssertionError(e);
|
||||
} catch (IllegalAccessException e) {
|
||||
throw new AssertionError(e);
|
||||
}
|
||||
}});
|
||||
|
||||
/**
|
||||
* Returns true if RMI-IIOP and CORBA is available.
|
||||
*/
|
||||
public static boolean isAvailable() {
|
||||
return proxy != null;
|
||||
}
|
||||
|
||||
private static void ensureAvailable() {
|
||||
if (proxy == null)
|
||||
throw new AssertionError("Should not here");
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the given object is a Stub.
|
||||
*/
|
||||
public static boolean isStub(Object obj) {
|
||||
return (proxy == null) ? false : proxy.isStub(obj);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the Delegate to which the given Stub delegates.
|
||||
*/
|
||||
public static Object getDelegate(Object stub) {
|
||||
ensureAvailable();
|
||||
return proxy.getDelegate(stub);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the Delegate for a given Stub.
|
||||
*/
|
||||
public static void setDelegate(Object stub, Object delegate) {
|
||||
ensureAvailable();
|
||||
proxy.setDelegate(stub, delegate);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the ORB associated with the given stub
|
||||
*
|
||||
* @throws UnsupportedOperationException
|
||||
* if the object does not support the operation that
|
||||
* was invoked
|
||||
*/
|
||||
public static Object getOrb(Object stub) {
|
||||
ensureAvailable();
|
||||
return proxy.getOrb(stub);
|
||||
}
|
||||
|
||||
/**
|
||||
* Connects the Stub to the given ORB.
|
||||
*/
|
||||
public static void connect(Object stub, Object orb)
|
||||
throws IOException
|
||||
{
|
||||
if (proxy == null)
|
||||
throw new IOException("Connection to ORB failed, RMI/IIOP not available");
|
||||
proxy.connect(stub, orb);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the given object is an ORB.
|
||||
*/
|
||||
public static boolean isOrb(Object obj) {
|
||||
return (proxy == null) ? false : proxy.isOrb(obj);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates, and returns, a new ORB instance.
|
||||
*/
|
||||
public static Object createOrb(String[] args, Properties props)
|
||||
throws IOException
|
||||
{
|
||||
if (proxy == null)
|
||||
throw new IOException("ORB initialization failed, RMI/IIOP not available");
|
||||
return proxy.createOrb(args, props);
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a string, produced by the object_to_string method, back
|
||||
* to a CORBA object reference.
|
||||
*/
|
||||
public static Object stringToObject(Object orb, String str) {
|
||||
ensureAvailable();
|
||||
return proxy.stringToObject(orb, str);
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts the given CORBA object reference to a string.
|
||||
*/
|
||||
public static String objectToString(Object orb, Object obj) {
|
||||
ensureAvailable();
|
||||
return proxy.objectToString(orb, obj);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks to ensure that an object of a remote or abstract interface
|
||||
* type can be cast to a desired type.
|
||||
*/
|
||||
public static <T> T narrow(Object narrowFrom, Class<T> narrowTo) {
|
||||
ensureAvailable();
|
||||
return proxy.narrow(narrowFrom, narrowTo);
|
||||
}
|
||||
|
||||
/**
|
||||
* Makes a server object ready to receive remote calls
|
||||
*/
|
||||
public static void exportObject(Remote obj) throws IOException {
|
||||
if (proxy == null)
|
||||
throw new IOException("RMI object cannot be exported, RMI/IIOP not available");
|
||||
proxy.exportObject(obj);
|
||||
}
|
||||
|
||||
/**
|
||||
* Deregisters a server object from the runtime.
|
||||
*/
|
||||
public static void unexportObject(Remote obj) throws IOException {
|
||||
if (proxy == null)
|
||||
throw new NoSuchObjectException("Object not exported");
|
||||
proxy.unexportObject(obj);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a stub for the given server object.
|
||||
*/
|
||||
public static Remote toStub(Remote obj) throws IOException {
|
||||
if (proxy == null)
|
||||
throw new NoSuchObjectException("Object not exported");
|
||||
return proxy.toStub(obj);
|
||||
}
|
||||
}
|
||||
110
jdkSrc/jdk8/com/sun/jmx/remote/internal/IIOPProxy.java
Normal file
110
jdkSrc/jdk8/com/sun/jmx/remote/internal/IIOPProxy.java
Normal file
@@ -0,0 +1,110 @@
|
||||
/*
|
||||
* 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 com.sun.jmx.remote.internal;
|
||||
|
||||
import java.util.Properties;
|
||||
import java.rmi.Remote;
|
||||
import java.rmi.RemoteException;
|
||||
import java.rmi.NoSuchObjectException;
|
||||
|
||||
/**
|
||||
* An interface to a subset of the RMI-IIOP and CORBA APIs to avoid a
|
||||
* static dependencies on the types defined by these APIs.
|
||||
*/
|
||||
|
||||
public interface IIOPProxy {
|
||||
|
||||
/**
|
||||
* Returns true if the given object is a Stub.
|
||||
*/
|
||||
boolean isStub(Object obj);
|
||||
|
||||
/**
|
||||
* Returns the Delegate to which the given Stub delegates.
|
||||
*/
|
||||
Object getDelegate(Object stub);
|
||||
|
||||
/**
|
||||
* Sets the Delegate for a given Stub.
|
||||
*/
|
||||
void setDelegate(Object stub, Object delegate);
|
||||
|
||||
/**
|
||||
* Returns the ORB associated with the given stub
|
||||
*
|
||||
* @throws UnsupportedOperationException
|
||||
* if the object does not support the operation that
|
||||
* was invoked
|
||||
*/
|
||||
Object getOrb(Object stub);
|
||||
|
||||
/**
|
||||
* Connects the Stub to the given ORB.
|
||||
*/
|
||||
void connect(Object stub, Object orb) throws RemoteException;
|
||||
|
||||
/**
|
||||
* Returns true if the given object is an ORB.
|
||||
*/
|
||||
boolean isOrb(Object obj);
|
||||
|
||||
/**
|
||||
* Creates, and returns, a new ORB instance.
|
||||
*/
|
||||
Object createOrb(String[] args, Properties props);
|
||||
|
||||
/**
|
||||
* Converts a string, produced by the object_to_string method, back
|
||||
* to a CORBA object reference.
|
||||
*/
|
||||
Object stringToObject(Object orb, String str);
|
||||
|
||||
/**
|
||||
* Converts the given CORBA object reference to a string.
|
||||
*/
|
||||
String objectToString(Object orb, Object obj);
|
||||
|
||||
/**
|
||||
* Checks to ensure that an object of a remote or abstract interface
|
||||
* type can be cast to a desired type.
|
||||
*/
|
||||
<T> T narrow(Object narrowFrom, Class<T> narrowTo);
|
||||
|
||||
/**
|
||||
* Makes a server object ready to receive remote calls
|
||||
*/
|
||||
void exportObject(Remote obj) throws RemoteException;
|
||||
|
||||
/**
|
||||
* Deregisters a server object from the runtime.
|
||||
*/
|
||||
void unexportObject(Remote obj) throws NoSuchObjectException;
|
||||
|
||||
/**
|
||||
* Returns a stub for the given server object.
|
||||
*/
|
||||
Remote toStub(Remote obj) throws NoSuchObjectException;
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
/*
|
||||
* Copyright (c) 2003, 2006, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package com.sun.jmx.remote.internal;
|
||||
|
||||
import java.util.Set;
|
||||
import javax.management.remote.NotificationResult;
|
||||
import javax.management.remote.TargetedNotification;
|
||||
|
||||
/** A buffer of notifications received from an MBean server. */
|
||||
public interface NotificationBuffer {
|
||||
/**
|
||||
* <p>Fetch notifications that match the given listeners.</p>
|
||||
*
|
||||
* <p>The operation only considers notifications with a sequence
|
||||
* number at least <code>startSequenceNumber</code>. It will take
|
||||
* no longer than <code>timeout</code>, and will return no more
|
||||
* than <code>maxNotifications</code> different notifications.</p>
|
||||
*
|
||||
* <p>If there are no notifications matching the criteria, the
|
||||
* operation will block until one arrives, subject to the
|
||||
* timeout.</p>
|
||||
*
|
||||
* @param filter an object that will add notifications to a
|
||||
* {@code List<TargetedNotification>} if they match the current
|
||||
* listeners with their filters.
|
||||
* @param startSequenceNumber the first sequence number to
|
||||
* consider.
|
||||
* @param timeout the maximum time to wait. May be 0 to indicate
|
||||
* not to wait if there are no notifications.
|
||||
* @param maxNotifications the maximum number of notifications to
|
||||
* return. May be 0 to indicate a wait for eligible notifications
|
||||
* that will return a usable <code>nextSequenceNumber</code>. The
|
||||
* {@link TargetedNotification} array in the returned {@link
|
||||
* NotificationResult} may contain more than this number of
|
||||
* elements but will not contain more than this number of
|
||||
* different notifications.
|
||||
*/
|
||||
public NotificationResult
|
||||
fetchNotifications(NotificationBufferFilter filter,
|
||||
long startSequenceNumber,
|
||||
long timeout,
|
||||
int maxNotifications)
|
||||
throws InterruptedException;
|
||||
|
||||
/**
|
||||
* <p>Discard this buffer.</p>
|
||||
*/
|
||||
public void dispose();
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* Copyright (c) 2006, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package com.sun.jmx.remote.internal;
|
||||
|
||||
import java.util.List;
|
||||
import javax.management.Notification;
|
||||
import javax.management.ObjectName;
|
||||
import javax.management.remote.TargetedNotification;
|
||||
|
||||
public interface NotificationBufferFilter {
|
||||
/**
|
||||
* Add the given notification coming from the given MBean to the list
|
||||
* iff it matches this filter's rules.
|
||||
*/
|
||||
public void apply(List<TargetedNotification> targetedNotifs,
|
||||
ObjectName source, Notification notif);
|
||||
}
|
||||
103
jdkSrc/jdk8/com/sun/jmx/remote/internal/ProxyRef.java
Normal file
103
jdkSrc/jdk8/com/sun/jmx/remote/internal/ProxyRef.java
Normal file
@@ -0,0 +1,103 @@
|
||||
/*
|
||||
* 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.internal;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.ObjectInput;
|
||||
import java.io.ObjectOutput;
|
||||
import java.lang.reflect.Method;
|
||||
import java.rmi.Remote;
|
||||
import java.rmi.RemoteException;
|
||||
import java.rmi.server.RemoteObject;
|
||||
import java.rmi.server.RemoteRef;
|
||||
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
public class ProxyRef implements RemoteRef {
|
||||
private static final long serialVersionUID = -6503061366316814723L;
|
||||
|
||||
public ProxyRef(RemoteRef ref) {
|
||||
this.ref = ref;
|
||||
}
|
||||
|
||||
public void readExternal(ObjectInput in)
|
||||
throws IOException, ClassNotFoundException {
|
||||
ref.readExternal(in);
|
||||
}
|
||||
|
||||
public void writeExternal(ObjectOutput out) throws IOException {
|
||||
ref.writeExternal(out);
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated
|
||||
*/
|
||||
@Deprecated
|
||||
public void invoke(java.rmi.server.RemoteCall call) throws Exception {
|
||||
ref.invoke(call);
|
||||
}
|
||||
|
||||
public Object invoke(Remote obj, Method method, Object[] params,
|
||||
long opnum) throws Exception {
|
||||
return ref.invoke(obj, method, params, opnum);
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated
|
||||
*/
|
||||
@Deprecated
|
||||
public void done(java.rmi.server.RemoteCall call) throws RemoteException {
|
||||
ref.done(call);
|
||||
}
|
||||
|
||||
public String getRefClass(ObjectOutput out) {
|
||||
return ref.getRefClass(out);
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated
|
||||
*/
|
||||
@Deprecated
|
||||
public java.rmi.server.RemoteCall newCall(RemoteObject obj,
|
||||
java.rmi.server.Operation[] op, int opnum,
|
||||
long hash) throws RemoteException {
|
||||
return ref.newCall(obj, op, opnum, hash);
|
||||
}
|
||||
|
||||
public boolean remoteEquals(RemoteRef obj) {
|
||||
return ref.remoteEquals(obj);
|
||||
}
|
||||
|
||||
public int remoteHashCode() {
|
||||
return ref.remoteHashCode();
|
||||
}
|
||||
|
||||
public String remoteToString() {
|
||||
return ref.remoteToString();
|
||||
}
|
||||
|
||||
protected RemoteRef ref;
|
||||
}
|
||||
59
jdkSrc/jdk8/com/sun/jmx/remote/internal/RMIExporter.java
Normal file
59
jdkSrc/jdk8/com/sun/jmx/remote/internal/RMIExporter.java
Normal file
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
* Copyright (c) 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 com.sun.jmx.remote.internal;
|
||||
|
||||
import java.rmi.NoSuchObjectException;
|
||||
import java.rmi.Remote;
|
||||
import java.rmi.RemoteException;
|
||||
import java.rmi.server.RMIClientSocketFactory;
|
||||
import java.rmi.server.RMIServerSocketFactory;
|
||||
import java.rmi.server.UnicastRemoteObject;
|
||||
|
||||
/**
|
||||
* <p>Unpublished interface controlling how the RMI Connector Server
|
||||
* exports objects. The RMIServerImpl object and each
|
||||
* RMIConnectionImpl object are exported using the exporter. The
|
||||
* default exporter calls {@link
|
||||
* UnicastRemoteObject#exportObject(Remote, int,
|
||||
* RMIClientSocketFactory, RMIServerSocketFactory)} to export objects
|
||||
* and {@link UnicastRemoteObject#unexportObject(Remote, boolean)} to
|
||||
* unexport them. A replacement exporter can be specified via the
|
||||
* {@link #EXPORTER_ATTRIBUTE} property in the environment Map passed
|
||||
* to the RMI connector server.</p>
|
||||
*/
|
||||
public interface RMIExporter {
|
||||
public static final String EXPORTER_ATTRIBUTE =
|
||||
"com.sun.jmx.remote.rmi.exporter";
|
||||
|
||||
public Remote exportObject(Remote obj,
|
||||
int port,
|
||||
RMIClientSocketFactory csf,
|
||||
RMIServerSocketFactory ssf)
|
||||
throws RemoteException;
|
||||
|
||||
public boolean unexportObject(Remote obj, boolean force)
|
||||
throws NoSuchObjectException;
|
||||
}
|
||||
@@ -0,0 +1,232 @@
|
||||
/*
|
||||
* Copyright (c) 2003, 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 com.sun.jmx.remote.internal;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import com.sun.jmx.remote.util.ClassLogger;
|
||||
|
||||
public abstract class ServerCommunicatorAdmin {
|
||||
public ServerCommunicatorAdmin(long timeout) {
|
||||
if (logger.traceOn()) {
|
||||
logger.trace("Constructor",
|
||||
"Creates a new ServerCommunicatorAdmin object "+
|
||||
"with the timeout "+timeout);
|
||||
}
|
||||
|
||||
this.timeout = timeout;
|
||||
|
||||
timestamp = 0;
|
||||
if (timeout < Long.MAX_VALUE) {
|
||||
Runnable timeoutTask = new Timeout();
|
||||
final Thread t = new Thread(timeoutTask);
|
||||
t.setName("JMX server connection timeout " + t.getId());
|
||||
// If you change this name you will need to change a unit test
|
||||
// (NoServerTimeoutTest)
|
||||
t.setDaemon(true);
|
||||
t.start();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tells that a new request message is received.
|
||||
* A caller of this method should always call the method
|
||||
* <code>rspOutgoing</code> to inform that a response is sent out
|
||||
* for the received request.
|
||||
* @return the value of the termination flag:
|
||||
* <ul><code>true</code> if the connection is already being terminated,
|
||||
* <br><code>false</code> otherwise.</ul>
|
||||
*/
|
||||
public boolean reqIncoming() {
|
||||
if (logger.traceOn()) {
|
||||
logger.trace("reqIncoming", "Receive a new request.");
|
||||
}
|
||||
|
||||
synchronized(lock) {
|
||||
if (terminated) {
|
||||
logger.warning("reqIncoming",
|
||||
"The server has decided to close " +
|
||||
"this client connection.");
|
||||
}
|
||||
++currentJobs;
|
||||
|
||||
return terminated;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tells that a response is sent out for a received request.
|
||||
* @return the value of the termination flag:
|
||||
* <ul><code>true</code> if the connection is already being terminated,
|
||||
* <br><code>false</code> otherwise.</ul>
|
||||
*/
|
||||
public boolean rspOutgoing() {
|
||||
if (logger.traceOn()) {
|
||||
logger.trace("reqIncoming", "Finish a request.");
|
||||
}
|
||||
|
||||
synchronized(lock) {
|
||||
if (--currentJobs == 0) {
|
||||
timestamp = System.currentTimeMillis();
|
||||
logtime("Admin: Timestamp=",timestamp);
|
||||
// tells the adminor to restart waiting with timeout
|
||||
lock.notify();
|
||||
}
|
||||
return terminated;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Called by this class to tell an implementation to do stop.
|
||||
*/
|
||||
protected abstract void doStop();
|
||||
|
||||
/**
|
||||
* Terminates this object.
|
||||
* Called only by outside, so do not need to call doStop
|
||||
*/
|
||||
public void terminate() {
|
||||
if (logger.traceOn()) {
|
||||
logger.trace("terminate",
|
||||
"terminate the ServerCommunicatorAdmin object.");
|
||||
}
|
||||
|
||||
synchronized(lock) {
|
||||
if (terminated) {
|
||||
return;
|
||||
}
|
||||
|
||||
terminated = true;
|
||||
|
||||
// tell Timeout to terminate
|
||||
lock.notify();
|
||||
}
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------
|
||||
// private classes
|
||||
// --------------------------------------------------------------
|
||||
private class Timeout implements Runnable {
|
||||
public void run() {
|
||||
boolean stopping = false;
|
||||
|
||||
synchronized(lock) {
|
||||
if (timestamp == 0) timestamp = System.currentTimeMillis();
|
||||
logtime("Admin: timeout=",timeout);
|
||||
logtime("Admin: Timestamp=",timestamp);
|
||||
|
||||
while(!terminated) {
|
||||
try {
|
||||
// wait until there is no more job
|
||||
while(!terminated && currentJobs != 0) {
|
||||
if (logger.traceOn()) {
|
||||
logger.trace("Timeout-run",
|
||||
"Waiting without timeout.");
|
||||
}
|
||||
|
||||
lock.wait();
|
||||
}
|
||||
|
||||
if (terminated) return;
|
||||
|
||||
final long remaining =
|
||||
timeout - (System.currentTimeMillis() - timestamp);
|
||||
|
||||
logtime("Admin: remaining timeout=",remaining);
|
||||
|
||||
if (remaining > 0) {
|
||||
|
||||
if (logger.traceOn()) {
|
||||
logger.trace("Timeout-run",
|
||||
"Waiting with timeout: "+
|
||||
remaining + " ms remaining");
|
||||
}
|
||||
|
||||
lock.wait(remaining);
|
||||
}
|
||||
|
||||
if (currentJobs > 0) continue;
|
||||
|
||||
final long elapsed =
|
||||
System.currentTimeMillis() - timestamp;
|
||||
logtime("Admin: elapsed=",elapsed);
|
||||
|
||||
if (!terminated && elapsed > timeout) {
|
||||
if (logger.traceOn()) {
|
||||
logger.trace("Timeout-run",
|
||||
"timeout elapsed");
|
||||
}
|
||||
logtime("Admin: timeout elapsed! "+
|
||||
elapsed+">",timeout);
|
||||
// stopping
|
||||
terminated = true;
|
||||
|
||||
stopping = true;
|
||||
break;
|
||||
}
|
||||
} catch (InterruptedException ire) {
|
||||
logger.warning("Timeout-run","Unexpected Exception: "+
|
||||
ire);
|
||||
logger.debug("Timeout-run",ire);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (stopping) {
|
||||
if (logger.traceOn()) {
|
||||
logger.trace("Timeout-run", "Call the doStop.");
|
||||
}
|
||||
|
||||
doStop();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void logtime(String desc,long time) {
|
||||
timelogger.trace("synchro",desc+time);
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------
|
||||
// private variables
|
||||
// --------------------------------------------------------------
|
||||
private long timestamp;
|
||||
|
||||
private final int[] lock = new int[0];
|
||||
private int currentJobs = 0;
|
||||
|
||||
private long timeout;
|
||||
|
||||
// state issue
|
||||
private boolean terminated = false;
|
||||
|
||||
private static final ClassLogger logger =
|
||||
new ClassLogger("javax.management.remote.misc",
|
||||
"ServerCommunicatorAdmin");
|
||||
private static final ClassLogger timelogger =
|
||||
new ClassLogger("javax.management.remote.timeout",
|
||||
"ServerCommunicatorAdmin");
|
||||
}
|
||||
@@ -0,0 +1,506 @@
|
||||
/*
|
||||
* Copyright (c) 2002, 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 com.sun.jmx.remote.internal;
|
||||
|
||||
import com.sun.jmx.remote.security.NotificationAccessController;
|
||||
import com.sun.jmx.remote.util.ClassLogger;
|
||||
import com.sun.jmx.remote.util.EnvHelp;
|
||||
import java.io.IOException;
|
||||
import java.security.AccessControlContext;
|
||||
import java.security.AccessController;
|
||||
import java.security.PrivilegedActionException;
|
||||
import java.security.PrivilegedExceptionAction;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import javax.management.InstanceNotFoundException;
|
||||
import javax.management.ListenerNotFoundException;
|
||||
import javax.management.MBeanPermission;
|
||||
import javax.management.MBeanServer;
|
||||
import javax.management.MBeanServerDelegate;
|
||||
import javax.management.MBeanServerNotification;
|
||||
import javax.management.Notification;
|
||||
import javax.management.NotificationBroadcaster;
|
||||
import javax.management.NotificationFilter;
|
||||
import javax.management.ObjectInstance;
|
||||
import javax.management.ObjectName;
|
||||
import javax.management.remote.NotificationResult;
|
||||
import javax.management.remote.TargetedNotification;
|
||||
import javax.management.MalformedObjectNameException;
|
||||
import javax.security.auth.Subject;
|
||||
|
||||
public class ServerNotifForwarder {
|
||||
|
||||
|
||||
public ServerNotifForwarder(MBeanServer mbeanServer,
|
||||
Map<String, ?> env,
|
||||
NotificationBuffer notifBuffer,
|
||||
String connectionId) {
|
||||
this.mbeanServer = mbeanServer;
|
||||
this.notifBuffer = notifBuffer;
|
||||
this.connectionId = connectionId;
|
||||
connectionTimeout = EnvHelp.getServerConnectionTimeout(env);
|
||||
|
||||
String stringBoolean = (String) env.get("jmx.remote.x.check.notification.emission");
|
||||
checkNotificationEmission = EnvHelp.computeBooleanFromString( stringBoolean );
|
||||
notificationAccessController =
|
||||
EnvHelp.getNotificationAccessController(env);
|
||||
}
|
||||
|
||||
public Integer addNotificationListener(final ObjectName name,
|
||||
final NotificationFilter filter)
|
||||
throws InstanceNotFoundException, IOException {
|
||||
|
||||
if (logger.traceOn()) {
|
||||
logger.trace("addNotificationListener",
|
||||
"Add a listener at " + name);
|
||||
}
|
||||
|
||||
checkState();
|
||||
|
||||
// Explicitly check MBeanPermission for addNotificationListener
|
||||
//
|
||||
checkMBeanPermission(name, "addNotificationListener");
|
||||
if (notificationAccessController != null) {
|
||||
notificationAccessController.addNotificationListener(
|
||||
connectionId, name, getSubject());
|
||||
}
|
||||
try {
|
||||
boolean instanceOf =
|
||||
AccessController.doPrivileged(
|
||||
new PrivilegedExceptionAction<Boolean>() {
|
||||
public Boolean run() throws InstanceNotFoundException {
|
||||
return mbeanServer.isInstanceOf(name, broadcasterClass);
|
||||
}
|
||||
});
|
||||
if (!instanceOf) {
|
||||
throw new IllegalArgumentException("The specified MBean [" +
|
||||
name + "] is not a " +
|
||||
"NotificationBroadcaster " +
|
||||
"object.");
|
||||
}
|
||||
} catch (PrivilegedActionException e) {
|
||||
throw (InstanceNotFoundException) extractException(e);
|
||||
}
|
||||
|
||||
final Integer id = getListenerID();
|
||||
|
||||
// 6238731: set the default domain if no domain is set.
|
||||
ObjectName nn = name;
|
||||
if (name.getDomain() == null || name.getDomain().equals("")) {
|
||||
try {
|
||||
nn = ObjectName.getInstance(mbeanServer.getDefaultDomain(),
|
||||
name.getKeyPropertyList());
|
||||
} catch (MalformedObjectNameException mfoe) {
|
||||
// impossible, but...
|
||||
IOException ioe = new IOException(mfoe.getMessage());
|
||||
ioe.initCause(mfoe);
|
||||
throw ioe;
|
||||
}
|
||||
}
|
||||
|
||||
synchronized (listenerMap) {
|
||||
IdAndFilter idaf = new IdAndFilter(id, filter);
|
||||
Set<IdAndFilter> set = listenerMap.get(nn);
|
||||
// Tread carefully because if set.size() == 1 it may be the
|
||||
// Collections.singleton we make here, which is unmodifiable.
|
||||
if (set == null)
|
||||
set = Collections.singleton(idaf);
|
||||
else {
|
||||
if (set.size() == 1)
|
||||
set = new HashSet<IdAndFilter>(set);
|
||||
set.add(idaf);
|
||||
}
|
||||
listenerMap.put(nn, set);
|
||||
}
|
||||
|
||||
return id;
|
||||
}
|
||||
|
||||
public void removeNotificationListener(ObjectName name,
|
||||
Integer[] listenerIDs)
|
||||
throws Exception {
|
||||
|
||||
if (logger.traceOn()) {
|
||||
logger.trace("removeNotificationListener",
|
||||
"Remove some listeners from " + name);
|
||||
}
|
||||
|
||||
checkState();
|
||||
|
||||
// Explicitly check MBeanPermission for removeNotificationListener
|
||||
//
|
||||
checkMBeanPermission(name, "removeNotificationListener");
|
||||
if (notificationAccessController != null) {
|
||||
notificationAccessController.removeNotificationListener(
|
||||
connectionId, name, getSubject());
|
||||
}
|
||||
|
||||
Exception re = null;
|
||||
for (int i = 0 ; i < listenerIDs.length ; i++) {
|
||||
try {
|
||||
removeNotificationListener(name, listenerIDs[i]);
|
||||
} catch (Exception e) {
|
||||
// Give back the first exception
|
||||
//
|
||||
if (re != null) {
|
||||
re = e;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (re != null) {
|
||||
throw re;
|
||||
}
|
||||
}
|
||||
|
||||
public void removeNotificationListener(ObjectName name, Integer listenerID)
|
||||
throws
|
||||
InstanceNotFoundException,
|
||||
ListenerNotFoundException,
|
||||
IOException {
|
||||
|
||||
if (logger.traceOn()) {
|
||||
logger.trace("removeNotificationListener",
|
||||
"Remove the listener " + listenerID + " from " + name);
|
||||
}
|
||||
|
||||
checkState();
|
||||
|
||||
if (name != null && !name.isPattern()) {
|
||||
if (!mbeanServer.isRegistered(name)) {
|
||||
throw new InstanceNotFoundException("The MBean " + name +
|
||||
" is not registered.");
|
||||
}
|
||||
}
|
||||
|
||||
synchronized (listenerMap) {
|
||||
// Tread carefully because if set.size() == 1 it may be a
|
||||
// Collections.singleton, which is unmodifiable.
|
||||
Set<IdAndFilter> set = listenerMap.get(name);
|
||||
IdAndFilter idaf = new IdAndFilter(listenerID, null);
|
||||
if (set == null || !set.contains(idaf))
|
||||
throw new ListenerNotFoundException("Listener not found");
|
||||
if (set.size() == 1)
|
||||
listenerMap.remove(name);
|
||||
else
|
||||
set.remove(idaf);
|
||||
}
|
||||
}
|
||||
|
||||
/* This is the object that will apply our filtering to candidate
|
||||
* notifications. First of all, if there are no listeners for the
|
||||
* ObjectName that the notification is coming from, we go no further.
|
||||
* Then, for each listener, we must apply the corresponding filter (if any)
|
||||
* and ignore the listener if the filter rejects. Finally, we apply
|
||||
* some access checks which may also reject the listener.
|
||||
*
|
||||
* A given notification may trigger several listeners on the same MBean,
|
||||
* which is why listenerMap is a Map<ObjectName, Set<IdAndFilter>> and
|
||||
* why we add the found notifications to a supplied List rather than
|
||||
* just returning a boolean.
|
||||
*/
|
||||
private final NotifForwarderBufferFilter bufferFilter = new NotifForwarderBufferFilter();
|
||||
|
||||
final class NotifForwarderBufferFilter implements NotificationBufferFilter {
|
||||
public void apply(List<TargetedNotification> targetedNotifs,
|
||||
ObjectName source, Notification notif) {
|
||||
// We proceed in two stages here, to avoid holding the listenerMap
|
||||
// lock while invoking the filters (which are user code).
|
||||
final IdAndFilter[] candidates;
|
||||
synchronized (listenerMap) {
|
||||
final Set<IdAndFilter> set = listenerMap.get(source);
|
||||
if (set == null) {
|
||||
logger.debug("bufferFilter", "no listeners for this name");
|
||||
return;
|
||||
}
|
||||
candidates = new IdAndFilter[set.size()];
|
||||
set.toArray(candidates);
|
||||
}
|
||||
// We don't synchronize on targetedNotifs, because it is a local
|
||||
// variable of our caller and no other thread can see it.
|
||||
for (IdAndFilter idaf : candidates) {
|
||||
final NotificationFilter nf = idaf.getFilter();
|
||||
if (nf == null || nf.isNotificationEnabled(notif)) {
|
||||
logger.debug("bufferFilter", "filter matches");
|
||||
final TargetedNotification tn =
|
||||
new TargetedNotification(notif, idaf.getId());
|
||||
if (allowNotificationEmission(source, tn))
|
||||
targetedNotifs.add(tn);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
public NotificationResult fetchNotifs(long startSequenceNumber,
|
||||
long timeout,
|
||||
int maxNotifications) {
|
||||
if (logger.traceOn()) {
|
||||
logger.trace("fetchNotifs", "Fetching notifications, the " +
|
||||
"startSequenceNumber is " + startSequenceNumber +
|
||||
", the timeout is " + timeout +
|
||||
", the maxNotifications is " + maxNotifications);
|
||||
}
|
||||
|
||||
NotificationResult nr;
|
||||
final long t = Math.min(connectionTimeout, timeout);
|
||||
try {
|
||||
nr = notifBuffer.fetchNotifications(bufferFilter,
|
||||
startSequenceNumber,
|
||||
t, maxNotifications);
|
||||
snoopOnUnregister(nr);
|
||||
} catch (InterruptedException ire) {
|
||||
nr = new NotificationResult(0L, 0L, new TargetedNotification[0]);
|
||||
}
|
||||
|
||||
if (logger.traceOn()) {
|
||||
logger.trace("fetchNotifs", "Forwarding the notifs: "+nr);
|
||||
}
|
||||
|
||||
return nr;
|
||||
}
|
||||
|
||||
// The standard RMI connector client will register a listener on the MBeanServerDelegate
|
||||
// in order to be told when MBeans are unregistered. We snoop on fetched notifications
|
||||
// so that we can know too, and remove the corresponding entry from the listenerMap.
|
||||
// See 6957378.
|
||||
private void snoopOnUnregister(NotificationResult nr) {
|
||||
List<IdAndFilter> copy = null;
|
||||
synchronized (listenerMap) {
|
||||
Set<IdAndFilter> delegateSet = listenerMap.get(MBeanServerDelegate.DELEGATE_NAME);
|
||||
if (delegateSet == null || delegateSet.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
copy = new ArrayList<>(delegateSet);
|
||||
}
|
||||
|
||||
for (TargetedNotification tn : nr.getTargetedNotifications()) {
|
||||
Integer id = tn.getListenerID();
|
||||
for (IdAndFilter idaf : copy) {
|
||||
if (idaf.id == id) {
|
||||
// This is a notification from the MBeanServerDelegate.
|
||||
Notification n = tn.getNotification();
|
||||
if (n instanceof MBeanServerNotification &&
|
||||
n.getType().equals(MBeanServerNotification.UNREGISTRATION_NOTIFICATION)) {
|
||||
MBeanServerNotification mbsn = (MBeanServerNotification) n;
|
||||
ObjectName gone = mbsn.getMBeanName();
|
||||
synchronized (listenerMap) {
|
||||
listenerMap.remove(gone);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void terminate() {
|
||||
if (logger.traceOn()) {
|
||||
logger.trace("terminate", "Be called.");
|
||||
}
|
||||
|
||||
synchronized(terminationLock) {
|
||||
if (terminated) {
|
||||
return;
|
||||
}
|
||||
|
||||
terminated = true;
|
||||
|
||||
synchronized(listenerMap) {
|
||||
listenerMap.clear();
|
||||
}
|
||||
}
|
||||
|
||||
if (logger.traceOn()) {
|
||||
logger.trace("terminate", "Terminated.");
|
||||
}
|
||||
}
|
||||
|
||||
//----------------
|
||||
// PRIVATE METHODS
|
||||
//----------------
|
||||
|
||||
private Subject getSubject() {
|
||||
return Subject.getSubject(AccessController.getContext());
|
||||
}
|
||||
|
||||
private void checkState() throws IOException {
|
||||
synchronized(terminationLock) {
|
||||
if (terminated) {
|
||||
throw new IOException("The connection has been terminated.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private Integer getListenerID() {
|
||||
synchronized(listenerCounterLock) {
|
||||
return listenerCounter++;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Explicitly check the MBeanPermission for
|
||||
* the current access control context.
|
||||
*/
|
||||
public final void checkMBeanPermission(
|
||||
final ObjectName name, final String actions)
|
||||
throws InstanceNotFoundException, SecurityException {
|
||||
checkMBeanPermission(mbeanServer,name,actions);
|
||||
}
|
||||
|
||||
static void checkMBeanPermission(
|
||||
final MBeanServer mbs, final ObjectName name, final String actions)
|
||||
throws InstanceNotFoundException, SecurityException {
|
||||
|
||||
SecurityManager sm = System.getSecurityManager();
|
||||
if (sm != null) {
|
||||
AccessControlContext acc = AccessController.getContext();
|
||||
ObjectInstance oi;
|
||||
try {
|
||||
oi = AccessController.doPrivileged(
|
||||
new PrivilegedExceptionAction<ObjectInstance>() {
|
||||
public ObjectInstance run()
|
||||
throws InstanceNotFoundException {
|
||||
return mbs.getObjectInstance(name);
|
||||
}
|
||||
});
|
||||
} catch (PrivilegedActionException e) {
|
||||
throw (InstanceNotFoundException) extractException(e);
|
||||
}
|
||||
String classname = oi.getClassName();
|
||||
MBeanPermission perm = new MBeanPermission(
|
||||
classname,
|
||||
null,
|
||||
name,
|
||||
actions);
|
||||
sm.checkPermission(perm, acc);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the caller has the right to get the following notifications.
|
||||
*/
|
||||
private boolean allowNotificationEmission(ObjectName name,
|
||||
TargetedNotification tn) {
|
||||
try {
|
||||
if (checkNotificationEmission) {
|
||||
checkMBeanPermission(name, "addNotificationListener");
|
||||
}
|
||||
if (notificationAccessController != null) {
|
||||
notificationAccessController.fetchNotification(
|
||||
connectionId, name, tn.getNotification(), getSubject());
|
||||
}
|
||||
return true;
|
||||
} catch (SecurityException e) {
|
||||
if (logger.debugOn()) {
|
||||
logger.debug("fetchNotifs", "Notification " +
|
||||
tn.getNotification() + " not forwarded: the " +
|
||||
"caller didn't have the required access rights");
|
||||
}
|
||||
return false;
|
||||
} catch (Exception e) {
|
||||
if (logger.debugOn()) {
|
||||
logger.debug("fetchNotifs", "Notification " +
|
||||
tn.getNotification() + " not forwarded: " +
|
||||
"got an unexpected exception: " + e);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Iterate until we extract the real exception
|
||||
* from a stack of PrivilegedActionExceptions.
|
||||
*/
|
||||
private static Exception extractException(Exception e) {
|
||||
while (e instanceof PrivilegedActionException) {
|
||||
e = ((PrivilegedActionException)e).getException();
|
||||
}
|
||||
return e;
|
||||
}
|
||||
|
||||
private static class IdAndFilter {
|
||||
private Integer id;
|
||||
private NotificationFilter filter;
|
||||
|
||||
IdAndFilter(Integer id, NotificationFilter filter) {
|
||||
this.id = id;
|
||||
this.filter = filter;
|
||||
}
|
||||
|
||||
Integer getId() {
|
||||
return this.id;
|
||||
}
|
||||
|
||||
NotificationFilter getFilter() {
|
||||
return this.filter;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return id.hashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
return ((o instanceof IdAndFilter) &&
|
||||
((IdAndFilter) o).getId().equals(getId()));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//------------------
|
||||
// PRIVATE VARIABLES
|
||||
//------------------
|
||||
|
||||
private MBeanServer mbeanServer;
|
||||
|
||||
private final String connectionId;
|
||||
|
||||
private final long connectionTimeout;
|
||||
|
||||
private static int listenerCounter = 0;
|
||||
private final static int[] listenerCounterLock = new int[0];
|
||||
|
||||
private NotificationBuffer notifBuffer;
|
||||
private final Map<ObjectName, Set<IdAndFilter>> listenerMap =
|
||||
new HashMap<ObjectName, Set<IdAndFilter>>();
|
||||
|
||||
private boolean terminated = false;
|
||||
private final int[] terminationLock = new int[0];
|
||||
|
||||
static final String broadcasterClass =
|
||||
NotificationBroadcaster.class.getName();
|
||||
|
||||
private final boolean checkNotificationEmission;
|
||||
|
||||
private final NotificationAccessController notificationAccessController;
|
||||
|
||||
private static final ClassLogger logger =
|
||||
new ClassLogger("javax.management.remote.misc", "ServerNotifForwarder");
|
||||
}
|
||||
34
jdkSrc/jdk8/com/sun/jmx/remote/internal/Unmarshal.java
Normal file
34
jdkSrc/jdk8/com/sun/jmx/remote/internal/Unmarshal.java
Normal file
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* 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.internal;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.rmi.MarshalledObject;
|
||||
|
||||
public interface Unmarshal {
|
||||
public Object get(MarshalledObject<?> mo)
|
||||
throws IOException, ClassNotFoundException;
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
* Copyright (c) 2003, 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 com.sun.jmx.remote.protocol.iiop;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.MalformedURLException;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.management.remote.JMXConnectorProvider;
|
||||
import javax.management.remote.JMXConnector;
|
||||
import javax.management.remote.JMXServiceURL;
|
||||
import javax.management.remote.rmi.RMIConnector;
|
||||
|
||||
public class ClientProvider implements JMXConnectorProvider {
|
||||
|
||||
public JMXConnector newJMXConnector(JMXServiceURL serviceURL,
|
||||
Map<String,?> environment)
|
||||
throws IOException {
|
||||
if (!serviceURL.getProtocol().equals("iiop")) {
|
||||
throw new MalformedURLException("Protocol not iiop: " +
|
||||
serviceURL.getProtocol());
|
||||
}
|
||||
return new RMIConnector(serviceURL, environment);
|
||||
}
|
||||
}
|
||||
157
jdkSrc/jdk8/com/sun/jmx/remote/protocol/iiop/IIOPProxyImpl.java
Normal file
157
jdkSrc/jdk8/com/sun/jmx/remote/protocol/iiop/IIOPProxyImpl.java
Normal file
@@ -0,0 +1,157 @@
|
||||
/*
|
||||
* Copyright (c) 2009,2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package com.sun.jmx.remote.protocol.iiop;
|
||||
|
||||
import org.omg.CORBA.ORB;
|
||||
import org.omg.CORBA.portable.Delegate;
|
||||
import javax.rmi.PortableRemoteObject;
|
||||
import javax.rmi.CORBA.Stub;
|
||||
|
||||
import java.util.Properties;
|
||||
import java.rmi.Remote;
|
||||
import java.rmi.RemoteException;
|
||||
import java.rmi.NoSuchObjectException;
|
||||
|
||||
import com.sun.jmx.remote.internal.IIOPProxy;
|
||||
import java.io.SerializablePermission;
|
||||
import java.security.AccessControlContext;
|
||||
import java.security.AccessController;
|
||||
import java.security.Permissions;
|
||||
import java.security.PrivilegedActionException;
|
||||
import java.security.PrivilegedExceptionAction;
|
||||
import java.security.ProtectionDomain;
|
||||
|
||||
/**
|
||||
* An implementation of IIOPProxy that simply delegates to the appropriate
|
||||
* RMI-IIOP and CORBA APIs.
|
||||
*/
|
||||
|
||||
public class IIOPProxyImpl implements IIOPProxy {
|
||||
// special ACC used to initialize the IIOP stub
|
||||
// the only allowed privilege is SerializablePermission("enableSubclassImplementation")
|
||||
private static final AccessControlContext STUB_ACC;
|
||||
|
||||
static {
|
||||
Permissions p = new Permissions();
|
||||
p.add(new SerializablePermission("enableSubclassImplementation"));
|
||||
STUB_ACC = new AccessControlContext(
|
||||
new ProtectionDomain[]{
|
||||
new ProtectionDomain(null, p)
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
public IIOPProxyImpl() { }
|
||||
|
||||
@Override
|
||||
public boolean isStub(Object obj) {
|
||||
return (obj instanceof Stub);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getDelegate(Object stub) {
|
||||
return ((Stub)stub)._get_delegate();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setDelegate(Object stub, Object delegate) {
|
||||
((Stub)stub)._set_delegate((Delegate)delegate);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getOrb(Object stub) {
|
||||
try {
|
||||
return ((Stub)stub)._orb();
|
||||
} catch (org.omg.CORBA.BAD_OPERATION x) {
|
||||
throw new UnsupportedOperationException(x);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void connect(Object stub, Object orb)
|
||||
throws RemoteException
|
||||
{
|
||||
((Stub)stub).connect((ORB)orb);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isOrb(Object obj) {
|
||||
return (obj instanceof ORB);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object createOrb(String[] args, Properties props) {
|
||||
return ORB.init(args, props);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object stringToObject(Object orb, String str) {
|
||||
return ((ORB)orb).string_to_object(str);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String objectToString(Object orb, Object obj) {
|
||||
return ((ORB)orb).object_to_string((org.omg.CORBA.Object)obj);
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T> T narrow(Object narrowFrom, Class<T> narrowTo) {
|
||||
return (T)PortableRemoteObject.narrow(narrowFrom, narrowTo);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void exportObject(Remote obj) throws RemoteException {
|
||||
PortableRemoteObject.exportObject(obj);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unexportObject(Remote obj) throws NoSuchObjectException {
|
||||
PortableRemoteObject.unexportObject(obj);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Remote toStub(final Remote obj) throws NoSuchObjectException {
|
||||
if (System.getSecurityManager() == null) {
|
||||
return PortableRemoteObject.toStub(obj);
|
||||
} else {
|
||||
try {
|
||||
return AccessController.doPrivileged(new PrivilegedExceptionAction<Remote>() {
|
||||
|
||||
@Override
|
||||
public Remote run() throws Exception {
|
||||
return PortableRemoteObject.toStub(obj);
|
||||
}
|
||||
}, STUB_ACC);
|
||||
} catch (PrivilegedActionException e) {
|
||||
if (e.getException() instanceof NoSuchObjectException) {
|
||||
throw (NoSuchObjectException)e.getException();
|
||||
}
|
||||
throw new RuntimeException("Unexpected exception type", e.getException());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,241 @@
|
||||
/*
|
||||
* 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.protocol.iiop;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.Serializable;
|
||||
import java.math.BigDecimal;
|
||||
|
||||
import org.omg.CORBA.Any;
|
||||
import org.omg.CORBA.Context;
|
||||
import org.omg.CORBA.NO_IMPLEMENT;
|
||||
import org.omg.CORBA.ORB;
|
||||
import org.omg.CORBA.TypeCode;
|
||||
import org.omg.CORBA.portable.BoxedValueHelper;
|
||||
|
||||
@SuppressWarnings({"deprecation", "rawtypes"})
|
||||
public class ProxyInputStream extends org.omg.CORBA_2_3.portable.InputStream {
|
||||
public ProxyInputStream(org.omg.CORBA.portable.InputStream in) {
|
||||
this.in = in;
|
||||
}
|
||||
|
||||
public boolean read_boolean() {
|
||||
return in.read_boolean();
|
||||
}
|
||||
|
||||
public char read_char() {
|
||||
return in.read_char();
|
||||
}
|
||||
|
||||
public char read_wchar() {
|
||||
return in.read_wchar();
|
||||
}
|
||||
|
||||
public byte read_octet() {
|
||||
return in.read_octet();
|
||||
}
|
||||
|
||||
public short read_short() {
|
||||
return in.read_short();
|
||||
}
|
||||
|
||||
public short read_ushort() {
|
||||
return in.read_ushort();
|
||||
}
|
||||
|
||||
public int read_long() {
|
||||
return in.read_long();
|
||||
}
|
||||
|
||||
public int read_ulong() {
|
||||
return in.read_ulong();
|
||||
}
|
||||
|
||||
public long read_longlong() {
|
||||
return in.read_longlong();
|
||||
}
|
||||
|
||||
public long read_ulonglong() {
|
||||
return in.read_ulonglong();
|
||||
}
|
||||
|
||||
public float read_float() {
|
||||
return in.read_float();
|
||||
}
|
||||
|
||||
public double read_double() {
|
||||
return in.read_double();
|
||||
}
|
||||
|
||||
public String read_string() {
|
||||
return in.read_string();
|
||||
}
|
||||
|
||||
public String read_wstring() {
|
||||
return in.read_wstring();
|
||||
}
|
||||
|
||||
public void read_boolean_array(boolean[] value, int offset, int length) {
|
||||
in.read_boolean_array(value, offset, length);
|
||||
}
|
||||
|
||||
public void read_char_array(char[] value, int offset, int length) {
|
||||
in.read_char_array(value, offset, length);
|
||||
}
|
||||
|
||||
public void read_wchar_array(char[] value, int offset, int length) {
|
||||
in.read_wchar_array(value, offset, length);
|
||||
}
|
||||
|
||||
public void read_octet_array(byte[] value, int offset, int length) {
|
||||
in.read_octet_array(value, offset, length);
|
||||
}
|
||||
|
||||
public void read_short_array(short[] value, int offset, int length) {
|
||||
in.read_short_array(value, offset, length);
|
||||
}
|
||||
|
||||
public void read_ushort_array(short[] value, int offset, int length) {
|
||||
in.read_ushort_array(value, offset, length);
|
||||
}
|
||||
|
||||
public void read_long_array(int[] value, int offset, int length) {
|
||||
in.read_long_array(value, offset, length);
|
||||
}
|
||||
|
||||
public void read_ulong_array(int[] value, int offset, int length) {
|
||||
in.read_ulong_array(value, offset, length);
|
||||
}
|
||||
|
||||
public void read_longlong_array(long[] value, int offset, int length) {
|
||||
in.read_longlong_array(value, offset, length);
|
||||
}
|
||||
|
||||
public void read_ulonglong_array(long[] value, int offset, int length) {
|
||||
in.read_ulonglong_array(value, offset, length);
|
||||
}
|
||||
|
||||
public void read_float_array(float[] value, int offset, int length) {
|
||||
in.read_float_array(value, offset, length);
|
||||
}
|
||||
|
||||
public void read_double_array(double[] value, int offset, int length) {
|
||||
in.read_double_array(value, offset, length);
|
||||
}
|
||||
|
||||
public org.omg.CORBA.Object read_Object() {
|
||||
return in.read_Object();
|
||||
}
|
||||
|
||||
public TypeCode read_TypeCode() {
|
||||
return in.read_TypeCode();
|
||||
}
|
||||
|
||||
public Any read_any() {
|
||||
return in.read_any();
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated
|
||||
*/
|
||||
@Override
|
||||
@Deprecated
|
||||
public org.omg.CORBA.Principal read_Principal() {
|
||||
return in.read_Principal();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int read() throws IOException {
|
||||
return in.read();
|
||||
}
|
||||
|
||||
@Override
|
||||
public BigDecimal read_fixed() {
|
||||
return in.read_fixed();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Context read_Context() {
|
||||
return in.read_Context();
|
||||
}
|
||||
|
||||
@Override
|
||||
public org.omg.CORBA.Object read_Object(java.lang.Class clz) {
|
||||
return in.read_Object(clz);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ORB orb() {
|
||||
return in.orb();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Serializable read_value() {
|
||||
return narrow().read_value();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Serializable read_value(Class clz) {
|
||||
return narrow().read_value(clz);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Serializable read_value(BoxedValueHelper factory) {
|
||||
return narrow().read_value(factory);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Serializable read_value(String rep_id) {
|
||||
return narrow().read_value(rep_id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Serializable read_value(Serializable value) {
|
||||
return narrow().read_value(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object read_abstract_interface() {
|
||||
return narrow().read_abstract_interface();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object read_abstract_interface(Class clz) {
|
||||
return narrow().read_abstract_interface(clz);
|
||||
}
|
||||
|
||||
protected org.omg.CORBA_2_3.portable.InputStream narrow() {
|
||||
if (in instanceof org.omg.CORBA_2_3.portable.InputStream)
|
||||
return (org.omg.CORBA_2_3.portable.InputStream) in;
|
||||
throw new NO_IMPLEMENT();
|
||||
}
|
||||
|
||||
public org.omg.CORBA.portable.InputStream getProxiedInputStream() {
|
||||
return in;
|
||||
}
|
||||
|
||||
protected final org.omg.CORBA.portable.InputStream in;
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
* Copyright (c) 2003, 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 com.sun.jmx.remote.protocol.iiop;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.MalformedURLException;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.management.MBeanServer;
|
||||
import javax.management.remote.JMXConnectorServer;
|
||||
import javax.management.remote.JMXConnectorServerProvider;
|
||||
import javax.management.remote.JMXServiceURL;
|
||||
import javax.management.remote.rmi.RMIConnectorServer;
|
||||
|
||||
public class ServerProvider implements JMXConnectorServerProvider {
|
||||
|
||||
public JMXConnectorServer newJMXConnectorServer(JMXServiceURL serviceURL,
|
||||
Map<String,?> environment,
|
||||
MBeanServer mbeanServer)
|
||||
throws IOException {
|
||||
if (!serviceURL.getProtocol().equals("iiop")) {
|
||||
throw new MalformedURLException("Protocol not iiop: " +
|
||||
serviceURL.getProtocol());
|
||||
}
|
||||
return new RMIConnectorServer(serviceURL, environment, mbeanServer);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
* Copyright (c) 2002, 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 com.sun.jmx.remote.protocol.rmi;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.MalformedURLException;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.management.remote.JMXConnectorProvider;
|
||||
import javax.management.remote.JMXConnector;
|
||||
import javax.management.remote.JMXServiceURL;
|
||||
import javax.management.remote.rmi.RMIConnector;
|
||||
|
||||
public class ClientProvider implements JMXConnectorProvider {
|
||||
|
||||
public JMXConnector newJMXConnector(JMXServiceURL serviceURL,
|
||||
Map<String,?> environment)
|
||||
throws IOException {
|
||||
if (!serviceURL.getProtocol().equals("rmi")) {
|
||||
throw new MalformedURLException("Protocol not rmi: " +
|
||||
serviceURL.getProtocol());
|
||||
}
|
||||
return new RMIConnector(serviceURL, environment);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
* Copyright (c) 2003, 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 com.sun.jmx.remote.protocol.rmi;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.MalformedURLException;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.management.MBeanServer;
|
||||
import javax.management.remote.JMXConnectorServer;
|
||||
import javax.management.remote.JMXConnectorServerProvider;
|
||||
import javax.management.remote.JMXServiceURL;
|
||||
import javax.management.remote.rmi.RMIConnectorServer;
|
||||
|
||||
public class ServerProvider implements JMXConnectorServerProvider {
|
||||
|
||||
public JMXConnectorServer newJMXConnectorServer(JMXServiceURL serviceURL,
|
||||
Map<String,?> environment,
|
||||
MBeanServer mbeanServer)
|
||||
throws IOException {
|
||||
if (!serviceURL.getProtocol().equals("rmi")) {
|
||||
throw new MalformedURLException("Protocol not rmi: " +
|
||||
serviceURL.getProtocol());
|
||||
}
|
||||
return new RMIConnectorServer(serviceURL, environment, mbeanServer);
|
||||
}
|
||||
|
||||
}
|
||||
570
jdkSrc/jdk8/com/sun/jmx/remote/security/FileLoginModule.java
Normal file
570
jdkSrc/jdk8/com/sun/jmx/remote/security/FileLoginModule.java
Normal file
@@ -0,0 +1,570 @@
|
||||
/*
|
||||
* Copyright (c) 2004, 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.security;
|
||||
|
||||
import com.sun.jmx.mbeanserver.GetPropertyAction;
|
||||
import com.sun.jmx.mbeanserver.Util;
|
||||
import java.io.BufferedInputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FilePermission;
|
||||
import java.io.IOException;
|
||||
import java.security.AccessControlException;
|
||||
import java.security.AccessController;
|
||||
import java.util.Arrays;
|
||||
import java.util.Hashtable;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
|
||||
import javax.security.auth.*;
|
||||
import javax.security.auth.callback.*;
|
||||
import javax.security.auth.login.*;
|
||||
import javax.security.auth.spi.*;
|
||||
import javax.management.remote.JMXPrincipal;
|
||||
|
||||
import com.sun.jmx.remote.util.ClassLogger;
|
||||
import com.sun.jmx.remote.util.EnvHelp;
|
||||
import sun.management.jmxremote.ConnectorBootstrap;
|
||||
|
||||
/**
|
||||
* This {@link LoginModule} performs file-based authentication.
|
||||
*
|
||||
* <p> A supplied username and password is verified against the
|
||||
* corresponding user credentials stored in a designated password file.
|
||||
* If successful then a new {@link JMXPrincipal} is created with the
|
||||
* user's name and it is associated with the current {@link Subject}.
|
||||
* Such principals may be identified and granted management privileges in
|
||||
* the access control file for JMX remote management or in a Java security
|
||||
* policy.
|
||||
*
|
||||
* <p> The password file comprises a list of key-value pairs as specified in
|
||||
* {@link Properties}. The key represents a user's name and the value is its
|
||||
* associated cleartext password. By default, the following password file is
|
||||
* used:
|
||||
* <pre>
|
||||
* ${java.home}/lib/management/jmxremote.password
|
||||
* </pre>
|
||||
* A different password file can be specified via the <code>passwordFile</code>
|
||||
* configuration option.
|
||||
*
|
||||
* <p> This module recognizes the following <code>Configuration</code> options:
|
||||
* <dl>
|
||||
* <dt> <code>passwordFile</code> </dt>
|
||||
* <dd> the path to an alternative password file. It is used instead of
|
||||
* the default password file.</dd>
|
||||
*
|
||||
* <dt> <code>useFirstPass</code> </dt>
|
||||
* <dd> if <code>true</code>, this module retrieves the username and password
|
||||
* from the module's shared state, using "javax.security.auth.login.name"
|
||||
* and "javax.security.auth.login.password" as the respective keys. The
|
||||
* retrieved values are used for authentication. If authentication fails,
|
||||
* no attempt for a retry is made, and the failure is reported back to
|
||||
* the calling application.</dd>
|
||||
*
|
||||
* <dt> <code>tryFirstPass</code> </dt>
|
||||
* <dd> if <code>true</code>, this module retrieves the username and password
|
||||
* from the module's shared state, using "javax.security.auth.login.name"
|
||||
* and "javax.security.auth.login.password" as the respective keys. The
|
||||
* retrieved values are used for authentication. If authentication fails,
|
||||
* the module uses the CallbackHandler to retrieve a new username and
|
||||
* password, and another attempt to authenticate is made. If the
|
||||
* authentication fails, the failure is reported back to the calling
|
||||
* application.</dd>
|
||||
*
|
||||
* <dt> <code>storePass</code> </dt>
|
||||
* <dd> if <code>true</code>, this module stores the username and password
|
||||
* obtained from the CallbackHandler in the module's shared state, using
|
||||
* "javax.security.auth.login.name" and
|
||||
* "javax.security.auth.login.password" as the respective keys. This is
|
||||
* not performed if existing values already exist for the username and
|
||||
* password in the shared state, or if authentication fails.</dd>
|
||||
*
|
||||
* <dt> <code>clearPass</code> </dt>
|
||||
* <dd> if <code>true</code>, this module clears the username and password
|
||||
* stored in the module's shared state after both phases of authentication
|
||||
* (login and commit) have completed.</dd>
|
||||
* </dl>
|
||||
*/
|
||||
public class FileLoginModule implements LoginModule {
|
||||
|
||||
// Location of the default password file
|
||||
private static final String DEFAULT_PASSWORD_FILE_NAME =
|
||||
AccessController.doPrivileged(new GetPropertyAction("java.home")) +
|
||||
File.separatorChar + "lib" +
|
||||
File.separatorChar + "management" + File.separatorChar +
|
||||
ConnectorBootstrap.DefaultValues.PASSWORD_FILE_NAME;
|
||||
|
||||
// Key to retrieve the stored username
|
||||
private static final String USERNAME_KEY =
|
||||
"javax.security.auth.login.name";
|
||||
|
||||
// Key to retrieve the stored password
|
||||
private static final String PASSWORD_KEY =
|
||||
"javax.security.auth.login.password";
|
||||
|
||||
// Log messages
|
||||
private static final ClassLogger logger =
|
||||
new ClassLogger("javax.management.remote.misc", "FileLoginModule");
|
||||
|
||||
// Configurable options
|
||||
private boolean useFirstPass = false;
|
||||
private boolean tryFirstPass = false;
|
||||
private boolean storePass = false;
|
||||
private boolean clearPass = false;
|
||||
|
||||
// Authentication status
|
||||
private boolean succeeded = false;
|
||||
private boolean commitSucceeded = false;
|
||||
|
||||
// Supplied username and password
|
||||
private String username;
|
||||
private char[] password;
|
||||
private JMXPrincipal user;
|
||||
|
||||
// Initial state
|
||||
private Subject subject;
|
||||
private CallbackHandler callbackHandler;
|
||||
private Map<String, Object> sharedState;
|
||||
private Map<String, ?> options;
|
||||
private String passwordFile;
|
||||
private String passwordFileDisplayName;
|
||||
private boolean userSuppliedPasswordFile;
|
||||
private boolean hasJavaHomePermission;
|
||||
private Properties userCredentials;
|
||||
|
||||
/**
|
||||
* Initialize this <code>LoginModule</code>.
|
||||
*
|
||||
* @param subject the <code>Subject</code> to be authenticated.
|
||||
* @param callbackHandler a <code>CallbackHandler</code> to acquire the
|
||||
* user's name and password.
|
||||
* @param sharedState shared <code>LoginModule</code> state.
|
||||
* @param options options specified in the login
|
||||
* <code>Configuration</code> for this particular
|
||||
* <code>LoginModule</code>.
|
||||
*/
|
||||
public void initialize(Subject subject, CallbackHandler callbackHandler,
|
||||
Map<String,?> sharedState,
|
||||
Map<String,?> options)
|
||||
{
|
||||
|
||||
this.subject = subject;
|
||||
this.callbackHandler = callbackHandler;
|
||||
this.sharedState = Util.cast(sharedState);
|
||||
this.options = options;
|
||||
|
||||
// initialize any configured options
|
||||
tryFirstPass =
|
||||
"true".equalsIgnoreCase((String)options.get("tryFirstPass"));
|
||||
useFirstPass =
|
||||
"true".equalsIgnoreCase((String)options.get("useFirstPass"));
|
||||
storePass =
|
||||
"true".equalsIgnoreCase((String)options.get("storePass"));
|
||||
clearPass =
|
||||
"true".equalsIgnoreCase((String)options.get("clearPass"));
|
||||
|
||||
passwordFile = (String)options.get("passwordFile");
|
||||
passwordFileDisplayName = passwordFile;
|
||||
userSuppliedPasswordFile = true;
|
||||
|
||||
// set the location of the password file
|
||||
if (passwordFile == null) {
|
||||
passwordFile = DEFAULT_PASSWORD_FILE_NAME;
|
||||
userSuppliedPasswordFile = false;
|
||||
try {
|
||||
System.getProperty("java.home");
|
||||
hasJavaHomePermission = true;
|
||||
passwordFileDisplayName = passwordFile;
|
||||
} catch (SecurityException e) {
|
||||
hasJavaHomePermission = false;
|
||||
passwordFileDisplayName =
|
||||
ConnectorBootstrap.DefaultValues.PASSWORD_FILE_NAME;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Begin user authentication (Authentication Phase 1).
|
||||
*
|
||||
* <p> Acquire the user's name and password and verify them against
|
||||
* the corresponding credentials from the password file.
|
||||
*
|
||||
* @return true always, since this <code>LoginModule</code>
|
||||
* should not be ignored.
|
||||
* @exception FailedLoginException if the authentication fails.
|
||||
* @exception LoginException if this <code>LoginModule</code>
|
||||
* is unable to perform the authentication.
|
||||
*/
|
||||
public boolean login() throws LoginException {
|
||||
|
||||
try {
|
||||
loadPasswordFile();
|
||||
} catch (IOException ioe) {
|
||||
LoginException le = new LoginException(
|
||||
"Error: unable to load the password file: " +
|
||||
passwordFileDisplayName);
|
||||
throw EnvHelp.initCause(le, ioe);
|
||||
}
|
||||
|
||||
if (userCredentials == null) {
|
||||
throw new LoginException
|
||||
("Error: unable to locate the users' credentials.");
|
||||
}
|
||||
|
||||
if (logger.debugOn()) {
|
||||
logger.debug("login",
|
||||
"Using password file: " + passwordFileDisplayName);
|
||||
}
|
||||
|
||||
// attempt the authentication
|
||||
if (tryFirstPass) {
|
||||
|
||||
try {
|
||||
// attempt the authentication by getting the
|
||||
// username and password from shared state
|
||||
attemptAuthentication(true);
|
||||
|
||||
// authentication succeeded
|
||||
succeeded = true;
|
||||
if (logger.debugOn()) {
|
||||
logger.debug("login",
|
||||
"Authentication using cached password has succeeded");
|
||||
}
|
||||
return true;
|
||||
|
||||
} catch (LoginException le) {
|
||||
// authentication failed -- try again below by prompting
|
||||
cleanState();
|
||||
logger.debug("login",
|
||||
"Authentication using cached password has failed");
|
||||
}
|
||||
|
||||
} else if (useFirstPass) {
|
||||
|
||||
try {
|
||||
// attempt the authentication by getting the
|
||||
// username and password from shared state
|
||||
attemptAuthentication(true);
|
||||
|
||||
// authentication succeeded
|
||||
succeeded = true;
|
||||
if (logger.debugOn()) {
|
||||
logger.debug("login",
|
||||
"Authentication using cached password has succeeded");
|
||||
}
|
||||
return true;
|
||||
|
||||
} catch (LoginException le) {
|
||||
// authentication failed
|
||||
cleanState();
|
||||
logger.debug("login",
|
||||
"Authentication using cached password has failed");
|
||||
|
||||
throw le;
|
||||
}
|
||||
}
|
||||
|
||||
if (logger.debugOn()) {
|
||||
logger.debug("login", "Acquiring password");
|
||||
}
|
||||
|
||||
// attempt the authentication using the supplied username and password
|
||||
try {
|
||||
attemptAuthentication(false);
|
||||
|
||||
// authentication succeeded
|
||||
succeeded = true;
|
||||
if (logger.debugOn()) {
|
||||
logger.debug("login", "Authentication has succeeded");
|
||||
}
|
||||
return true;
|
||||
|
||||
} catch (LoginException le) {
|
||||
cleanState();
|
||||
logger.debug("login", "Authentication has failed");
|
||||
|
||||
throw le;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Complete user authentication (Authentication Phase 2).
|
||||
*
|
||||
* <p> This method is called if the LoginContext's
|
||||
* overall authentication has succeeded
|
||||
* (all the relevant REQUIRED, REQUISITE, SUFFICIENT and OPTIONAL
|
||||
* LoginModules have succeeded).
|
||||
*
|
||||
* <p> If this LoginModule's own authentication attempt
|
||||
* succeeded (checked by retrieving the private state saved by the
|
||||
* <code>login</code> method), then this method associates a
|
||||
* <code>JMXPrincipal</code> with the <code>Subject</code> located in the
|
||||
* <code>LoginModule</code>. If this LoginModule's own
|
||||
* authentication attempted failed, then this method removes
|
||||
* any state that was originally saved.
|
||||
*
|
||||
* @exception LoginException if the commit fails
|
||||
* @return true if this LoginModule's own login and commit
|
||||
* attempts succeeded, or false otherwise.
|
||||
*/
|
||||
public boolean commit() throws LoginException {
|
||||
|
||||
if (succeeded == false) {
|
||||
return false;
|
||||
} else {
|
||||
if (subject.isReadOnly()) {
|
||||
cleanState();
|
||||
throw new LoginException("Subject is read-only");
|
||||
}
|
||||
// add Principals to the Subject
|
||||
if (!subject.getPrincipals().contains(user)) {
|
||||
subject.getPrincipals().add(user);
|
||||
}
|
||||
|
||||
if (logger.debugOn()) {
|
||||
logger.debug("commit",
|
||||
"Authentication has completed successfully");
|
||||
}
|
||||
}
|
||||
// in any case, clean out state
|
||||
cleanState();
|
||||
commitSucceeded = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Abort user authentication (Authentication Phase 2).
|
||||
*
|
||||
* <p> This method is called if the LoginContext's overall authentication
|
||||
* failed (the relevant REQUIRED, REQUISITE, SUFFICIENT and OPTIONAL
|
||||
* LoginModules did not succeed).
|
||||
*
|
||||
* <p> If this LoginModule's own authentication attempt
|
||||
* succeeded (checked by retrieving the private state saved by the
|
||||
* <code>login</code> and <code>commit</code> methods),
|
||||
* then this method cleans up any state that was originally saved.
|
||||
*
|
||||
* @exception LoginException if the abort fails.
|
||||
* @return false if this LoginModule's own login and/or commit attempts
|
||||
* failed, and true otherwise.
|
||||
*/
|
||||
public boolean abort() throws LoginException {
|
||||
|
||||
if (logger.debugOn()) {
|
||||
logger.debug("abort",
|
||||
"Authentication has not completed successfully");
|
||||
}
|
||||
|
||||
if (succeeded == false) {
|
||||
return false;
|
||||
} else if (succeeded == true && commitSucceeded == false) {
|
||||
|
||||
// Clean out state
|
||||
succeeded = false;
|
||||
cleanState();
|
||||
user = null;
|
||||
} else {
|
||||
// overall authentication succeeded and commit succeeded,
|
||||
// but someone else's commit failed
|
||||
logout();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Logout a user.
|
||||
*
|
||||
* <p> This method removes the Principals
|
||||
* that were added by the <code>commit</code> method.
|
||||
*
|
||||
* @exception LoginException if the logout fails.
|
||||
* @return true in all cases since this <code>LoginModule</code>
|
||||
* should not be ignored.
|
||||
*/
|
||||
public boolean logout() throws LoginException {
|
||||
if (subject.isReadOnly()) {
|
||||
cleanState();
|
||||
throw new LoginException ("Subject is read-only");
|
||||
}
|
||||
subject.getPrincipals().remove(user);
|
||||
|
||||
// clean out state
|
||||
cleanState();
|
||||
succeeded = false;
|
||||
commitSucceeded = false;
|
||||
user = null;
|
||||
|
||||
if (logger.debugOn()) {
|
||||
logger.debug("logout", "Subject is being logged out");
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempt authentication
|
||||
*
|
||||
* @param usePasswdFromSharedState a flag to tell this method whether
|
||||
* to retrieve the password from the sharedState.
|
||||
*/
|
||||
@SuppressWarnings("unchecked") // sharedState used as Map<String,Object>
|
||||
private void attemptAuthentication(boolean usePasswdFromSharedState)
|
||||
throws LoginException {
|
||||
|
||||
// get the username and password
|
||||
getUsernamePassword(usePasswdFromSharedState);
|
||||
|
||||
String localPassword;
|
||||
|
||||
// userCredentials is initialized in login()
|
||||
if (((localPassword = userCredentials.getProperty(username)) == null) ||
|
||||
(! localPassword.equals(new String(password)))) {
|
||||
|
||||
// username not found or passwords do not match
|
||||
if (logger.debugOn()) {
|
||||
logger.debug("login", "Invalid username or password");
|
||||
}
|
||||
throw new FailedLoginException("Invalid username or password");
|
||||
}
|
||||
|
||||
// Save the username and password in the shared state
|
||||
// only if authentication succeeded
|
||||
if (storePass &&
|
||||
!sharedState.containsKey(USERNAME_KEY) &&
|
||||
!sharedState.containsKey(PASSWORD_KEY)) {
|
||||
sharedState.put(USERNAME_KEY, username);
|
||||
sharedState.put(PASSWORD_KEY, password);
|
||||
}
|
||||
|
||||
// Create a new user principal
|
||||
user = new JMXPrincipal(username);
|
||||
|
||||
if (logger.debugOn()) {
|
||||
logger.debug("login",
|
||||
"User '" + username + "' successfully validated");
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Read the password file.
|
||||
*/
|
||||
private void loadPasswordFile() throws IOException {
|
||||
FileInputStream fis;
|
||||
try {
|
||||
fis = new FileInputStream(passwordFile);
|
||||
} catch (SecurityException e) {
|
||||
if (userSuppliedPasswordFile || hasJavaHomePermission) {
|
||||
throw e;
|
||||
} else {
|
||||
final FilePermission fp =
|
||||
new FilePermission(passwordFileDisplayName, "read");
|
||||
AccessControlException ace = new AccessControlException(
|
||||
"access denied " + fp.toString());
|
||||
ace.setStackTrace(e.getStackTrace());
|
||||
throw ace;
|
||||
}
|
||||
}
|
||||
try {
|
||||
final BufferedInputStream bis = new BufferedInputStream(fis);
|
||||
try {
|
||||
userCredentials = new Properties();
|
||||
userCredentials.load(bis);
|
||||
} finally {
|
||||
bis.close();
|
||||
}
|
||||
} finally {
|
||||
fis.close();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the username and password.
|
||||
* This method does not return any value.
|
||||
* Instead, it sets global name and password variables.
|
||||
*
|
||||
* <p> Also note that this method will set the username and password
|
||||
* values in the shared state in case subsequent LoginModules
|
||||
* want to use them via use/tryFirstPass.
|
||||
*
|
||||
* @param usePasswdFromSharedState boolean that tells this method whether
|
||||
* to retrieve the password from the sharedState.
|
||||
*/
|
||||
private void getUsernamePassword(boolean usePasswdFromSharedState)
|
||||
throws LoginException {
|
||||
|
||||
if (usePasswdFromSharedState) {
|
||||
// use the password saved by the first module in the stack
|
||||
username = (String)sharedState.get(USERNAME_KEY);
|
||||
password = (char[])sharedState.get(PASSWORD_KEY);
|
||||
return;
|
||||
}
|
||||
|
||||
// acquire username and password
|
||||
if (callbackHandler == null)
|
||||
throw new LoginException("Error: no CallbackHandler available " +
|
||||
"to garner authentication information from the user");
|
||||
|
||||
Callback[] callbacks = new Callback[2];
|
||||
callbacks[0] = new NameCallback("username");
|
||||
callbacks[1] = new PasswordCallback("password", false);
|
||||
|
||||
try {
|
||||
callbackHandler.handle(callbacks);
|
||||
username = ((NameCallback)callbacks[0]).getName();
|
||||
char[] tmpPassword = ((PasswordCallback)callbacks[1]).getPassword();
|
||||
password = new char[tmpPassword.length];
|
||||
System.arraycopy(tmpPassword, 0,
|
||||
password, 0, tmpPassword.length);
|
||||
((PasswordCallback)callbacks[1]).clearPassword();
|
||||
|
||||
} catch (IOException ioe) {
|
||||
LoginException le = new LoginException(ioe.toString());
|
||||
throw EnvHelp.initCause(le, ioe);
|
||||
} catch (UnsupportedCallbackException uce) {
|
||||
LoginException le = new LoginException(
|
||||
"Error: " + uce.getCallback().toString() +
|
||||
" not available to garner authentication " +
|
||||
"information from the user");
|
||||
throw EnvHelp.initCause(le, uce);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Clean out state because of a failed authentication attempt
|
||||
*/
|
||||
private void cleanState() {
|
||||
username = null;
|
||||
if (password != null) {
|
||||
Arrays.fill(password, ' ');
|
||||
password = null;
|
||||
}
|
||||
|
||||
if (clearPass) {
|
||||
sharedState.remove(USERNAME_KEY);
|
||||
sharedState.remove(PASSWORD_KEY);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,346 @@
|
||||
/*
|
||||
* Copyright (c) 2004, 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.security;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.security.AccessController;
|
||||
import java.security.Principal;
|
||||
import java.security.PrivilegedAction;
|
||||
import java.security.PrivilegedActionException;
|
||||
import java.security.PrivilegedExceptionAction;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
import javax.management.remote.JMXPrincipal;
|
||||
import javax.management.remote.JMXAuthenticator;
|
||||
import javax.security.auth.AuthPermission;
|
||||
import javax.security.auth.Subject;
|
||||
import javax.security.auth.callback.*;
|
||||
import javax.security.auth.login.AppConfigurationEntry;
|
||||
import javax.security.auth.login.Configuration;
|
||||
import javax.security.auth.login.LoginContext;
|
||||
import javax.security.auth.login.LoginException;
|
||||
import javax.security.auth.spi.LoginModule;
|
||||
import com.sun.jmx.remote.util.ClassLogger;
|
||||
import com.sun.jmx.remote.util.EnvHelp;
|
||||
|
||||
/**
|
||||
* <p>This class represents a
|
||||
* <a href="{@docRoot}/../guide/security/jaas/JAASRefGuide.html">JAAS</a>
|
||||
* based implementation of the {@link JMXAuthenticator} interface.</p>
|
||||
*
|
||||
* <p>Authentication is performed by passing the supplied user's credentials
|
||||
* to one or more authentication mechanisms ({@link LoginModule}) for
|
||||
* verification. An authentication mechanism acquires the user's credentials
|
||||
* by calling {@link NameCallback} and/or {@link PasswordCallback}.
|
||||
* If authentication is successful then an authenticated {@link Subject}
|
||||
* filled in with a {@link Principal} is returned. Authorization checks
|
||||
* will then be performed based on this <code>Subject</code>.</p>
|
||||
*
|
||||
* <p>By default, a single file-based authentication mechanism
|
||||
* {@link FileLoginModule} is configured (<code>FileLoginConfig</code>).</p>
|
||||
*
|
||||
* <p>To override the default configuration use the
|
||||
* <code>com.sun.management.jmxremote.login.config</code> management property
|
||||
* described in the JRE/lib/management/management.properties file.
|
||||
* Set this property to the name of a JAAS configuration entry and ensure that
|
||||
* the entry is loaded by the installed {@link Configuration}. In addition,
|
||||
* ensure that the authentication mechanisms specified in the entry acquire
|
||||
* the user's credentials by calling {@link NameCallback} and
|
||||
* {@link PasswordCallback} and that they return a {@link Subject} filled-in
|
||||
* with a {@link Principal}, for those users that are successfully
|
||||
* authenticated.</p>
|
||||
*/
|
||||
public final class JMXPluggableAuthenticator implements JMXAuthenticator {
|
||||
|
||||
/**
|
||||
* Creates an instance of <code>JMXPluggableAuthenticator</code>
|
||||
* and initializes it with a {@link LoginContext}.
|
||||
*
|
||||
* @param env the environment containing configuration properties for the
|
||||
* authenticator. Can be null, which is equivalent to an empty
|
||||
* Map.
|
||||
* @exception SecurityException if the authentication mechanism cannot be
|
||||
* initialized.
|
||||
*/
|
||||
public JMXPluggableAuthenticator(Map<?, ?> env) {
|
||||
|
||||
String loginConfigName = null;
|
||||
String passwordFile = null;
|
||||
|
||||
if (env != null) {
|
||||
loginConfigName = (String) env.get(LOGIN_CONFIG_PROP);
|
||||
passwordFile = (String) env.get(PASSWORD_FILE_PROP);
|
||||
}
|
||||
|
||||
try {
|
||||
|
||||
if (loginConfigName != null) {
|
||||
// use the supplied JAAS login configuration
|
||||
loginContext =
|
||||
new LoginContext(loginConfigName, new JMXCallbackHandler());
|
||||
|
||||
} else {
|
||||
// use the default JAAS login configuration (file-based)
|
||||
SecurityManager sm = System.getSecurityManager();
|
||||
if (sm != null) {
|
||||
sm.checkPermission(
|
||||
new AuthPermission("createLoginContext." +
|
||||
LOGIN_CONFIG_NAME));
|
||||
}
|
||||
|
||||
final String pf = passwordFile;
|
||||
try {
|
||||
loginContext = AccessController.doPrivileged(
|
||||
new PrivilegedExceptionAction<LoginContext>() {
|
||||
public LoginContext run() throws LoginException {
|
||||
return new LoginContext(
|
||||
LOGIN_CONFIG_NAME,
|
||||
null,
|
||||
new JMXCallbackHandler(),
|
||||
new FileLoginConfig(pf));
|
||||
}
|
||||
});
|
||||
} catch (PrivilegedActionException pae) {
|
||||
throw (LoginException) pae.getException();
|
||||
}
|
||||
}
|
||||
|
||||
} catch (LoginException le) {
|
||||
authenticationFailure("authenticate", le);
|
||||
|
||||
} catch (SecurityException se) {
|
||||
authenticationFailure("authenticate", se);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Authenticate the <code>MBeanServerConnection</code> client
|
||||
* with the given client credentials.
|
||||
*
|
||||
* @param credentials the user-defined credentials to be passed in
|
||||
* to the server in order to authenticate the user before creating
|
||||
* the <code>MBeanServerConnection</code>. This parameter must
|
||||
* be a two-element <code>String[]</code> containing the client's
|
||||
* username and password in that order.
|
||||
*
|
||||
* @return the authenticated subject containing a
|
||||
* <code>JMXPrincipal(username)</code>.
|
||||
*
|
||||
* @exception SecurityException if the server cannot authenticate the user
|
||||
* with the provided credentials.
|
||||
*/
|
||||
public Subject authenticate(Object credentials) {
|
||||
// Verify that credentials is of type String[].
|
||||
//
|
||||
if (!(credentials instanceof String[])) {
|
||||
// Special case for null so we get a more informative message
|
||||
if (credentials == null)
|
||||
authenticationFailure("authenticate", "Credentials required");
|
||||
|
||||
final String message =
|
||||
"Credentials should be String[] instead of " +
|
||||
credentials.getClass().getName();
|
||||
authenticationFailure("authenticate", message);
|
||||
}
|
||||
// Verify that the array contains two elements.
|
||||
//
|
||||
final String[] aCredentials = (String[]) credentials;
|
||||
if (aCredentials.length != 2) {
|
||||
final String message =
|
||||
"Credentials should have 2 elements not " +
|
||||
aCredentials.length;
|
||||
authenticationFailure("authenticate", message);
|
||||
}
|
||||
// Verify that username exists and the associated
|
||||
// password matches the one supplied by the client.
|
||||
//
|
||||
username = aCredentials[0];
|
||||
password = aCredentials[1];
|
||||
if (username == null || password == null) {
|
||||
final String message = "Username or password is null";
|
||||
authenticationFailure("authenticate", message);
|
||||
}
|
||||
|
||||
// Perform authentication
|
||||
try {
|
||||
loginContext.login();
|
||||
final Subject subject = loginContext.getSubject();
|
||||
AccessController.doPrivileged(new PrivilegedAction<Void>() {
|
||||
public Void run() {
|
||||
subject.setReadOnly();
|
||||
return null;
|
||||
}
|
||||
});
|
||||
|
||||
return subject;
|
||||
|
||||
} catch (LoginException le) {
|
||||
authenticationFailure("authenticate", le);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static void authenticationFailure(String method, String message)
|
||||
throws SecurityException {
|
||||
final String msg = "Authentication failed! " + message;
|
||||
final SecurityException e = new SecurityException(msg);
|
||||
logException(method, msg, e);
|
||||
throw e;
|
||||
}
|
||||
|
||||
private static void authenticationFailure(String method,
|
||||
Exception exception)
|
||||
throws SecurityException {
|
||||
String msg;
|
||||
SecurityException se;
|
||||
if (exception instanceof SecurityException) {
|
||||
msg = exception.getMessage();
|
||||
se = (SecurityException) exception;
|
||||
} else {
|
||||
msg = "Authentication failed! " + exception.getMessage();
|
||||
final SecurityException e = new SecurityException(msg);
|
||||
EnvHelp.initCause(e, exception);
|
||||
se = e;
|
||||
}
|
||||
logException(method, msg, se);
|
||||
throw se;
|
||||
}
|
||||
|
||||
private static void logException(String method,
|
||||
String message,
|
||||
Exception e) {
|
||||
if (logger.traceOn()) {
|
||||
logger.trace(method, message);
|
||||
}
|
||||
if (logger.debugOn()) {
|
||||
logger.debug(method, e);
|
||||
}
|
||||
}
|
||||
|
||||
private LoginContext loginContext;
|
||||
private String username;
|
||||
private String password;
|
||||
private static final String LOGIN_CONFIG_PROP =
|
||||
"jmx.remote.x.login.config";
|
||||
private static final String LOGIN_CONFIG_NAME = "JMXPluggableAuthenticator";
|
||||
private static final String PASSWORD_FILE_PROP =
|
||||
"jmx.remote.x.password.file";
|
||||
private static final ClassLogger logger =
|
||||
new ClassLogger("javax.management.remote.misc", LOGIN_CONFIG_NAME);
|
||||
|
||||
/**
|
||||
* This callback handler supplies the username and password (which was
|
||||
* originally supplied by the JMX user) to the JAAS login module performing
|
||||
* the authentication. No interactive user prompting is required because the
|
||||
* credentials are already available to this class (via its enclosing class).
|
||||
*/
|
||||
private final class JMXCallbackHandler implements CallbackHandler {
|
||||
|
||||
/**
|
||||
* Sets the username and password in the appropriate Callback object.
|
||||
*/
|
||||
public void handle(Callback[] callbacks)
|
||||
throws IOException, UnsupportedCallbackException {
|
||||
|
||||
for (int i = 0; i < callbacks.length; i++) {
|
||||
if (callbacks[i] instanceof NameCallback) {
|
||||
((NameCallback)callbacks[i]).setName(username);
|
||||
|
||||
} else if (callbacks[i] instanceof PasswordCallback) {
|
||||
((PasswordCallback)callbacks[i])
|
||||
.setPassword(password.toCharArray());
|
||||
|
||||
} else {
|
||||
throw new UnsupportedCallbackException
|
||||
(callbacks[i], "Unrecognized Callback");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This class defines the JAAS configuration for file-based authentication.
|
||||
* It is equivalent to the following textual configuration entry:
|
||||
* <pre>
|
||||
* JMXPluggableAuthenticator {
|
||||
* com.sun.jmx.remote.security.FileLoginModule required;
|
||||
* };
|
||||
* </pre>
|
||||
*/
|
||||
private static class FileLoginConfig extends Configuration {
|
||||
|
||||
// The JAAS configuration for file-based authentication
|
||||
private AppConfigurationEntry[] entries;
|
||||
|
||||
// The classname of the login module for file-based authentication
|
||||
private static final String FILE_LOGIN_MODULE =
|
||||
FileLoginModule.class.getName();
|
||||
|
||||
// The option that identifies the password file to use
|
||||
private static final String PASSWORD_FILE_OPTION = "passwordFile";
|
||||
|
||||
/**
|
||||
* Creates an instance of <code>FileLoginConfig</code>
|
||||
*
|
||||
* @param passwordFile A filepath that identifies the password file to use.
|
||||
* If null then the default password file is used.
|
||||
*/
|
||||
public FileLoginConfig(String passwordFile) {
|
||||
|
||||
Map<String, String> options;
|
||||
if (passwordFile != null) {
|
||||
options = new HashMap<String, String>(1);
|
||||
options.put(PASSWORD_FILE_OPTION, passwordFile);
|
||||
} else {
|
||||
options = Collections.emptyMap();
|
||||
}
|
||||
|
||||
entries = new AppConfigurationEntry[] {
|
||||
new AppConfigurationEntry(FILE_LOGIN_MODULE,
|
||||
AppConfigurationEntry.LoginModuleControlFlag.REQUIRED,
|
||||
options)
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the JAAS configuration for file-based authentication
|
||||
*/
|
||||
public AppConfigurationEntry[] getAppConfigurationEntry(String name) {
|
||||
|
||||
return name.equals(LOGIN_CONFIG_NAME) ? entries : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Refreshes the configuration.
|
||||
*/
|
||||
public void refresh() {
|
||||
// the configuration is fixed
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,106 @@
|
||||
/*
|
||||
* Copyright (c) 2003, 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 com.sun.jmx.remote.security;
|
||||
|
||||
import java.security.AccessControlContext;
|
||||
import java.security.AccessController;
|
||||
import java.security.CodeSource;
|
||||
import java.security.Permissions;
|
||||
import java.security.ProtectionDomain;
|
||||
import javax.security.auth.Subject;
|
||||
import javax.security.auth.SubjectDomainCombiner;
|
||||
|
||||
/**
|
||||
* <p>This class represents an extension to the {@link SubjectDomainCombiner}
|
||||
* and is used to add a new {@link ProtectionDomain}, comprised of a null
|
||||
* codesource/signers and an empty permission set, to the access control
|
||||
* context with which this combiner is combined.</p>
|
||||
*
|
||||
* <p>When the {@link #combine} method is called the {@link ProtectionDomain}
|
||||
* is augmented with the permissions granted to the set of principals present
|
||||
* in the supplied {@link Subject}.</p>
|
||||
*/
|
||||
public class JMXSubjectDomainCombiner extends SubjectDomainCombiner {
|
||||
|
||||
public JMXSubjectDomainCombiner(Subject s) {
|
||||
super(s);
|
||||
}
|
||||
|
||||
public ProtectionDomain[] combine(ProtectionDomain[] current,
|
||||
ProtectionDomain[] assigned) {
|
||||
// Add a new ProtectionDomain with the null codesource/signers, and
|
||||
// the empty permission set, to the end of the array containing the
|
||||
// 'current' protections domains, i.e. the ones that will be augmented
|
||||
// with the permissions granted to the set of principals present in
|
||||
// the supplied subject.
|
||||
//
|
||||
ProtectionDomain[] newCurrent;
|
||||
if (current == null || current.length == 0) {
|
||||
newCurrent = new ProtectionDomain[1];
|
||||
newCurrent[0] = pdNoPerms;
|
||||
} else {
|
||||
newCurrent = new ProtectionDomain[current.length + 1];
|
||||
for (int i = 0; i < current.length; i++) {
|
||||
newCurrent[i] = current[i];
|
||||
}
|
||||
newCurrent[current.length] = pdNoPerms;
|
||||
}
|
||||
return super.combine(newCurrent, assigned);
|
||||
}
|
||||
|
||||
/**
|
||||
* A null CodeSource.
|
||||
*/
|
||||
private static final CodeSource nullCodeSource =
|
||||
new CodeSource(null, (java.security.cert.Certificate[]) null);
|
||||
|
||||
/**
|
||||
* A ProtectionDomain with a null CodeSource and an empty permission set.
|
||||
*/
|
||||
private static final ProtectionDomain pdNoPerms =
|
||||
new ProtectionDomain(nullCodeSource, new Permissions(), null, null);
|
||||
|
||||
/**
|
||||
* Get the current AccessControlContext combined with the supplied subject.
|
||||
*/
|
||||
public static AccessControlContext getContext(Subject subject) {
|
||||
return new AccessControlContext(AccessController.getContext(),
|
||||
new JMXSubjectDomainCombiner(subject));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the AccessControlContext of the domain combiner created with
|
||||
* the supplied subject, i.e. an AccessControlContext with the domain
|
||||
* combiner created with the supplied subject and where the caller's
|
||||
* context has been removed.
|
||||
*/
|
||||
public static AccessControlContext
|
||||
getDomainCombinerContext(Subject subject) {
|
||||
return new AccessControlContext(
|
||||
new AccessControlContext(new ProtectionDomain[0]),
|
||||
new JMXSubjectDomainCombiner(subject));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,665 @@
|
||||
/*
|
||||
* Copyright (c) 2003, 2006, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package com.sun.jmx.remote.security;
|
||||
|
||||
import com.sun.jmx.mbeanserver.GetPropertyAction;
|
||||
import java.io.ObjectInputStream;
|
||||
import java.security.AccessController;
|
||||
import java.util.Set;
|
||||
import javax.management.Attribute;
|
||||
import javax.management.AttributeList;
|
||||
import javax.management.AttributeNotFoundException;
|
||||
import javax.management.InstanceNotFoundException;
|
||||
import javax.management.InstanceAlreadyExistsException;
|
||||
import javax.management.IntrospectionException;
|
||||
import javax.management.InvalidAttributeValueException;
|
||||
import javax.management.ListenerNotFoundException;
|
||||
import javax.management.MBeanException;
|
||||
import javax.management.MBeanInfo;
|
||||
import javax.management.MBeanRegistrationException;
|
||||
import javax.management.MBeanServer;
|
||||
import javax.management.NotCompliantMBeanException;
|
||||
import javax.management.NotificationFilter;
|
||||
import javax.management.NotificationListener;
|
||||
import javax.management.ObjectInstance;
|
||||
import javax.management.ObjectName;
|
||||
import javax.management.OperationsException;
|
||||
import javax.management.QueryExp;
|
||||
import javax.management.ReflectionException;
|
||||
import javax.management.loading.ClassLoaderRepository;
|
||||
import javax.management.remote.MBeanServerForwarder;
|
||||
|
||||
/**
|
||||
* <p>An object of this class implements the MBeanServer interface
|
||||
* and, for each of its methods, calls an appropriate checking method
|
||||
* and then forwards the request to a wrapped MBeanServer object. The
|
||||
* checking method may throw a RuntimeException if the operation is
|
||||
* not allowed; in this case the request is not forwarded to the
|
||||
* wrapped object.</p>
|
||||
*
|
||||
* <p>A typical use of this class is to insert it between a connector server
|
||||
* such as the RMI connector and the MBeanServer with which the connector
|
||||
* is associated. Requests from the connector client can then be filtered
|
||||
* and those operations that are not allowed, or not allowed in a particular
|
||||
* context, can be rejected by throwing a <code>SecurityException</code>
|
||||
* in the corresponding <code>check*</code> method.</p>
|
||||
*
|
||||
* <p>This is an abstract class, because in its implementation none of
|
||||
* the checking methods does anything. To be useful, it must be
|
||||
* subclassed and at least one of the checking methods overridden to
|
||||
* do some checking. Some or all of the MBeanServer methods may also
|
||||
* be overridden, for instance if the default checking behavior is
|
||||
* inappropriate.</p>
|
||||
*
|
||||
* <p>If there is no SecurityManager, then the access controller will refuse
|
||||
* to create an MBean that is a ClassLoader, which includes MLets, or to
|
||||
* execute the method addURL on an MBean that is an MLet. This prevents
|
||||
* people from opening security holes unintentionally. Otherwise, it
|
||||
* would not be obvious that granting write access grants the ability to
|
||||
* download and execute arbitrary code in the target MBean server. Advanced
|
||||
* users who do want the ability to use MLets are presumably advanced enough
|
||||
* to handle policy files and security managers.</p>
|
||||
*/
|
||||
public abstract class MBeanServerAccessController
|
||||
implements MBeanServerForwarder {
|
||||
|
||||
public MBeanServer getMBeanServer() {
|
||||
return mbs;
|
||||
}
|
||||
|
||||
public void setMBeanServer(MBeanServer mbs) {
|
||||
if (mbs == null)
|
||||
throw new IllegalArgumentException("Null MBeanServer");
|
||||
if (this.mbs != null)
|
||||
throw new IllegalArgumentException("MBeanServer object already " +
|
||||
"initialized");
|
||||
this.mbs = mbs;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the caller can do read operations. This method does
|
||||
* nothing if so, otherwise throws SecurityException.
|
||||
*/
|
||||
protected abstract void checkRead();
|
||||
|
||||
/**
|
||||
* Check if the caller can do write operations. This method does
|
||||
* nothing if so, otherwise throws SecurityException.
|
||||
*/
|
||||
protected abstract void checkWrite();
|
||||
|
||||
/**
|
||||
* Check if the caller can create the named class. The default
|
||||
* implementation of this method calls {@link #checkWrite()}.
|
||||
*/
|
||||
protected void checkCreate(String className) {
|
||||
checkWrite();
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the caller can unregister the named MBean. The default
|
||||
* implementation of this method calls {@link #checkWrite()}.
|
||||
*/
|
||||
protected void checkUnregister(ObjectName name) {
|
||||
checkWrite();
|
||||
}
|
||||
|
||||
//--------------------------------------------
|
||||
//--------------------------------------------
|
||||
//
|
||||
// Implementation of the MBeanServer interface
|
||||
//
|
||||
//--------------------------------------------
|
||||
//--------------------------------------------
|
||||
|
||||
/**
|
||||
* Call <code>checkRead()</code>, then forward this method to the
|
||||
* wrapped object.
|
||||
*/
|
||||
public void addNotificationListener(ObjectName name,
|
||||
NotificationListener listener,
|
||||
NotificationFilter filter,
|
||||
Object handback)
|
||||
throws InstanceNotFoundException {
|
||||
checkRead();
|
||||
getMBeanServer().addNotificationListener(name, listener,
|
||||
filter, handback);
|
||||
}
|
||||
|
||||
/**
|
||||
* Call <code>checkRead()</code>, then forward this method to the
|
||||
* wrapped object.
|
||||
*/
|
||||
public void addNotificationListener(ObjectName name,
|
||||
ObjectName listener,
|
||||
NotificationFilter filter,
|
||||
Object handback)
|
||||
throws InstanceNotFoundException {
|
||||
checkRead();
|
||||
getMBeanServer().addNotificationListener(name, listener,
|
||||
filter, handback);
|
||||
}
|
||||
|
||||
/**
|
||||
* Call <code>checkCreate(className)</code>, then forward this method to the
|
||||
* wrapped object.
|
||||
*/
|
||||
public ObjectInstance createMBean(String className, ObjectName name)
|
||||
throws
|
||||
ReflectionException,
|
||||
InstanceAlreadyExistsException,
|
||||
MBeanRegistrationException,
|
||||
MBeanException,
|
||||
NotCompliantMBeanException {
|
||||
checkCreate(className);
|
||||
SecurityManager sm = System.getSecurityManager();
|
||||
if (sm == null) {
|
||||
Object object = getMBeanServer().instantiate(className);
|
||||
checkClassLoader(object);
|
||||
return getMBeanServer().registerMBean(object, name);
|
||||
} else {
|
||||
return getMBeanServer().createMBean(className, name);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Call <code>checkCreate(className)</code>, then forward this method to the
|
||||
* wrapped object.
|
||||
*/
|
||||
public ObjectInstance createMBean(String className, ObjectName name,
|
||||
Object params[], String signature[])
|
||||
throws
|
||||
ReflectionException,
|
||||
InstanceAlreadyExistsException,
|
||||
MBeanRegistrationException,
|
||||
MBeanException,
|
||||
NotCompliantMBeanException {
|
||||
checkCreate(className);
|
||||
SecurityManager sm = System.getSecurityManager();
|
||||
if (sm == null) {
|
||||
Object object = getMBeanServer().instantiate(className,
|
||||
params,
|
||||
signature);
|
||||
checkClassLoader(object);
|
||||
return getMBeanServer().registerMBean(object, name);
|
||||
} else {
|
||||
return getMBeanServer().createMBean(className, name,
|
||||
params, signature);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Call <code>checkCreate(className)</code>, then forward this method to the
|
||||
* wrapped object.
|
||||
*/
|
||||
public ObjectInstance createMBean(String className,
|
||||
ObjectName name,
|
||||
ObjectName loaderName)
|
||||
throws
|
||||
ReflectionException,
|
||||
InstanceAlreadyExistsException,
|
||||
MBeanRegistrationException,
|
||||
MBeanException,
|
||||
NotCompliantMBeanException,
|
||||
InstanceNotFoundException {
|
||||
checkCreate(className);
|
||||
SecurityManager sm = System.getSecurityManager();
|
||||
if (sm == null) {
|
||||
Object object = getMBeanServer().instantiate(className,
|
||||
loaderName);
|
||||
checkClassLoader(object);
|
||||
return getMBeanServer().registerMBean(object, name);
|
||||
} else {
|
||||
return getMBeanServer().createMBean(className, name, loaderName);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Call <code>checkCreate(className)</code>, then forward this method to the
|
||||
* wrapped object.
|
||||
*/
|
||||
public ObjectInstance createMBean(String className,
|
||||
ObjectName name,
|
||||
ObjectName loaderName,
|
||||
Object params[],
|
||||
String signature[])
|
||||
throws
|
||||
ReflectionException,
|
||||
InstanceAlreadyExistsException,
|
||||
MBeanRegistrationException,
|
||||
MBeanException,
|
||||
NotCompliantMBeanException,
|
||||
InstanceNotFoundException {
|
||||
checkCreate(className);
|
||||
SecurityManager sm = System.getSecurityManager();
|
||||
if (sm == null) {
|
||||
Object object = getMBeanServer().instantiate(className,
|
||||
loaderName,
|
||||
params,
|
||||
signature);
|
||||
checkClassLoader(object);
|
||||
return getMBeanServer().registerMBean(object, name);
|
||||
} else {
|
||||
return getMBeanServer().createMBean(className, name, loaderName,
|
||||
params, signature);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Call <code>checkRead()</code>, then forward this method to the
|
||||
* wrapped object.
|
||||
*/
|
||||
@Deprecated
|
||||
public ObjectInputStream deserialize(ObjectName name, byte[] data)
|
||||
throws InstanceNotFoundException, OperationsException {
|
||||
checkRead();
|
||||
return getMBeanServer().deserialize(name, data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Call <code>checkRead()</code>, then forward this method to the
|
||||
* wrapped object.
|
||||
*/
|
||||
@Deprecated
|
||||
public ObjectInputStream deserialize(String className, byte[] data)
|
||||
throws OperationsException, ReflectionException {
|
||||
checkRead();
|
||||
return getMBeanServer().deserialize(className, data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Call <code>checkRead()</code>, then forward this method to the
|
||||
* wrapped object.
|
||||
*/
|
||||
@Deprecated
|
||||
public ObjectInputStream deserialize(String className,
|
||||
ObjectName loaderName,
|
||||
byte[] data)
|
||||
throws
|
||||
InstanceNotFoundException,
|
||||
OperationsException,
|
||||
ReflectionException {
|
||||
checkRead();
|
||||
return getMBeanServer().deserialize(className, loaderName, data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Call <code>checkRead()</code>, then forward this method to the
|
||||
* wrapped object.
|
||||
*/
|
||||
public Object getAttribute(ObjectName name, String attribute)
|
||||
throws
|
||||
MBeanException,
|
||||
AttributeNotFoundException,
|
||||
InstanceNotFoundException,
|
||||
ReflectionException {
|
||||
checkRead();
|
||||
return getMBeanServer().getAttribute(name, attribute);
|
||||
}
|
||||
|
||||
/**
|
||||
* Call <code>checkRead()</code>, then forward this method to the
|
||||
* wrapped object.
|
||||
*/
|
||||
public AttributeList getAttributes(ObjectName name, String[] attributes)
|
||||
throws InstanceNotFoundException, ReflectionException {
|
||||
checkRead();
|
||||
return getMBeanServer().getAttributes(name, attributes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Call <code>checkRead()</code>, then forward this method to the
|
||||
* wrapped object.
|
||||
*/
|
||||
public ClassLoader getClassLoader(ObjectName loaderName)
|
||||
throws InstanceNotFoundException {
|
||||
checkRead();
|
||||
return getMBeanServer().getClassLoader(loaderName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Call <code>checkRead()</code>, then forward this method to the
|
||||
* wrapped object.
|
||||
*/
|
||||
public ClassLoader getClassLoaderFor(ObjectName mbeanName)
|
||||
throws InstanceNotFoundException {
|
||||
checkRead();
|
||||
return getMBeanServer().getClassLoaderFor(mbeanName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Call <code>checkRead()</code>, then forward this method to the
|
||||
* wrapped object.
|
||||
*/
|
||||
public ClassLoaderRepository getClassLoaderRepository() {
|
||||
checkRead();
|
||||
return getMBeanServer().getClassLoaderRepository();
|
||||
}
|
||||
|
||||
/**
|
||||
* Call <code>checkRead()</code>, then forward this method to the
|
||||
* wrapped object.
|
||||
*/
|
||||
public String getDefaultDomain() {
|
||||
checkRead();
|
||||
return getMBeanServer().getDefaultDomain();
|
||||
}
|
||||
|
||||
/**
|
||||
* Call <code>checkRead()</code>, then forward this method to the
|
||||
* wrapped object.
|
||||
*/
|
||||
public String[] getDomains() {
|
||||
checkRead();
|
||||
return getMBeanServer().getDomains();
|
||||
}
|
||||
|
||||
/**
|
||||
* Call <code>checkRead()</code>, then forward this method to the
|
||||
* wrapped object.
|
||||
*/
|
||||
public Integer getMBeanCount() {
|
||||
checkRead();
|
||||
return getMBeanServer().getMBeanCount();
|
||||
}
|
||||
|
||||
/**
|
||||
* Call <code>checkRead()</code>, then forward this method to the
|
||||
* wrapped object.
|
||||
*/
|
||||
public MBeanInfo getMBeanInfo(ObjectName name)
|
||||
throws
|
||||
InstanceNotFoundException,
|
||||
IntrospectionException,
|
||||
ReflectionException {
|
||||
checkRead();
|
||||
return getMBeanServer().getMBeanInfo(name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Call <code>checkRead()</code>, then forward this method to the
|
||||
* wrapped object.
|
||||
*/
|
||||
public ObjectInstance getObjectInstance(ObjectName name)
|
||||
throws InstanceNotFoundException {
|
||||
checkRead();
|
||||
return getMBeanServer().getObjectInstance(name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Call <code>checkCreate(className)</code>, then forward this method to the
|
||||
* wrapped object.
|
||||
*/
|
||||
public Object instantiate(String className)
|
||||
throws ReflectionException, MBeanException {
|
||||
checkCreate(className);
|
||||
return getMBeanServer().instantiate(className);
|
||||
}
|
||||
|
||||
/**
|
||||
* Call <code>checkCreate(className)</code>, then forward this method to the
|
||||
* wrapped object.
|
||||
*/
|
||||
public Object instantiate(String className,
|
||||
Object params[],
|
||||
String signature[])
|
||||
throws ReflectionException, MBeanException {
|
||||
checkCreate(className);
|
||||
return getMBeanServer().instantiate(className, params, signature);
|
||||
}
|
||||
|
||||
/**
|
||||
* Call <code>checkCreate(className)</code>, then forward this method to the
|
||||
* wrapped object.
|
||||
*/
|
||||
public Object instantiate(String className, ObjectName loaderName)
|
||||
throws ReflectionException, MBeanException, InstanceNotFoundException {
|
||||
checkCreate(className);
|
||||
return getMBeanServer().instantiate(className, loaderName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Call <code>checkCreate(className)</code>, then forward this method to the
|
||||
* wrapped object.
|
||||
*/
|
||||
public Object instantiate(String className, ObjectName loaderName,
|
||||
Object params[], String signature[])
|
||||
throws ReflectionException, MBeanException, InstanceNotFoundException {
|
||||
checkCreate(className);
|
||||
return getMBeanServer().instantiate(className, loaderName,
|
||||
params, signature);
|
||||
}
|
||||
|
||||
/**
|
||||
* Call <code>checkWrite()</code>, then forward this method to the
|
||||
* wrapped object.
|
||||
*/
|
||||
public Object invoke(ObjectName name, String operationName,
|
||||
Object params[], String signature[])
|
||||
throws
|
||||
InstanceNotFoundException,
|
||||
MBeanException,
|
||||
ReflectionException {
|
||||
checkWrite();
|
||||
checkMLetMethods(name, operationName);
|
||||
return getMBeanServer().invoke(name, operationName, params, signature);
|
||||
}
|
||||
|
||||
/**
|
||||
* Call <code>checkRead()</code>, then forward this method to the
|
||||
* wrapped object.
|
||||
*/
|
||||
public boolean isInstanceOf(ObjectName name, String className)
|
||||
throws InstanceNotFoundException {
|
||||
checkRead();
|
||||
return getMBeanServer().isInstanceOf(name, className);
|
||||
}
|
||||
|
||||
/**
|
||||
* Call <code>checkRead()</code>, then forward this method to the
|
||||
* wrapped object.
|
||||
*/
|
||||
public boolean isRegistered(ObjectName name) {
|
||||
checkRead();
|
||||
return getMBeanServer().isRegistered(name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Call <code>checkRead()</code>, then forward this method to the
|
||||
* wrapped object.
|
||||
*/
|
||||
public Set<ObjectInstance> queryMBeans(ObjectName name, QueryExp query) {
|
||||
checkRead();
|
||||
return getMBeanServer().queryMBeans(name, query);
|
||||
}
|
||||
|
||||
/**
|
||||
* Call <code>checkRead()</code>, then forward this method to the
|
||||
* wrapped object.
|
||||
*/
|
||||
public Set<ObjectName> queryNames(ObjectName name, QueryExp query) {
|
||||
checkRead();
|
||||
return getMBeanServer().queryNames(name, query);
|
||||
}
|
||||
|
||||
/**
|
||||
* Call <code>checkWrite()</code>, then forward this method to the
|
||||
* wrapped object.
|
||||
*/
|
||||
public ObjectInstance registerMBean(Object object, ObjectName name)
|
||||
throws
|
||||
InstanceAlreadyExistsException,
|
||||
MBeanRegistrationException,
|
||||
NotCompliantMBeanException {
|
||||
checkWrite();
|
||||
return getMBeanServer().registerMBean(object, name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Call <code>checkRead()</code>, then forward this method to the
|
||||
* wrapped object.
|
||||
*/
|
||||
public void removeNotificationListener(ObjectName name,
|
||||
NotificationListener listener)
|
||||
throws InstanceNotFoundException, ListenerNotFoundException {
|
||||
checkRead();
|
||||
getMBeanServer().removeNotificationListener(name, listener);
|
||||
}
|
||||
|
||||
/**
|
||||
* Call <code>checkRead()</code>, then forward this method to the
|
||||
* wrapped object.
|
||||
*/
|
||||
public void removeNotificationListener(ObjectName name,
|
||||
NotificationListener listener,
|
||||
NotificationFilter filter,
|
||||
Object handback)
|
||||
throws InstanceNotFoundException, ListenerNotFoundException {
|
||||
checkRead();
|
||||
getMBeanServer().removeNotificationListener(name, listener,
|
||||
filter, handback);
|
||||
}
|
||||
|
||||
/**
|
||||
* Call <code>checkRead()</code>, then forward this method to the
|
||||
* wrapped object.
|
||||
*/
|
||||
public void removeNotificationListener(ObjectName name,
|
||||
ObjectName listener)
|
||||
throws InstanceNotFoundException, ListenerNotFoundException {
|
||||
checkRead();
|
||||
getMBeanServer().removeNotificationListener(name, listener);
|
||||
}
|
||||
|
||||
/**
|
||||
* Call <code>checkRead()</code>, then forward this method to the
|
||||
* wrapped object.
|
||||
*/
|
||||
public void removeNotificationListener(ObjectName name,
|
||||
ObjectName listener,
|
||||
NotificationFilter filter,
|
||||
Object handback)
|
||||
throws InstanceNotFoundException, ListenerNotFoundException {
|
||||
checkRead();
|
||||
getMBeanServer().removeNotificationListener(name, listener,
|
||||
filter, handback);
|
||||
}
|
||||
|
||||
/**
|
||||
* Call <code>checkWrite()</code>, then forward this method to the
|
||||
* wrapped object.
|
||||
*/
|
||||
public void setAttribute(ObjectName name, Attribute attribute)
|
||||
throws
|
||||
InstanceNotFoundException,
|
||||
AttributeNotFoundException,
|
||||
InvalidAttributeValueException,
|
||||
MBeanException,
|
||||
ReflectionException {
|
||||
checkWrite();
|
||||
getMBeanServer().setAttribute(name, attribute);
|
||||
}
|
||||
|
||||
/**
|
||||
* Call <code>checkWrite()</code>, then forward this method to the
|
||||
* wrapped object.
|
||||
*/
|
||||
public AttributeList setAttributes(ObjectName name,
|
||||
AttributeList attributes)
|
||||
throws InstanceNotFoundException, ReflectionException {
|
||||
checkWrite();
|
||||
return getMBeanServer().setAttributes(name, attributes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Call <code>checkUnregister()</code>, then forward this method to the
|
||||
* wrapped object.
|
||||
*/
|
||||
public void unregisterMBean(ObjectName name)
|
||||
throws InstanceNotFoundException, MBeanRegistrationException {
|
||||
checkUnregister(name);
|
||||
getMBeanServer().unregisterMBean(name);
|
||||
}
|
||||
|
||||
//----------------
|
||||
// PRIVATE METHODS
|
||||
//----------------
|
||||
|
||||
private void checkClassLoader(Object object) {
|
||||
if (object instanceof ClassLoader)
|
||||
throw new SecurityException("Access denied! Creating an " +
|
||||
"MBean that is a ClassLoader " +
|
||||
"is forbidden unless a security " +
|
||||
"manager is installed.");
|
||||
}
|
||||
|
||||
private void checkMLetMethods(ObjectName name, String operation)
|
||||
throws InstanceNotFoundException {
|
||||
// Check if security manager installed
|
||||
SecurityManager sm = System.getSecurityManager();
|
||||
if (sm != null) {
|
||||
return;
|
||||
}
|
||||
// Check for addURL and getMBeansFromURL methods
|
||||
if (!operation.equals("addURL") &&
|
||||
!operation.equals("getMBeansFromURL")) {
|
||||
return;
|
||||
}
|
||||
// Check if MBean is instance of MLet
|
||||
if (!getMBeanServer().isInstanceOf(name,
|
||||
"javax.management.loading.MLet")) {
|
||||
return;
|
||||
}
|
||||
// Throw security exception
|
||||
if (operation.equals("addURL")) { // addURL
|
||||
throw new SecurityException("Access denied! MLet method addURL " +
|
||||
"cannot be invoked unless a security manager is installed.");
|
||||
} else { // getMBeansFromURL
|
||||
// Whether or not calling getMBeansFromURL is allowed is controlled
|
||||
// by the value of the "jmx.remote.x.mlet.allow.getMBeansFromURL"
|
||||
// system property. If the value of this property is true, calling
|
||||
// the MLet's getMBeansFromURL method is allowed. The default value
|
||||
// for this property is false.
|
||||
final String propName = "jmx.remote.x.mlet.allow.getMBeansFromURL";
|
||||
GetPropertyAction propAction = new GetPropertyAction(propName);
|
||||
String propValue = AccessController.doPrivileged(propAction);
|
||||
boolean allowGetMBeansFromURL = "true".equalsIgnoreCase(propValue);
|
||||
if (!allowGetMBeansFromURL) {
|
||||
throw new SecurityException("Access denied! MLet method " +
|
||||
"getMBeansFromURL cannot be invoked unless a " +
|
||||
"security manager is installed or the system property " +
|
||||
"-Djmx.remote.x.mlet.allow.getMBeansFromURL=true " +
|
||||
"is specified.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//------------------
|
||||
// PRIVATE VARIABLES
|
||||
//------------------
|
||||
|
||||
private MBeanServer mbs;
|
||||
}
|
||||
@@ -0,0 +1,544 @@
|
||||
/*
|
||||
* 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.security;
|
||||
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.security.AccessControlContext;
|
||||
import java.security.AccessController;
|
||||
import java.security.Principal;
|
||||
import java.security.PrivilegedAction;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
import java.util.Set;
|
||||
import java.util.StringTokenizer;
|
||||
import java.util.regex.Pattern;
|
||||
import javax.management.MBeanServer;
|
||||
import javax.management.ObjectName;
|
||||
import javax.security.auth.Subject;
|
||||
|
||||
/**
|
||||
* <p>An object of this class implements the MBeanServerAccessController
|
||||
* interface and, for each of its methods, calls an appropriate checking
|
||||
* method and then forwards the request to a wrapped MBeanServer object.
|
||||
* The checking method may throw a SecurityException if the operation is
|
||||
* not allowed; in this case the request is not forwarded to the
|
||||
* wrapped object.</p>
|
||||
*
|
||||
* <p>This class implements the {@link #checkRead()}, {@link #checkWrite()},
|
||||
* {@link #checkCreate(String)}, and {@link #checkUnregister(ObjectName)}
|
||||
* methods based on an access level properties file containing username/access
|
||||
* level pairs. The set of username/access level pairs is passed either as a
|
||||
* filename which denotes a properties file on disk, or directly as an instance
|
||||
* of the {@link Properties} class. In both cases, the name of each property
|
||||
* represents a username, and the value of the property is the associated access
|
||||
* level. Thus, any given username either does not exist in the properties or
|
||||
* has exactly one access level. The same access level can be shared by several
|
||||
* usernames.</p>
|
||||
*
|
||||
* <p>The supported access level values are {@code readonly} and
|
||||
* {@code readwrite}. The {@code readwrite} access level can be
|
||||
* qualified by one or more <i>clauses</i>, where each clause looks
|
||||
* like <code>create <i>classNamePattern</i></code> or {@code
|
||||
* unregister}. For example:</p>
|
||||
*
|
||||
* <pre>
|
||||
* monitorRole readonly
|
||||
* controlRole readwrite \
|
||||
* create javax.management.timer.*,javax.management.monitor.* \
|
||||
* unregister
|
||||
* </pre>
|
||||
*
|
||||
* <p>(The continuation lines with {@code \} come from the parser for
|
||||
* Properties files.)</p>
|
||||
*/
|
||||
public class MBeanServerFileAccessController
|
||||
extends MBeanServerAccessController {
|
||||
|
||||
static final String READONLY = "readonly";
|
||||
static final String READWRITE = "readwrite";
|
||||
|
||||
static final String CREATE = "create";
|
||||
static final String UNREGISTER = "unregister";
|
||||
|
||||
private enum AccessType {READ, WRITE, CREATE, UNREGISTER};
|
||||
|
||||
private static class Access {
|
||||
final boolean write;
|
||||
final String[] createPatterns;
|
||||
private boolean unregister;
|
||||
|
||||
Access(boolean write, boolean unregister, List<String> createPatternList) {
|
||||
this.write = write;
|
||||
int npats = (createPatternList == null) ? 0 : createPatternList.size();
|
||||
if (npats == 0)
|
||||
this.createPatterns = NO_STRINGS;
|
||||
else
|
||||
this.createPatterns = createPatternList.toArray(new String[npats]);
|
||||
this.unregister = unregister;
|
||||
}
|
||||
|
||||
private final String[] NO_STRINGS = new String[0];
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Create a new MBeanServerAccessController that forwards all the
|
||||
* MBeanServer requests to the MBeanServer set by invoking the {@link
|
||||
* #setMBeanServer} method after doing access checks based on read and
|
||||
* write permissions.</p>
|
||||
*
|
||||
* <p>This instance is initialized from the specified properties file.</p>
|
||||
*
|
||||
* @param accessFileName name of the file which denotes a properties
|
||||
* file on disk containing the username/access level entries.
|
||||
*
|
||||
* @exception IOException if the file does not exist, is a
|
||||
* directory rather than a regular file, or for some other
|
||||
* reason cannot be opened for reading.
|
||||
*
|
||||
* @exception IllegalArgumentException if any of the supplied access
|
||||
* level values differs from "readonly" or "readwrite".
|
||||
*/
|
||||
public MBeanServerFileAccessController(String accessFileName)
|
||||
throws IOException {
|
||||
super();
|
||||
this.accessFileName = accessFileName;
|
||||
Properties props = propertiesFromFile(accessFileName);
|
||||
parseProperties(props);
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Create a new MBeanServerAccessController that forwards all the
|
||||
* MBeanServer requests to <code>mbs</code> after doing access checks
|
||||
* based on read and write permissions.</p>
|
||||
*
|
||||
* <p>This instance is initialized from the specified properties file.</p>
|
||||
*
|
||||
* @param accessFileName name of the file which denotes a properties
|
||||
* file on disk containing the username/access level entries.
|
||||
*
|
||||
* @param mbs the MBeanServer object to which requests will be forwarded.
|
||||
*
|
||||
* @exception IOException if the file does not exist, is a
|
||||
* directory rather than a regular file, or for some other
|
||||
* reason cannot be opened for reading.
|
||||
*
|
||||
* @exception IllegalArgumentException if any of the supplied access
|
||||
* level values differs from "readonly" or "readwrite".
|
||||
*/
|
||||
public MBeanServerFileAccessController(String accessFileName,
|
||||
MBeanServer mbs)
|
||||
throws IOException {
|
||||
this(accessFileName);
|
||||
setMBeanServer(mbs);
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Create a new MBeanServerAccessController that forwards all the
|
||||
* MBeanServer requests to the MBeanServer set by invoking the {@link
|
||||
* #setMBeanServer} method after doing access checks based on read and
|
||||
* write permissions.</p>
|
||||
*
|
||||
* <p>This instance is initialized from the specified properties
|
||||
* instance. This constructor makes a copy of the properties
|
||||
* instance and it is the copy that is consulted to check the
|
||||
* username and access level of an incoming connection. The
|
||||
* original properties object can be modified without affecting
|
||||
* the copy. If the {@link #refresh} method is then called, the
|
||||
* <code>MBeanServerFileAccessController</code> will make a new
|
||||
* copy of the properties object at that time.</p>
|
||||
*
|
||||
* @param accessFileProps properties list containing the username/access
|
||||
* level entries.
|
||||
*
|
||||
* @exception IllegalArgumentException if <code>accessFileProps</code> is
|
||||
* <code>null</code> or if any of the supplied access level values differs
|
||||
* from "readonly" or "readwrite".
|
||||
*/
|
||||
public MBeanServerFileAccessController(Properties accessFileProps)
|
||||
throws IOException {
|
||||
super();
|
||||
if (accessFileProps == null)
|
||||
throw new IllegalArgumentException("Null properties");
|
||||
originalProps = accessFileProps;
|
||||
parseProperties(accessFileProps);
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Create a new MBeanServerAccessController that forwards all the
|
||||
* MBeanServer requests to the MBeanServer set by invoking the {@link
|
||||
* #setMBeanServer} method after doing access checks based on read and
|
||||
* write permissions.</p>
|
||||
*
|
||||
* <p>This instance is initialized from the specified properties
|
||||
* instance. This constructor makes a copy of the properties
|
||||
* instance and it is the copy that is consulted to check the
|
||||
* username and access level of an incoming connection. The
|
||||
* original properties object can be modified without affecting
|
||||
* the copy. If the {@link #refresh} method is then called, the
|
||||
* <code>MBeanServerFileAccessController</code> will make a new
|
||||
* copy of the properties object at that time.</p>
|
||||
*
|
||||
* @param accessFileProps properties list containing the username/access
|
||||
* level entries.
|
||||
*
|
||||
* @param mbs the MBeanServer object to which requests will be forwarded.
|
||||
*
|
||||
* @exception IllegalArgumentException if <code>accessFileProps</code> is
|
||||
* <code>null</code> or if any of the supplied access level values differs
|
||||
* from "readonly" or "readwrite".
|
||||
*/
|
||||
public MBeanServerFileAccessController(Properties accessFileProps,
|
||||
MBeanServer mbs)
|
||||
throws IOException {
|
||||
this(accessFileProps);
|
||||
setMBeanServer(mbs);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the caller can do read operations. This method does
|
||||
* nothing if so, otherwise throws SecurityException.
|
||||
*/
|
||||
@Override
|
||||
public void checkRead() {
|
||||
checkAccess(AccessType.READ, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the caller can do write operations. This method does
|
||||
* nothing if so, otherwise throws SecurityException.
|
||||
*/
|
||||
@Override
|
||||
public void checkWrite() {
|
||||
checkAccess(AccessType.WRITE, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the caller can create MBeans or instances of the given class.
|
||||
* This method does nothing if so, otherwise throws SecurityException.
|
||||
*/
|
||||
@Override
|
||||
public void checkCreate(String className) {
|
||||
checkAccess(AccessType.CREATE, className);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the caller can do unregister operations. This method does
|
||||
* nothing if so, otherwise throws SecurityException.
|
||||
*/
|
||||
@Override
|
||||
public void checkUnregister(ObjectName name) {
|
||||
checkAccess(AccessType.UNREGISTER, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Refresh the set of username/access level entries.</p>
|
||||
*
|
||||
* <p>If this instance was created using the
|
||||
* {@link #MBeanServerFileAccessController(String)} or
|
||||
* {@link #MBeanServerFileAccessController(String,MBeanServer)}
|
||||
* constructors to specify a file from which the entries are read,
|
||||
* the file is re-read.</p>
|
||||
*
|
||||
* <p>If this instance was created using the
|
||||
* {@link #MBeanServerFileAccessController(Properties)} or
|
||||
* {@link #MBeanServerFileAccessController(Properties,MBeanServer)}
|
||||
* constructors then a new copy of the <code>Properties</code> object
|
||||
* is made.</p>
|
||||
*
|
||||
* @exception IOException if the file does not exist, is a
|
||||
* directory rather than a regular file, or for some other
|
||||
* reason cannot be opened for reading.
|
||||
*
|
||||
* @exception IllegalArgumentException if any of the supplied access
|
||||
* level values differs from "readonly" or "readwrite".
|
||||
*/
|
||||
public synchronized void refresh() throws IOException {
|
||||
Properties props;
|
||||
if (accessFileName == null)
|
||||
props = (Properties) originalProps;
|
||||
else
|
||||
props = propertiesFromFile(accessFileName);
|
||||
parseProperties(props);
|
||||
}
|
||||
|
||||
private static Properties propertiesFromFile(String fname)
|
||||
throws IOException {
|
||||
FileInputStream fin = new FileInputStream(fname);
|
||||
try {
|
||||
Properties p = new Properties();
|
||||
p.load(fin);
|
||||
return p;
|
||||
} finally {
|
||||
fin.close();
|
||||
}
|
||||
}
|
||||
|
||||
private synchronized void checkAccess(AccessType requiredAccess, String arg) {
|
||||
final AccessControlContext acc = AccessController.getContext();
|
||||
final Subject s =
|
||||
AccessController.doPrivileged(new PrivilegedAction<Subject>() {
|
||||
public Subject run() {
|
||||
return Subject.getSubject(acc);
|
||||
}
|
||||
});
|
||||
if (s == null) return; /* security has not been enabled */
|
||||
final Set principals = s.getPrincipals();
|
||||
String newPropertyValue = null;
|
||||
for (Iterator i = principals.iterator(); i.hasNext(); ) {
|
||||
final Principal p = (Principal) i.next();
|
||||
Access access = accessMap.get(p.getName());
|
||||
if (access != null) {
|
||||
boolean ok;
|
||||
switch (requiredAccess) {
|
||||
case READ:
|
||||
ok = true; // all access entries imply read
|
||||
break;
|
||||
case WRITE:
|
||||
ok = access.write;
|
||||
break;
|
||||
case UNREGISTER:
|
||||
ok = access.unregister;
|
||||
if (!ok && access.write)
|
||||
newPropertyValue = "unregister";
|
||||
break;
|
||||
case CREATE:
|
||||
ok = checkCreateAccess(access, arg);
|
||||
if (!ok && access.write)
|
||||
newPropertyValue = "create " + arg;
|
||||
break;
|
||||
default:
|
||||
throw new AssertionError();
|
||||
}
|
||||
if (ok)
|
||||
return;
|
||||
}
|
||||
}
|
||||
SecurityException se = new SecurityException("Access denied! Invalid " +
|
||||
"access level for requested MBeanServer operation.");
|
||||
// Add some more information to help people with deployments that
|
||||
// worked before we required explicit create clauses. We're not giving
|
||||
// any information to the bad guys, other than that the access control
|
||||
// is based on a file, which they could have worked out from the stack
|
||||
// trace anyway.
|
||||
if (newPropertyValue != null) {
|
||||
SecurityException se2 = new SecurityException("Access property " +
|
||||
"for this identity should be similar to: " + READWRITE +
|
||||
" " + newPropertyValue);
|
||||
se.initCause(se2);
|
||||
}
|
||||
throw se;
|
||||
}
|
||||
|
||||
private static boolean checkCreateAccess(Access access, String className) {
|
||||
for (String classNamePattern : access.createPatterns) {
|
||||
if (classNameMatch(classNamePattern, className))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private static boolean classNameMatch(String pattern, String className) {
|
||||
// We studiously avoided regexes when parsing the properties file,
|
||||
// because that is done whenever the VM is started with the
|
||||
// appropriate -Dcom.sun.management options, even if nobody ever
|
||||
// creates an MBean. We don't want to incur the overhead of loading
|
||||
// all the regex code whenever those options are specified, but if we
|
||||
// get as far as here then the VM is already running and somebody is
|
||||
// doing the very unusual operation of remotely creating an MBean.
|
||||
// Because that operation is so unusual, we don't try to optimize
|
||||
// by hand-matching or by caching compiled Pattern objects.
|
||||
StringBuilder sb = new StringBuilder();
|
||||
StringTokenizer stok = new StringTokenizer(pattern, "*", true);
|
||||
while (stok.hasMoreTokens()) {
|
||||
String tok = stok.nextToken();
|
||||
if (tok.equals("*"))
|
||||
sb.append("[^.]*");
|
||||
else
|
||||
sb.append(Pattern.quote(tok));
|
||||
}
|
||||
return className.matches(sb.toString());
|
||||
}
|
||||
|
||||
private void parseProperties(Properties props) {
|
||||
this.accessMap = new HashMap<String, Access>();
|
||||
for (Map.Entry<Object, Object> entry : props.entrySet()) {
|
||||
String identity = (String) entry.getKey();
|
||||
String accessString = (String) entry.getValue();
|
||||
Access access = Parser.parseAccess(identity, accessString);
|
||||
accessMap.put(identity, access);
|
||||
}
|
||||
}
|
||||
|
||||
private static class Parser {
|
||||
private final static int EOS = -1; // pseudo-codepoint "end of string"
|
||||
static {
|
||||
assert !Character.isWhitespace(EOS);
|
||||
}
|
||||
|
||||
private final String identity; // just for better error messages
|
||||
private final String s; // the string we're parsing
|
||||
private final int len; // s.length()
|
||||
private int i;
|
||||
private int c;
|
||||
// At any point, either c is s.codePointAt(i), or i == len and
|
||||
// c is EOS. We use int rather than char because it is conceivable
|
||||
// (if unlikely) that a classname in a create clause might contain
|
||||
// "supplementary characters", the ones that don't fit in the original
|
||||
// 16 bits for Unicode.
|
||||
|
||||
private Parser(String identity, String s) {
|
||||
this.identity = identity;
|
||||
this.s = s;
|
||||
this.len = s.length();
|
||||
this.i = 0;
|
||||
if (i < len)
|
||||
this.c = s.codePointAt(i);
|
||||
else
|
||||
this.c = EOS;
|
||||
}
|
||||
|
||||
static Access parseAccess(String identity, String s) {
|
||||
return new Parser(identity, s).parseAccess();
|
||||
}
|
||||
|
||||
private Access parseAccess() {
|
||||
skipSpace();
|
||||
String type = parseWord();
|
||||
Access access;
|
||||
if (type.equals(READONLY))
|
||||
access = new Access(false, false, null);
|
||||
else if (type.equals(READWRITE))
|
||||
access = parseReadWrite();
|
||||
else {
|
||||
throw syntax("Expected " + READONLY + " or " + READWRITE +
|
||||
": " + type);
|
||||
}
|
||||
if (c != EOS)
|
||||
throw syntax("Extra text at end of line");
|
||||
return access;
|
||||
}
|
||||
|
||||
private Access parseReadWrite() {
|
||||
List<String> createClasses = new ArrayList<String>();
|
||||
boolean unregister = false;
|
||||
while (true) {
|
||||
skipSpace();
|
||||
if (c == EOS)
|
||||
break;
|
||||
String type = parseWord();
|
||||
if (type.equals(UNREGISTER))
|
||||
unregister = true;
|
||||
else if (type.equals(CREATE))
|
||||
parseCreate(createClasses);
|
||||
else
|
||||
throw syntax("Unrecognized keyword " + type);
|
||||
}
|
||||
return new Access(true, unregister, createClasses);
|
||||
}
|
||||
|
||||
private void parseCreate(List<String> createClasses) {
|
||||
while (true) {
|
||||
skipSpace();
|
||||
createClasses.add(parseClassName());
|
||||
skipSpace();
|
||||
if (c == ',')
|
||||
next();
|
||||
else
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private String parseClassName() {
|
||||
// We don't check that classname components begin with suitable
|
||||
// characters (so we accept 1.2.3 for example). This means that
|
||||
// there are only two states, which we can call dotOK and !dotOK
|
||||
// according as a dot (.) is legal or not. Initially we're in
|
||||
// !dotOK since a classname can't start with a dot; after a dot
|
||||
// we're in !dotOK again; and after any other characters we're in
|
||||
// dotOK. The classname is only accepted if we end in dotOK,
|
||||
// so we reject an empty name or a name that ends with a dot.
|
||||
final int start = i;
|
||||
boolean dotOK = false;
|
||||
while (true) {
|
||||
if (c == '.') {
|
||||
if (!dotOK)
|
||||
throw syntax("Bad . in class name");
|
||||
dotOK = false;
|
||||
} else if (c == '*' || Character.isJavaIdentifierPart(c))
|
||||
dotOK = true;
|
||||
else
|
||||
break;
|
||||
next();
|
||||
}
|
||||
String className = s.substring(start, i);
|
||||
if (!dotOK)
|
||||
throw syntax("Bad class name " + className);
|
||||
return className;
|
||||
}
|
||||
|
||||
// Advance c and i to the next character, unless already at EOS.
|
||||
private void next() {
|
||||
if (c != EOS) {
|
||||
i += Character.charCount(c);
|
||||
if (i < len)
|
||||
c = s.codePointAt(i);
|
||||
else
|
||||
c = EOS;
|
||||
}
|
||||
}
|
||||
|
||||
private void skipSpace() {
|
||||
while (Character.isWhitespace(c))
|
||||
next();
|
||||
}
|
||||
|
||||
private String parseWord() {
|
||||
skipSpace();
|
||||
if (c == EOS)
|
||||
throw syntax("Expected word at end of line");
|
||||
final int start = i;
|
||||
while (c != EOS && !Character.isWhitespace(c))
|
||||
next();
|
||||
String word = s.substring(start, i);
|
||||
skipSpace();
|
||||
return word;
|
||||
}
|
||||
|
||||
private IllegalArgumentException syntax(String msg) {
|
||||
return new IllegalArgumentException(
|
||||
msg + " [" + identity + " " + s + "]");
|
||||
}
|
||||
}
|
||||
|
||||
private Map<String, Access> accessMap;
|
||||
private Properties originalProps;
|
||||
private String accessFileName;
|
||||
}
|
||||
@@ -0,0 +1,110 @@
|
||||
/*
|
||||
* 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 com.sun.jmx.remote.security;
|
||||
|
||||
import javax.management.Notification;
|
||||
import javax.management.ObjectName;
|
||||
import javax.security.auth.Subject;
|
||||
|
||||
/**
|
||||
* <p>This interface allows to control remote access to the
|
||||
* {@code addNotificationListener} and {@code removeNotificationListener}
|
||||
* methods when the notification listener parameter is of type
|
||||
* {@code NotificationListener} and also allows to control remote access
|
||||
* to the notifications being forwarded to the interested remote listeners.</p>
|
||||
*
|
||||
* <p>An implementation of this interface can be supplied to a
|
||||
* {@code JMXConnectorServer} in the environment map through the
|
||||
* {@code com.sun.jmx.remote.notification.access.controller}
|
||||
* environment map property.</p>
|
||||
*
|
||||
* @since 1.6
|
||||
*/
|
||||
public interface NotificationAccessController {
|
||||
|
||||
/**
|
||||
* This method is called when a remote
|
||||
* {@link javax.management.remote.JMXConnector} invokes the method
|
||||
* {@link javax.management.MBeanServerConnection#addNotificationListener(ObjectName,NotificationListener,NotificationFilter,Object)}.
|
||||
*
|
||||
* @param connectionId the {@code connectionId} of the remote client
|
||||
* adding the listener.
|
||||
* @param name the name of the MBean where the listener is to be added.
|
||||
* @param subject the authenticated subject representing the remote client.
|
||||
*
|
||||
* @throws SecurityException if the remote client with the supplied
|
||||
* authenticated subject does not have the rights to add a listener
|
||||
* to the supplied MBean.
|
||||
*/
|
||||
public void addNotificationListener(String connectionId,
|
||||
ObjectName name,
|
||||
Subject subject)
|
||||
throws SecurityException;
|
||||
|
||||
/**
|
||||
* This method is called when a remote
|
||||
* {@link javax.management.remote.JMXConnector} invokes the method
|
||||
* {@link javax.management.MBeanServerConnection#removeNotificationListener(ObjectName,NotificationListener)}
|
||||
* or the method
|
||||
* {@link javax.management.MBeanServerConnection#removeNotificationListener(ObjectName,NotificationListener,NotificationFilter,Object)}.
|
||||
*
|
||||
* @param connectionId the {@code connectionId} of the remote client
|
||||
* removing the listener.
|
||||
* @param name the name of the MBean where the listener is to be removed.
|
||||
* @param subject the authenticated subject representing the remote client.
|
||||
*
|
||||
* @throws SecurityException if the remote client with the supplied
|
||||
* authenticated subject does not have the rights to remove a listener
|
||||
* from the supplied MBean.
|
||||
*/
|
||||
public void removeNotificationListener(String connectionId,
|
||||
ObjectName name,
|
||||
Subject subject)
|
||||
throws SecurityException;
|
||||
|
||||
/**
|
||||
* This method is called before the
|
||||
* {@link javax.management.remote.JMXConnectorServer}
|
||||
* forwards the notification to the interested remote
|
||||
* listener represented by the authenticated subject.
|
||||
*
|
||||
* @param connectionId the {@code connectionId} of the remote client
|
||||
* receiving the notification.
|
||||
* @param name the name of the MBean forwarding the notification.
|
||||
* @param notification the notification to be forwarded to the interested
|
||||
* remote listener.
|
||||
* @param subject the authenticated subject representing the remote client.
|
||||
*
|
||||
* @throws SecurityException if the remote client with
|
||||
* the supplied authenticated subject does not have the
|
||||
* rights to receive the notification.
|
||||
*/
|
||||
public void fetchNotification(String connectionId,
|
||||
ObjectName name,
|
||||
Notification notification,
|
||||
Subject subject)
|
||||
throws SecurityException;
|
||||
}
|
||||
125
jdkSrc/jdk8/com/sun/jmx/remote/security/SubjectDelegator.java
Normal file
125
jdkSrc/jdk8/com/sun/jmx/remote/security/SubjectDelegator.java
Normal file
@@ -0,0 +1,125 @@
|
||||
/*
|
||||
* Copyright (c) 2003, 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.
|
||||
*/
|
||||
|
||||
package com.sun.jmx.remote.security;
|
||||
|
||||
import java.security.AccessController;
|
||||
import java.security.AccessControlContext;
|
||||
import java.security.Permission;
|
||||
import java.security.Principal;
|
||||
import java.security.PrivilegedAction;
|
||||
import javax.security.auth.Subject;
|
||||
|
||||
import javax.management.remote.SubjectDelegationPermission;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
public class SubjectDelegator {
|
||||
/* Return the AccessControlContext appropriate to execute an
|
||||
operation on behalf of the delegatedSubject. If the
|
||||
authenticatedAccessControlContext does not have permission to
|
||||
delegate to that subject, throw SecurityException. */
|
||||
public AccessControlContext
|
||||
delegatedContext(AccessControlContext authenticatedACC,
|
||||
Subject delegatedSubject,
|
||||
boolean removeCallerContext)
|
||||
throws SecurityException {
|
||||
|
||||
if (System.getSecurityManager() != null && authenticatedACC == null) {
|
||||
throw new SecurityException("Illegal AccessControlContext: null");
|
||||
}
|
||||
|
||||
// Check if the subject delegation permission allows the
|
||||
// authenticated subject to assume the identity of each
|
||||
// principal in the delegated subject
|
||||
//
|
||||
Collection<Principal> ps = getSubjectPrincipals(delegatedSubject);
|
||||
final Collection<Permission> permissions = new ArrayList<>(ps.size());
|
||||
for(Principal p : ps) {
|
||||
final String pname = p.getClass().getName() + "." + p.getName();
|
||||
permissions.add(new SubjectDelegationPermission(pname));
|
||||
}
|
||||
PrivilegedAction<Void> action =
|
||||
new PrivilegedAction<Void>() {
|
||||
public Void run() {
|
||||
for (Permission sdp : permissions) {
|
||||
AccessController.checkPermission(sdp);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
};
|
||||
AccessController.doPrivileged(action, authenticatedACC);
|
||||
|
||||
return getDelegatedAcc(delegatedSubject, removeCallerContext);
|
||||
}
|
||||
|
||||
private AccessControlContext getDelegatedAcc(Subject delegatedSubject, boolean removeCallerContext) {
|
||||
if (removeCallerContext) {
|
||||
return JMXSubjectDomainCombiner.getDomainCombinerContext(delegatedSubject);
|
||||
} else {
|
||||
return JMXSubjectDomainCombiner.getContext(delegatedSubject);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the connector server creator can assume the identity of each
|
||||
* principal in the authenticated subject, i.e. check if the connector
|
||||
* server creator codebase contains a subject delegation permission for
|
||||
* each principal present in the authenticated subject.
|
||||
*
|
||||
* @return {@code true} if the connector server creator can delegate to all
|
||||
* the authenticated principals in the subject. Otherwise, {@code false}.
|
||||
*/
|
||||
public static synchronized boolean
|
||||
checkRemoveCallerContext(Subject subject) {
|
||||
try {
|
||||
for (Principal p : getSubjectPrincipals(subject)) {
|
||||
final String pname =
|
||||
p.getClass().getName() + "." + p.getName();
|
||||
final Permission sdp =
|
||||
new SubjectDelegationPermission(pname);
|
||||
AccessController.checkPermission(sdp);
|
||||
}
|
||||
} catch (SecurityException e) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the {@linkplain Subject} principals
|
||||
* @param subject The subject
|
||||
* @return If the {@code Subject} is immutable it will return the principals directly.
|
||||
* If the {@code Subject} is mutable it will create an unmodifiable copy.
|
||||
*/
|
||||
private static Collection<Principal> getSubjectPrincipals(Subject subject) {
|
||||
if (subject.isReadOnly()) {
|
||||
return subject.getPrincipals();
|
||||
}
|
||||
|
||||
List<Principal> principals = Arrays.asList(subject.getPrincipals().toArray(new Principal[0]));
|
||||
return Collections.unmodifiableList(principals);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
* 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 javax.management.loading.ClassLoaderRepository;
|
||||
|
||||
public class ClassLoaderWithRepository extends ClassLoader {
|
||||
public ClassLoaderWithRepository(ClassLoaderRepository clr,
|
||||
ClassLoader cl2) {
|
||||
|
||||
if (clr == null) throw new
|
||||
IllegalArgumentException("Null ClassLoaderRepository object.");
|
||||
|
||||
repository = clr;
|
||||
this.cl2 = cl2;
|
||||
}
|
||||
|
||||
protected Class<?> findClass(String name) throws ClassNotFoundException {
|
||||
Class<?> cls;
|
||||
try {
|
||||
cls = repository.loadClass(name);
|
||||
} catch (ClassNotFoundException cne) {
|
||||
if (cl2 != null) {
|
||||
return cl2.loadClass(name);
|
||||
} else {
|
||||
throw cne;
|
||||
}
|
||||
}
|
||||
|
||||
if(!cls.getName().equals(name)){
|
||||
if (cl2 != null) {
|
||||
return cl2.loadClass(name);
|
||||
} else {
|
||||
throw new ClassNotFoundException(name);
|
||||
}
|
||||
}
|
||||
return cls;
|
||||
}
|
||||
|
||||
private ClassLoaderRepository repository;
|
||||
private ClassLoader cl2;
|
||||
}
|
||||
246
jdkSrc/jdk8/com/sun/jmx/remote/util/ClassLogger.java
Normal file
246
jdkSrc/jdk8/com/sun/jmx/remote/util/ClassLogger.java
Normal file
@@ -0,0 +1,246 @@
|
||||
/*
|
||||
* 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.util.logging.Logger;
|
||||
|
||||
public class ClassLogger {
|
||||
|
||||
private static final boolean ok;
|
||||
private final String className;
|
||||
private final Logger logger;
|
||||
|
||||
static {
|
||||
/* We attempt to work even if we are running in J2SE 1.3, where
|
||||
there is no java.util.logging. The technique we use here is
|
||||
not strictly portable, but it does work with Sun's J2SE 1.3
|
||||
at least. This is just a best effort: the Right Thing is for
|
||||
people to use at least J2SE 1.4. */
|
||||
boolean loaded = false;
|
||||
try {
|
||||
Class<?> c = java.util.logging.Logger.class;
|
||||
loaded = true;
|
||||
} catch (Error e) {
|
||||
// OK.
|
||||
// java.util.logger package is not available in this jvm.
|
||||
}
|
||||
ok = loaded;
|
||||
}
|
||||
|
||||
public ClassLogger(String subsystem, String className) {
|
||||
if (ok)
|
||||
logger = Logger.getLogger(subsystem);
|
||||
else
|
||||
logger = null;
|
||||
this.className = className;
|
||||
}
|
||||
|
||||
public final boolean traceOn() {
|
||||
return finerOn();
|
||||
}
|
||||
|
||||
public final boolean debugOn() {
|
||||
return finestOn();
|
||||
}
|
||||
|
||||
public final boolean warningOn() {
|
||||
return ok && logger.isLoggable(java.util.logging.Level.WARNING);
|
||||
}
|
||||
|
||||
public final boolean infoOn() {
|
||||
return ok && logger.isLoggable(java.util.logging.Level.INFO);
|
||||
}
|
||||
|
||||
public final boolean configOn() {
|
||||
return ok && logger.isLoggable(java.util.logging.Level.CONFIG);
|
||||
}
|
||||
|
||||
public final boolean fineOn() {
|
||||
return ok && logger.isLoggable(java.util.logging.Level.FINE);
|
||||
}
|
||||
|
||||
public final boolean finerOn() {
|
||||
return ok && logger.isLoggable(java.util.logging.Level.FINER);
|
||||
}
|
||||
|
||||
public final boolean finestOn() {
|
||||
return ok && logger.isLoggable(java.util.logging.Level.FINEST);
|
||||
}
|
||||
|
||||
public final void debug(String func, String msg) {
|
||||
finest(func,msg);
|
||||
}
|
||||
|
||||
public final void debug(String func, Throwable t) {
|
||||
finest(func,t);
|
||||
}
|
||||
|
||||
public final void debug(String func, String msg, Throwable t) {
|
||||
finest(func,msg,t);
|
||||
}
|
||||
|
||||
public final void trace(String func, String msg) {
|
||||
finer(func,msg);
|
||||
}
|
||||
|
||||
public final void trace(String func, Throwable t) {
|
||||
finer(func,t);
|
||||
}
|
||||
|
||||
public final void trace(String func, String msg, Throwable t) {
|
||||
finer(func,msg,t);
|
||||
}
|
||||
|
||||
public final void error(String func, String msg) {
|
||||
severe(func,msg);
|
||||
}
|
||||
|
||||
public final void error(String func, Throwable t) {
|
||||
severe(func,t);
|
||||
}
|
||||
|
||||
public final void error(String func, String msg, Throwable t) {
|
||||
severe(func,msg,t);
|
||||
}
|
||||
|
||||
public final void finest(String func, String msg) {
|
||||
if (ok)
|
||||
logger.logp(java.util.logging.Level.FINEST, className, func, msg);
|
||||
}
|
||||
|
||||
public final void finest(String func, Throwable t) {
|
||||
if (ok)
|
||||
logger.logp(java.util.logging.Level.FINEST, className, func,
|
||||
t.toString(), t);
|
||||
}
|
||||
|
||||
public final void finest(String func, String msg, Throwable t) {
|
||||
if (ok)
|
||||
logger.logp(java.util.logging.Level.FINEST, className, func, msg,
|
||||
t);
|
||||
}
|
||||
|
||||
public final void finer(String func, String msg) {
|
||||
if (ok)
|
||||
logger.logp(java.util.logging.Level.FINER, className, func, msg);
|
||||
}
|
||||
|
||||
public final void finer(String func, Throwable t) {
|
||||
if (ok)
|
||||
logger.logp(java.util.logging.Level.FINER, className, func,
|
||||
t.toString(), t);
|
||||
}
|
||||
|
||||
public final void finer(String func, String msg, Throwable t) {
|
||||
if (ok)
|
||||
logger.logp(java.util.logging.Level.FINER, className, func, msg,t);
|
||||
}
|
||||
|
||||
public final void fine(String func, String msg) {
|
||||
if (ok)
|
||||
logger.logp(java.util.logging.Level.FINE, className, func, msg);
|
||||
}
|
||||
|
||||
public final void fine(String func, Throwable t) {
|
||||
if (ok)
|
||||
logger.logp(java.util.logging.Level.FINE, className, func,
|
||||
t.toString(), t);
|
||||
}
|
||||
|
||||
public final void fine(String func, String msg, Throwable t) {
|
||||
if (ok)
|
||||
logger.logp(java.util.logging.Level.FINE, className, func, msg,
|
||||
t);
|
||||
}
|
||||
|
||||
public final void config(String func, String msg) {
|
||||
if (ok)
|
||||
logger.logp(java.util.logging.Level.CONFIG, className, func, msg);
|
||||
}
|
||||
|
||||
public final void config(String func, Throwable t) {
|
||||
if (ok)
|
||||
logger.logp(java.util.logging.Level.CONFIG, className, func,
|
||||
t.toString(), t);
|
||||
}
|
||||
|
||||
public final void config(String func, String msg, Throwable t) {
|
||||
if (ok)
|
||||
logger.logp(java.util.logging.Level.CONFIG, className, func, msg,
|
||||
t);
|
||||
}
|
||||
|
||||
public final void info(String func, String msg) {
|
||||
if (ok)
|
||||
logger.logp(java.util.logging.Level.INFO, className, func, msg);
|
||||
}
|
||||
|
||||
public final void info(String func, Throwable t) {
|
||||
if (ok)
|
||||
logger.logp(java.util.logging.Level.INFO, className, func,
|
||||
t.toString(), t);
|
||||
}
|
||||
|
||||
public final void info(String func, String msg, Throwable t) {
|
||||
if (ok)
|
||||
logger.logp(java.util.logging.Level.INFO, className, func, msg,
|
||||
t);
|
||||
}
|
||||
|
||||
public final void warning(String func, String msg) {
|
||||
if (ok)
|
||||
logger.logp(java.util.logging.Level.WARNING, className, func, msg);
|
||||
}
|
||||
|
||||
public final void warning(String func, Throwable t) {
|
||||
if (ok)
|
||||
logger.logp(java.util.logging.Level.WARNING, className, func,
|
||||
t.toString(), t);
|
||||
}
|
||||
|
||||
public final void warning(String func, String msg, Throwable t) {
|
||||
if (ok)
|
||||
logger.logp(java.util.logging.Level.WARNING, className, func, msg,
|
||||
t);
|
||||
}
|
||||
|
||||
public final void severe(String func, String msg) {
|
||||
if (ok)
|
||||
logger.logp(java.util.logging.Level.SEVERE, className, func, msg);
|
||||
}
|
||||
|
||||
public final void severe(String func, Throwable t) {
|
||||
if (ok)
|
||||
logger.logp(java.util.logging.Level.SEVERE, className, func,
|
||||
t.toString(), t);
|
||||
}
|
||||
|
||||
public final void severe(String func, String msg, Throwable t) {
|
||||
if (ok)
|
||||
logger.logp(java.util.logging.Level.SEVERE, className, func, msg,
|
||||
t);
|
||||
}
|
||||
}
|
||||
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");
|
||||
}
|
||||
51
jdkSrc/jdk8/com/sun/jmx/remote/util/OrderClassLoaders.java
Normal file
51
jdkSrc/jdk8/com/sun/jmx/remote/util/OrderClassLoaders.java
Normal file
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
* 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 com.sun.jmx.remote.util;
|
||||
|
||||
import sun.reflect.misc.ReflectUtil;
|
||||
|
||||
public class OrderClassLoaders extends ClassLoader {
|
||||
public OrderClassLoaders(ClassLoader cl1, ClassLoader cl2) {
|
||||
super(cl1);
|
||||
|
||||
this.cl2 = cl2;
|
||||
}
|
||||
|
||||
protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException {
|
||||
ReflectUtil.checkPackageAccess(name);
|
||||
try {
|
||||
return super.loadClass(name, resolve);
|
||||
} catch (ClassNotFoundException cne) {
|
||||
if (cl2 != null) {
|
||||
return cl2.loadClass(name);
|
||||
} else {
|
||||
throw cne;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private ClassLoader cl2;
|
||||
}
|
||||
757
jdkSrc/jdk8/com/sun/jmx/snmp/BerDecoder.java
Normal file
757
jdkSrc/jdk8/com/sun/jmx/snmp/BerDecoder.java
Normal file
@@ -0,0 +1,757 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2007, 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.snmp;
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* The <CODE>BerDecoder</CODE> class is used for decoding
|
||||
* BER-encoded data.
|
||||
*
|
||||
* A <CODE>BerDecoder</CODE> needs to be set up with the byte string containing
|
||||
* the encoding. It maintains a current position in the byte string.
|
||||
*
|
||||
* Methods allows to fetch integer, string, OID, etc., from the current
|
||||
* position. After a fetch the current position is moved forward.
|
||||
*
|
||||
* A fetch throws a <CODE>BerException</CODE> if the encoding is not of the
|
||||
* expected type.
|
||||
*
|
||||
* <p><b>This API is a Sun Microsystems internal API and is subject
|
||||
* to change without notice.</b></p>
|
||||
*
|
||||
* @since 1.5
|
||||
*/
|
||||
|
||||
public class BerDecoder {
|
||||
|
||||
/**
|
||||
* Constructs a new decoder and attaches it to the specified byte string.
|
||||
*
|
||||
* @param b The byte string containing the encoded data.
|
||||
*/
|
||||
|
||||
public BerDecoder(byte b[]) {
|
||||
bytes = b ;
|
||||
reset() ;
|
||||
}
|
||||
|
||||
public void reset() {
|
||||
next = 0 ;
|
||||
stackTop = 0 ;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch an integer.
|
||||
*
|
||||
* @return The decoded integer.
|
||||
*
|
||||
* @exception BerException Current position does not point to an integer.
|
||||
*/
|
||||
|
||||
public int fetchInteger() throws BerException {
|
||||
return fetchInteger(IntegerTag) ;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Fetch an integer with the specified tag.
|
||||
*
|
||||
* @param tag The expected tag.
|
||||
*
|
||||
* @return The decoded integer.
|
||||
*
|
||||
* @exception BerException Current position does not point to an integer
|
||||
* or the tag is not the expected one.
|
||||
*/
|
||||
|
||||
public int fetchInteger(int tag) throws BerException {
|
||||
int result = 0 ;
|
||||
final int backup = next ;
|
||||
try {
|
||||
if (fetchTag() != tag) {
|
||||
throw new BerException() ;
|
||||
}
|
||||
result = fetchIntegerValue() ;
|
||||
}
|
||||
catch(BerException e) {
|
||||
next = backup ;
|
||||
throw e ;
|
||||
}
|
||||
|
||||
return result ;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Fetch an integer and return a long value.
|
||||
*
|
||||
* @return The decoded integer.
|
||||
*
|
||||
* @exception BerException Current position does not point to an integer.
|
||||
*/
|
||||
|
||||
public long fetchIntegerAsLong() throws BerException {
|
||||
return fetchIntegerAsLong(IntegerTag) ;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Fetch an integer with the specified tag and return a long value.
|
||||
*
|
||||
* @param tag The expected tag.
|
||||
*
|
||||
* @return The decoded integer.
|
||||
*
|
||||
* @exception BerException Current position does not point to an integer
|
||||
* or the tag is not the expected one.
|
||||
*/
|
||||
|
||||
public long fetchIntegerAsLong(int tag) throws BerException {
|
||||
long result = 0 ;
|
||||
final int backup = next ;
|
||||
try {
|
||||
if (fetchTag() != tag) {
|
||||
throw new BerException() ;
|
||||
}
|
||||
result = fetchIntegerValueAsLong() ;
|
||||
}
|
||||
catch(BerException e) {
|
||||
next = backup ;
|
||||
throw e ;
|
||||
}
|
||||
|
||||
return result ;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Fetch an octet string.
|
||||
*
|
||||
* @return The decoded string.
|
||||
*
|
||||
* @exception BerException Current position does not point to an octet string.
|
||||
*/
|
||||
|
||||
public byte[] fetchOctetString() throws BerException {
|
||||
return fetchOctetString(OctetStringTag) ;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Fetch an octet string with a specified tag.
|
||||
*
|
||||
* @param tag The expected tag.
|
||||
*
|
||||
* @return The decoded string.
|
||||
*
|
||||
* @exception BerException Current position does not point to an octet string
|
||||
* or the tag is not the expected one.
|
||||
*/
|
||||
|
||||
public byte[] fetchOctetString(int tag) throws BerException {
|
||||
byte[] result = null ;
|
||||
final int backup = next ;
|
||||
try {
|
||||
if (fetchTag() != tag) {
|
||||
throw new BerException() ;
|
||||
}
|
||||
result = fetchStringValue() ;
|
||||
}
|
||||
catch(BerException e) {
|
||||
next = backup ;
|
||||
throw e ;
|
||||
}
|
||||
|
||||
return result ;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Fetch an object identifier.
|
||||
*
|
||||
* @return The decoded object identifier as an array of long.
|
||||
*/
|
||||
|
||||
public long[] fetchOid() throws BerException {
|
||||
return fetchOid(OidTag) ;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Fetch an object identifier with a specified tag.
|
||||
*
|
||||
* @param tag The expected tag.
|
||||
*
|
||||
* @return The decoded object identifier as an array of long.
|
||||
*
|
||||
* @exception BerException Current position does not point to an oid
|
||||
* or the tag is not the expected one.
|
||||
*/
|
||||
|
||||
public long[] fetchOid(int tag) throws BerException {
|
||||
long[] result = null ;
|
||||
final int backup = next ;
|
||||
try {
|
||||
if (fetchTag() != tag) {
|
||||
throw new BerException() ;
|
||||
}
|
||||
result = fetchOidValue() ;
|
||||
}
|
||||
catch(BerException e) {
|
||||
next = backup ;
|
||||
throw e ;
|
||||
}
|
||||
|
||||
return result ;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Fetch a <CODE>NULL</CODE> value.
|
||||
*
|
||||
* @exception BerException Current position does not point to <CODE>NULL</CODE> value.
|
||||
*/
|
||||
|
||||
public void fetchNull() throws BerException {
|
||||
fetchNull(NullTag) ;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Fetch a <CODE>NULL</CODE> value with a specified tag.
|
||||
*
|
||||
* @param tag The expected tag.
|
||||
*
|
||||
* @exception BerException Current position does not point to
|
||||
* <CODE>NULL</CODE> value or the tag is not the expected one.
|
||||
*/
|
||||
|
||||
public void fetchNull(int tag) throws BerException {
|
||||
final int backup = next ;
|
||||
try {
|
||||
if (fetchTag() != tag) {
|
||||
throw new BerException() ;
|
||||
}
|
||||
final int length = fetchLength();
|
||||
if (length != 0) throw new BerException();
|
||||
}
|
||||
catch(BerException e) {
|
||||
next = backup ;
|
||||
throw e ;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Fetch an <CODE>ANY</CODE> value. In fact, this method does not decode anything
|
||||
* it simply returns the next TLV as an array of bytes.
|
||||
*
|
||||
* @return The TLV as a byte array.
|
||||
*
|
||||
* @exception BerException The next TLV is really badly encoded...
|
||||
*/
|
||||
|
||||
public byte[] fetchAny() throws BerException {
|
||||
byte[] result = null ;
|
||||
final int backup = next ;
|
||||
try {
|
||||
final int tag = fetchTag() ;
|
||||
final int contentLength = fetchLength() ;
|
||||
if (contentLength < 0) throw new BerException() ;
|
||||
final int tlvLength = next + contentLength - backup ;
|
||||
if (contentLength > (bytes.length - next))
|
||||
throw new IndexOutOfBoundsException("Decoded length exceeds buffer");
|
||||
final byte[] data = new byte[tlvLength] ;
|
||||
java.lang.System.arraycopy(bytes,backup,data,0,tlvLength);
|
||||
// for (int i = 0 ; i < tlvLength ; i++) {
|
||||
// data[i] = bytes[backup + i] ;
|
||||
// }
|
||||
next = next + contentLength ;
|
||||
result = data;
|
||||
}
|
||||
catch(IndexOutOfBoundsException e) {
|
||||
next = backup ;
|
||||
throw new BerException() ;
|
||||
}
|
||||
// catch(Error e) {
|
||||
// debug("fetchAny: Error decoding BER: " + e);
|
||||
// throw e;
|
||||
// }
|
||||
|
||||
return result ;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Fetch an <CODE>ANY</CODE> value with a specific tag.
|
||||
*
|
||||
* @param tag The expected tag.
|
||||
*
|
||||
* @return The TLV as a byte array.
|
||||
*
|
||||
* @exception BerException The next TLV is really badly encoded...
|
||||
*/
|
||||
|
||||
public byte[] fetchAny(int tag) throws BerException {
|
||||
if (getTag() != tag) {
|
||||
throw new BerException() ;
|
||||
}
|
||||
return fetchAny() ;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Fetch a sequence header.
|
||||
* The decoder computes the end position of the sequence and push it
|
||||
* on its stack.
|
||||
*
|
||||
* @exception BerException Current position does not point to a sequence header.
|
||||
*/
|
||||
|
||||
public void openSequence() throws BerException {
|
||||
openSequence(SequenceTag) ;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Fetch a sequence header with a specific tag.
|
||||
*
|
||||
* @param tag The expected tag.
|
||||
*
|
||||
* @exception BerException Current position does not point to a sequence header
|
||||
* or the tag is not the expected one.
|
||||
*/
|
||||
|
||||
public void openSequence(int tag) throws BerException {
|
||||
final int backup = next ;
|
||||
try {
|
||||
if (fetchTag() != tag) {
|
||||
throw new BerException() ;
|
||||
}
|
||||
final int l = fetchLength() ;
|
||||
if (l < 0) throw new BerException();
|
||||
if (l > (bytes.length - next)) throw new BerException();
|
||||
stackBuf[stackTop++] = next + l ;
|
||||
}
|
||||
catch(BerException e) {
|
||||
next = backup ;
|
||||
throw e ;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Close a sequence.
|
||||
* The decode pull the stack and verifies that the current position
|
||||
* matches with the calculated end of the sequence. If not it throws
|
||||
* an exception.
|
||||
*
|
||||
* @exception BerException The sequence is not expected to finish here.
|
||||
*/
|
||||
|
||||
public void closeSequence() throws BerException {
|
||||
if (stackBuf[stackTop - 1] == next) {
|
||||
stackTop-- ;
|
||||
}
|
||||
else {
|
||||
throw new BerException() ;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return <CODE>true</CODE> if the end of the current sequence is not reached.
|
||||
* When this method returns <CODE>false</CODE>, <CODE>closeSequence</CODE> can (and must) be
|
||||
* invoked.
|
||||
*
|
||||
* @return <CODE>true</CODE> if there is still some data in the sequence.
|
||||
*/
|
||||
|
||||
public boolean cannotCloseSequence() {
|
||||
return (next < stackBuf[stackTop - 1]) ;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the tag of the data at the current position.
|
||||
* Current position is unchanged.
|
||||
*
|
||||
* @return The next tag.
|
||||
*/
|
||||
|
||||
public int getTag() throws BerException {
|
||||
int result = 0 ;
|
||||
final int backup = next ;
|
||||
try {
|
||||
result = fetchTag() ;
|
||||
}
|
||||
finally {
|
||||
next = backup ;
|
||||
}
|
||||
|
||||
return result ;
|
||||
}
|
||||
|
||||
|
||||
|
||||
public String toString() {
|
||||
final StringBuffer result = new StringBuffer(bytes.length * 2) ;
|
||||
for (int i = 0 ; i < bytes.length ; i++) {
|
||||
final int b = (bytes[i] > 0) ? bytes[i] : bytes[i] + 256 ;
|
||||
if (i == next) {
|
||||
result.append("(") ;
|
||||
}
|
||||
result.append(Character.forDigit(b / 16, 16)) ;
|
||||
result.append(Character.forDigit(b % 16, 16)) ;
|
||||
if (i == next) {
|
||||
result.append(")") ;
|
||||
}
|
||||
}
|
||||
if (bytes.length == next) {
|
||||
result.append("()") ;
|
||||
}
|
||||
|
||||
return new String(result) ;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Some standard tags
|
||||
//
|
||||
public final static int BooleanTag = 1 ;
|
||||
public final static int IntegerTag = 2 ;
|
||||
public final static int OctetStringTag = 4 ;
|
||||
public final static int NullTag = 5 ;
|
||||
public final static int OidTag = 6 ;
|
||||
public final static int SequenceTag = 0x30 ;
|
||||
|
||||
|
||||
|
||||
|
||||
////////////////////////// PRIVATE ///////////////////////////////
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Fetch a tag and move the current position forward.
|
||||
*
|
||||
* @return The tag
|
||||
*/
|
||||
|
||||
private final int fetchTag() throws BerException {
|
||||
int result = 0 ;
|
||||
final int backup = next ;
|
||||
|
||||
try {
|
||||
final byte b0 = bytes[next++] ;
|
||||
result = (b0 >= 0) ? b0 : b0 + 256 ;
|
||||
if ((result & 31) == 31) {
|
||||
while ((bytes[next] & 128) != 0) {
|
||||
result = result << 7 ;
|
||||
result = result | (bytes[next++] & 127);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch(IndexOutOfBoundsException e) {
|
||||
next = backup ;
|
||||
throw new BerException() ;
|
||||
}
|
||||
|
||||
return result ;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Fetch a length and move the current position forward.
|
||||
*
|
||||
* @return The length
|
||||
*/
|
||||
|
||||
private final int fetchLength() throws BerException {
|
||||
int result = 0 ;
|
||||
final int backup = next ;
|
||||
|
||||
try {
|
||||
final byte b0 = bytes[next++] ;
|
||||
if (b0 >= 0) {
|
||||
result = b0 ;
|
||||
}
|
||||
else {
|
||||
for (int c = 128 + b0 ; c > 0 ; c--) {
|
||||
final byte bX = bytes[next++] ;
|
||||
result = result << 8 ;
|
||||
result = result | ((bX >= 0) ? bX : bX+256) ;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch(IndexOutOfBoundsException e) {
|
||||
next = backup ;
|
||||
throw new BerException() ;
|
||||
}
|
||||
|
||||
return result ;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Fetch an integer value and move the current position forward.
|
||||
*
|
||||
* @return The integer
|
||||
*/
|
||||
|
||||
private int fetchIntegerValue() throws BerException {
|
||||
int result = 0 ;
|
||||
final int backup = next ;
|
||||
|
||||
try {
|
||||
final int length = fetchLength() ;
|
||||
if (length <= 0) throw new BerException() ;
|
||||
if (length > (bytes.length - next)) throw
|
||||
new IndexOutOfBoundsException("Decoded length exceeds buffer");
|
||||
final int end = next + length ;
|
||||
result = bytes[next++] ;
|
||||
while (next < end) {
|
||||
final byte b = bytes[next++] ;
|
||||
if (b < 0) {
|
||||
result = (result << 8) | (256 + b) ;
|
||||
}
|
||||
else {
|
||||
result = (result << 8) | b ;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch(BerException e) {
|
||||
next = backup ;
|
||||
throw e ;
|
||||
}
|
||||
catch(IndexOutOfBoundsException e) {
|
||||
next = backup ;
|
||||
throw new BerException() ;
|
||||
}
|
||||
catch(ArithmeticException e) {
|
||||
next = backup ;
|
||||
throw new BerException() ;
|
||||
}
|
||||
return result ;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Fetch an integer value and return a long value.
|
||||
* FIX ME: someday we could have only on fetchIntegerValue() which always
|
||||
* returns a long value.
|
||||
*
|
||||
* @return The integer
|
||||
*/
|
||||
|
||||
private final long fetchIntegerValueAsLong() throws BerException {
|
||||
long result = 0 ;
|
||||
final int backup = next ;
|
||||
|
||||
try {
|
||||
final int length = fetchLength() ;
|
||||
if (length <= 0) throw new BerException() ;
|
||||
if (length > (bytes.length - next)) throw
|
||||
new IndexOutOfBoundsException("Decoded length exceeds buffer");
|
||||
|
||||
final int end = next + length ;
|
||||
result = bytes[next++] ;
|
||||
while (next < end) {
|
||||
final byte b = bytes[next++] ;
|
||||
if (b < 0) {
|
||||
result = (result << 8) | (256 + b) ;
|
||||
}
|
||||
else {
|
||||
result = (result << 8) | b ;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch(BerException e) {
|
||||
next = backup ;
|
||||
throw e ;
|
||||
}
|
||||
catch(IndexOutOfBoundsException e) {
|
||||
next = backup ;
|
||||
throw new BerException() ;
|
||||
}
|
||||
catch(ArithmeticException e) {
|
||||
next = backup ;
|
||||
throw new BerException() ;
|
||||
}
|
||||
return result ;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Fetch a byte string and move the current position forward.
|
||||
*
|
||||
* @return The byte string
|
||||
*/
|
||||
|
||||
private byte[] fetchStringValue() throws BerException {
|
||||
byte[] result = null ;
|
||||
final int backup = next ;
|
||||
|
||||
try {
|
||||
final int length = fetchLength() ;
|
||||
if (length < 0) throw new BerException() ;
|
||||
if (length > (bytes.length - next))
|
||||
throw new IndexOutOfBoundsException("Decoded length exceeds buffer");
|
||||
final byte data[] = new byte[length] ;
|
||||
java.lang.System.arraycopy(bytes,next,data,0,length);
|
||||
next += length;
|
||||
// int i = 0 ;
|
||||
// while (i < length) {
|
||||
// result[i++] = bytes[next++] ;
|
||||
// }
|
||||
result = data;
|
||||
}
|
||||
catch(BerException e) {
|
||||
next = backup ;
|
||||
throw e ;
|
||||
}
|
||||
catch(IndexOutOfBoundsException e) {
|
||||
next = backup ;
|
||||
throw new BerException() ;
|
||||
}
|
||||
catch(ArithmeticException e) {
|
||||
next = backup ;
|
||||
throw new BerException() ;
|
||||
}
|
||||
// catch(Error e) {
|
||||
// debug("fetchStringValue: Error decoding BER: " + e);
|
||||
// throw e;
|
||||
// }
|
||||
|
||||
return result ;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Fetch an oid and move the current position forward.
|
||||
*
|
||||
* @return The oid
|
||||
*/
|
||||
|
||||
private final long[] fetchOidValue() throws BerException {
|
||||
long[] result = null ;
|
||||
final int backup = next ;
|
||||
|
||||
try {
|
||||
final int length = fetchLength() ;
|
||||
if (length <= 0) throw new BerException() ;
|
||||
if (length > (bytes.length - next))
|
||||
throw new IndexOutOfBoundsException("Decoded length exceeds buffer");
|
||||
// Count how many bytes have their 8th bit to 0
|
||||
// -> this gives the number of components in the oid
|
||||
int subidCount = 2 ;
|
||||
for (int i = 1 ; i < length ; i++) {
|
||||
if ((bytes[next + i] & 0x80) == 0) {
|
||||
subidCount++ ;
|
||||
}
|
||||
}
|
||||
final int datalen = subidCount;
|
||||
final long[] data = new long[datalen];
|
||||
final byte b0 = bytes[next++] ;
|
||||
|
||||
// bugId 4641746
|
||||
// The 8th bit of the first byte should always be set to 0
|
||||
if (b0 < 0) throw new BerException();
|
||||
|
||||
// bugId 4641746
|
||||
// The first sub Id cannot be greater than 2
|
||||
final long lb0 = b0 / 40 ;
|
||||
if (lb0 > 2) throw new BerException();
|
||||
|
||||
final long lb1 = b0 % 40;
|
||||
data[0] = lb0 ;
|
||||
data[1] = lb1 ;
|
||||
int i = 2 ;
|
||||
while (i < datalen) {
|
||||
long subid = 0 ;
|
||||
byte b = bytes[next++] ;
|
||||
while ((b & 0x80) != 0) {
|
||||
subid = (subid << 7) | (b & 0x7f) ;
|
||||
// bugId 4654674
|
||||
if (subid < 0) throw new BerException();
|
||||
b = bytes[next++] ;
|
||||
}
|
||||
subid = (subid << 7) | b ;
|
||||
// bugId 4654674
|
||||
if (subid < 0) throw new BerException();
|
||||
data[i++] = subid ;
|
||||
}
|
||||
result = data;
|
||||
}
|
||||
catch(BerException e) {
|
||||
next = backup ;
|
||||
throw e ;
|
||||
}
|
||||
catch(IndexOutOfBoundsException e) {
|
||||
next = backup ;
|
||||
throw new BerException() ;
|
||||
}
|
||||
// catch(Error e) {
|
||||
// debug("fetchOidValue: Error decoding BER: " + e);
|
||||
// throw e;
|
||||
// }
|
||||
|
||||
return result ;
|
||||
}
|
||||
|
||||
// private static final void debug(String str) {
|
||||
// System.out.println(str);
|
||||
// }
|
||||
|
||||
//
|
||||
// This is the byte array containing the encoding.
|
||||
//
|
||||
private final byte bytes[];
|
||||
|
||||
//
|
||||
// This is the current location. It is the next byte
|
||||
// to be decoded. It's an index in bytes[].
|
||||
//
|
||||
private int next = 0 ;
|
||||
|
||||
//
|
||||
// This is the stack where end of sequences are kept.
|
||||
// A value is computed and pushed in it each time openSequence()
|
||||
// is invoked.
|
||||
// A value is pulled and checked each time closeSequence() is called.
|
||||
//
|
||||
private final int stackBuf[] = new int[200] ;
|
||||
private int stackTop = 0 ;
|
||||
|
||||
}
|
||||
477
jdkSrc/jdk8/com/sun/jmx/snmp/BerEncoder.java
Normal file
477
jdkSrc/jdk8/com/sun/jmx/snmp/BerEncoder.java
Normal file
@@ -0,0 +1,477 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2007, 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.snmp;
|
||||
|
||||
|
||||
/**
|
||||
* The <CODE>BerEncoder</CODE> class is used for encoding data using BER.
|
||||
*
|
||||
* A <CODE>BerEncoder</CODE> needs to be set up with a byte buffer. The encoded
|
||||
* data are stored in this byte buffer.
|
||||
* <P>
|
||||
* NOTE : the buffer is filled from end to start. This means the caller
|
||||
* needs to encode its data in the reverse order.
|
||||
*
|
||||
*
|
||||
* <p><b>This API is a Sun Microsystems internal API and is subject
|
||||
* to change without notice.</b></p>
|
||||
*
|
||||
* @since 1.5
|
||||
*/
|
||||
|
||||
public class BerEncoder {
|
||||
|
||||
/**
|
||||
* Constructs a new encoder and attaches it to the specified byte string.
|
||||
*
|
||||
* @param b The byte string containing the encoded data.
|
||||
*/
|
||||
|
||||
public BerEncoder(byte b[]) {
|
||||
bytes = b ;
|
||||
start = b.length ;
|
||||
stackTop = 0 ;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Trim the encoding data and returns the length of the encoding.
|
||||
*
|
||||
* The encoder does backward encoding : so the bytes buffer is
|
||||
* filled from end to start. The encoded data must be shift before
|
||||
* the buffer can be used. This is the purpose of the <CODE>trim</CODE> method.
|
||||
*
|
||||
* After a call to the <CODE>trim</CODE> method, the encoder is reinitialized and <CODE>putXXX</CODE>
|
||||
* overwrite any existing encoded data.
|
||||
*
|
||||
* @return The length of the encoded data.
|
||||
*/
|
||||
|
||||
public int trim() {
|
||||
final int result = bytes.length - start ;
|
||||
|
||||
// for (int i = start ; i < bytes.length ; i++) {
|
||||
// bytes[i-start] = bytes[i] ;
|
||||
// }
|
||||
if (result > 0)
|
||||
java.lang.System.arraycopy(bytes,start,bytes,0,result);
|
||||
|
||||
start = bytes.length ;
|
||||
stackTop = 0 ;
|
||||
|
||||
return result ;
|
||||
}
|
||||
|
||||
/**
|
||||
* Put an integer.
|
||||
*
|
||||
* @param v The integer to encode.
|
||||
*/
|
||||
|
||||
public void putInteger(int v) {
|
||||
putInteger(v, IntegerTag) ;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Put an integer with the specified tag.
|
||||
*
|
||||
* @param v The integer to encode.
|
||||
* @param tag The tag to encode.
|
||||
*/
|
||||
|
||||
public void putInteger(int v, int tag) {
|
||||
putIntegerValue(v) ;
|
||||
putTag(tag) ;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Put an integer expressed as a long.
|
||||
*
|
||||
* @param v The long to encode.
|
||||
*/
|
||||
|
||||
public void putInteger(long v) {
|
||||
putInteger(v, IntegerTag) ;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Put an integer expressed as a long with the specified tag.
|
||||
*
|
||||
* @param v The long to encode
|
||||
* @param tag The tag to encode.
|
||||
*/
|
||||
|
||||
public void putInteger(long v, int tag) {
|
||||
putIntegerValue(v) ;
|
||||
putTag(tag) ;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Put an octet string.
|
||||
*
|
||||
* @param s The bytes to encode
|
||||
*/
|
||||
|
||||
public void putOctetString(byte[] s) {
|
||||
putOctetString(s, OctetStringTag) ;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Put an octet string with a specified tag.
|
||||
*
|
||||
* @param s The bytes to encode
|
||||
* @param tag The tag to encode.
|
||||
*/
|
||||
|
||||
public void putOctetString(byte[] s, int tag) {
|
||||
putStringValue(s) ;
|
||||
putTag(tag) ;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Put an object identifier.
|
||||
*
|
||||
* @param s The oid to encode.
|
||||
*/
|
||||
|
||||
public void putOid(long[] s) {
|
||||
putOid(s, OidTag) ;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Put an object identifier with a specified tag.
|
||||
*
|
||||
* @param s The integer to encode.
|
||||
* @param tag The tag to encode.
|
||||
*/
|
||||
|
||||
public void putOid(long[] s, int tag) {
|
||||
putOidValue(s) ;
|
||||
putTag(tag) ;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Put a <CODE>NULL</CODE> value.
|
||||
*/
|
||||
|
||||
public void putNull() {
|
||||
putNull(NullTag) ;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Put a <CODE>NULL</CODE> value with a specified tag.
|
||||
*
|
||||
* @param tag The tag to encode.
|
||||
*/
|
||||
|
||||
public void putNull(int tag) {
|
||||
putLength(0) ;
|
||||
putTag(tag) ;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Put an <CODE>ANY</CODE> value. In fact, this method does not encode anything.
|
||||
* It simply copies the specified bytes into the encoding.
|
||||
*
|
||||
* @param s The encoding of the <CODE>ANY</CODE> value.
|
||||
*/
|
||||
|
||||
public void putAny(byte[] s) {
|
||||
putAny(s, s.length) ;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Put an <CODE>ANY</CODE> value. Only the first <CODE>byteCount</CODE> are considered.
|
||||
*
|
||||
* @param s The encoding of the <CODE>ANY</CODE> value.
|
||||
* @param byteCount The number of bytes of the encoding.
|
||||
*/
|
||||
|
||||
public void putAny(byte[] s, int byteCount) {
|
||||
java.lang.System.arraycopy(s,0,bytes,start-byteCount,byteCount);
|
||||
start -= byteCount;
|
||||
// for (int i = byteCount - 1 ; i >= 0 ; i--) {
|
||||
// bytes[--start] = s[i] ;
|
||||
// }
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Open a sequence.
|
||||
* The encoder push the current position on its stack.
|
||||
*/
|
||||
|
||||
public void openSequence() {
|
||||
stackBuf[stackTop++] = start ;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Close a sequence.
|
||||
* The decode pull the stack to know the end of the current sequence.
|
||||
*/
|
||||
|
||||
public void closeSequence() {
|
||||
closeSequence(SequenceTag) ;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Close a sequence with the specified tag.
|
||||
*/
|
||||
|
||||
public void closeSequence(int tag) {
|
||||
final int end = stackBuf[--stackTop] ;
|
||||
putLength(end - start) ;
|
||||
putTag(tag) ;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Some standard tags
|
||||
//
|
||||
public final static int BooleanTag = 1 ;
|
||||
public final static int IntegerTag = 2 ;
|
||||
public final static int OctetStringTag = 4 ;
|
||||
public final static int NullTag = 5 ;
|
||||
public final static int OidTag = 6 ;
|
||||
public final static int SequenceTag = 0x30 ;
|
||||
|
||||
|
||||
|
||||
|
||||
////////////////////////// PROTECTED ///////////////////////////////
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Put a tag and move the current position backward.
|
||||
*
|
||||
* @param tag The tag to encode.
|
||||
*/
|
||||
|
||||
protected final void putTag(int tag) {
|
||||
if (tag < 256) {
|
||||
bytes[--start] = (byte)tag ;
|
||||
}
|
||||
else {
|
||||
while (tag != 0) {
|
||||
bytes[--start] = (byte)(tag & 127) ;
|
||||
tag = tag << 7 ;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Put a length and move the current position backward.
|
||||
*
|
||||
* @param length The length to encode.
|
||||
*/
|
||||
|
||||
protected final void putLength(final int length) {
|
||||
if (length < 0) {
|
||||
throw new IllegalArgumentException() ;
|
||||
}
|
||||
else if (length < 128) {
|
||||
bytes[--start] = (byte)length ;
|
||||
}
|
||||
else if (length < 256) {
|
||||
bytes[--start] = (byte)length ;
|
||||
bytes[--start] = (byte)0x81 ;
|
||||
}
|
||||
else if (length < 65536) {
|
||||
bytes[--start] = (byte)(length) ;
|
||||
bytes[--start] = (byte)(length >> 8) ;
|
||||
bytes[--start] = (byte)0x82 ;
|
||||
}
|
||||
else if (length < 16777126) {
|
||||
bytes[--start] = (byte)(length) ;
|
||||
bytes[--start] = (byte)(length >> 8) ;
|
||||
bytes[--start] = (byte)(length >> 16) ;
|
||||
bytes[--start] = (byte)0x83 ;
|
||||
}
|
||||
else {
|
||||
bytes[--start] = (byte)(length) ;
|
||||
bytes[--start] = (byte)(length >> 8) ;
|
||||
bytes[--start] = (byte)(length >> 16) ;
|
||||
bytes[--start] = (byte)(length >> 24) ;
|
||||
bytes[--start] = (byte)0x84 ;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Put an integer value and move the current position backward.
|
||||
*
|
||||
* @param v The integer to encode.
|
||||
*/
|
||||
|
||||
protected final void putIntegerValue(int v) {
|
||||
final int end = start ;
|
||||
int mask = 0x7f800000 ;
|
||||
int byteNeeded = 4 ;
|
||||
if (v < 0) {
|
||||
while (((mask & v) == mask) && (byteNeeded > 1)) {
|
||||
mask = mask >> 8 ;
|
||||
byteNeeded-- ;
|
||||
}
|
||||
}
|
||||
else {
|
||||
while (((mask & v) == 0) && (byteNeeded > 1)) {
|
||||
mask = mask >> 8 ;
|
||||
byteNeeded-- ;
|
||||
}
|
||||
}
|
||||
for (int i = 0 ; i < byteNeeded ; i++) {
|
||||
bytes[--start] = (byte)v ;
|
||||
v = v >> 8 ;
|
||||
}
|
||||
putLength(end - start) ;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Put an integer value expressed as a long.
|
||||
*
|
||||
* @param v The integer to encode.
|
||||
*/
|
||||
|
||||
protected final void putIntegerValue(long v) {
|
||||
final int end = start ;
|
||||
long mask = 0x7f80000000000000L ;
|
||||
int byteNeeded = 8 ;
|
||||
if (v < 0) {
|
||||
while (((mask & v) == mask) && (byteNeeded > 1)) {
|
||||
mask = mask >> 8 ;
|
||||
byteNeeded-- ;
|
||||
}
|
||||
}
|
||||
else {
|
||||
while (((mask & v) == 0) && (byteNeeded > 1)) {
|
||||
mask = mask >> 8 ;
|
||||
byteNeeded-- ;
|
||||
}
|
||||
}
|
||||
for (int i = 0 ; i < byteNeeded ; i++) {
|
||||
bytes[--start] = (byte)v ;
|
||||
v = v >> 8 ;
|
||||
}
|
||||
putLength(end - start) ;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Put a byte string and move the current position backward.
|
||||
*
|
||||
* @param s The byte string to encode.
|
||||
*/
|
||||
|
||||
protected final void putStringValue(byte[] s) {
|
||||
final int datalen = s.length;
|
||||
java.lang.System.arraycopy(s,0,bytes,start-datalen,datalen);
|
||||
start -= datalen;
|
||||
// for (int i = s.length - 1 ; i >= 0 ; i--) {
|
||||
// bytes[--start] = s[i] ;
|
||||
// }
|
||||
putLength(datalen) ;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Put an oid and move the current position backward.
|
||||
*
|
||||
* @param s The oid to encode.
|
||||
*/
|
||||
|
||||
protected final void putOidValue(final long[] s) {
|
||||
final int end = start ;
|
||||
final int slength = s.length;
|
||||
|
||||
// bugId 4641746: 0, 1, and 2 are legal values.
|
||||
if ((slength < 2) || (s[0] > 2) || (s[1] >= 40)) {
|
||||
throw new IllegalArgumentException() ;
|
||||
}
|
||||
for (int i = slength - 1 ; i >= 2 ; i--) {
|
||||
long c = s[i] ;
|
||||
if (c < 0) {
|
||||
throw new IllegalArgumentException() ;
|
||||
}
|
||||
else if (c < 128) {
|
||||
bytes[--start] = (byte)c ;
|
||||
}
|
||||
else {
|
||||
bytes[--start] = (byte)(c & 127) ;
|
||||
c = c >> 7 ;
|
||||
while (c != 0) {
|
||||
bytes[--start] = (byte)(c | 128) ;
|
||||
c = c >> 7 ;
|
||||
}
|
||||
}
|
||||
}
|
||||
bytes[--start] = (byte)(s[0] * 40 + s[1]) ;
|
||||
putLength(end - start) ;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// This is the byte array containing the encoding.
|
||||
//
|
||||
protected final byte bytes[];
|
||||
|
||||
//
|
||||
// This is the index of the first byte of the encoding.
|
||||
// It is initialized to <CODE>bytes.length</CODE> and decrease each time
|
||||
// an value is put in the encoder.
|
||||
//
|
||||
protected int start = -1 ;
|
||||
|
||||
//
|
||||
// This is the stack where end of sequences are kept.
|
||||
// A value is computed and pushed in it each time the <CODE>openSequence</CODE> method
|
||||
// is invoked.
|
||||
// A value is pulled and checked each time the <CODE>closeSequence</CODE> method is called.
|
||||
//
|
||||
protected final int stackBuf[] = new int[200] ;
|
||||
protected int stackTop = 0 ;
|
||||
|
||||
}
|
||||
63
jdkSrc/jdk8/com/sun/jmx/snmp/BerException.java
Normal file
63
jdkSrc/jdk8/com/sun/jmx/snmp/BerException.java
Normal file
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2007, 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.snmp;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Exception thrown when a BER encoding/decoding error occurs.
|
||||
*
|
||||
* <p><b>This API is a Sun Microsystems internal API and is subject
|
||||
* to change without notice.</b></p>
|
||||
*
|
||||
* @since 1.5
|
||||
*/
|
||||
|
||||
public class BerException extends Exception {
|
||||
private static final long serialVersionUID = 494709767137042951L;
|
||||
|
||||
public static final int BAD_VERSION=1;
|
||||
|
||||
private int errorType= 0;
|
||||
|
||||
public BerException() {
|
||||
errorType= 0;
|
||||
}
|
||||
|
||||
public BerException(int x) {
|
||||
errorType= x;
|
||||
}
|
||||
|
||||
public boolean isInvalidSnmpVersion() {
|
||||
if (errorType == BAD_VERSION)
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
}
|
||||
304
jdkSrc/jdk8/com/sun/jmx/snmp/EnumRowStatus.java
Normal file
304
jdkSrc/jdk8/com/sun/jmx/snmp/EnumRowStatus.java
Normal file
@@ -0,0 +1,304 @@
|
||||
/*
|
||||
* Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package com.sun.jmx.snmp;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Hashtable;
|
||||
|
||||
|
||||
/**
|
||||
* This class is an internal class which is used to represent RowStatus
|
||||
* codes as defined in RFC 2579.
|
||||
*
|
||||
* It defines an additional code, <i>unspecified</i>, which is
|
||||
* implementation specific, and is used to identify
|
||||
* unspecified actions (when for instance the RowStatus variable
|
||||
* is not present in the varbind list) or uninitialized values.
|
||||
*
|
||||
* mibgen does not generate objects of this class but any variable
|
||||
* using the RowStatus textual convention can be converted into an
|
||||
* object of this class thanks to the
|
||||
* <code>EnumRowStatus(Enumerated valueIndex)</code> constructor.
|
||||
*
|
||||
* <p><b>This API is a Sun Microsystems internal API and is subject
|
||||
* to change without notice.</b></p>
|
||||
**/
|
||||
|
||||
public class EnumRowStatus extends Enumerated implements Serializable {
|
||||
private static final long serialVersionUID = 8966519271130162420L;
|
||||
|
||||
/**
|
||||
* This value is SNMP Runtime implementation specific, and is used to identify
|
||||
* unspecified actions (when for instance the RowStatus variable
|
||||
* is not present in the varbind list) or uninitialized values.
|
||||
*/
|
||||
public final static int unspecified = 0;
|
||||
|
||||
/**
|
||||
* This value corresponds to the <i>active</i> RowStatus, as defined in
|
||||
* RFC 2579 from SMIv2:
|
||||
* <ul>
|
||||
* <i>active</i> indicates that the conceptual row is available for
|
||||
* use by the managed device;
|
||||
* </ul>
|
||||
*/
|
||||
public final static int active = 1;
|
||||
|
||||
/**
|
||||
* This value corresponds to the <i>notInService</i> RowStatus, as
|
||||
* defined in RFC 2579 from SMIv2:
|
||||
* <ul>
|
||||
* <i>notInService</i> indicates that the conceptual
|
||||
* row exists in the agent, but is unavailable for use by
|
||||
* the managed device; <i>notInService</i> has
|
||||
* no implication regarding the internal consistency of
|
||||
* the row, availability of resources, or consistency with
|
||||
* the current state of the managed device;
|
||||
* </ul>
|
||||
**/
|
||||
public final static int notInService = 2;
|
||||
|
||||
/**
|
||||
* This value corresponds to the <i>notReady</i> RowStatus, as defined
|
||||
* in RFC 2579 from SMIv2:
|
||||
* <ul>
|
||||
* <i>notReady</i> indicates that the conceptual row
|
||||
* exists in the agent, but is missing information
|
||||
* necessary in order to be available for use by the
|
||||
* managed device (i.e., one or more required columns in
|
||||
* the conceptual row have not been instantiated);
|
||||
* </ul>
|
||||
*/
|
||||
public final static int notReady = 3;
|
||||
|
||||
/**
|
||||
* This value corresponds to the <i>createAndGo</i> RowStatus,
|
||||
* as defined in RFC 2579 from SMIv2:
|
||||
* <ul>
|
||||
* <i>createAndGo</i> is supplied by a management
|
||||
* station wishing to create a new instance of a
|
||||
* conceptual row and to have its status automatically set
|
||||
* to active, making it available for use by the managed
|
||||
* device;
|
||||
* </ul>
|
||||
*/
|
||||
public final static int createAndGo = 4;
|
||||
|
||||
/**
|
||||
* This value corresponds to the <i>createAndWait</i> RowStatus,
|
||||
* as defined in RFC 2579 from SMIv2:
|
||||
* <ul>
|
||||
* <i>createAndWait</i> is supplied by a management
|
||||
* station wishing to create a new instance of a
|
||||
* conceptual row (but not make it available for use by
|
||||
* the managed device);
|
||||
* </ul>
|
||||
*/
|
||||
public final static int createAndWait = 5;
|
||||
|
||||
/**
|
||||
* This value corresponds to the <i>destroy</i> RowStatus, as defined in
|
||||
* RFC 2579 from SMIv2:
|
||||
* <ul>
|
||||
* <i>destroy</i> is supplied by a management station
|
||||
* wishing to delete all of the instances associated with
|
||||
* an existing conceptual row.
|
||||
* </ul>
|
||||
*/
|
||||
public final static int destroy = 6;
|
||||
|
||||
/**
|
||||
* Build an <code>EnumRowStatus</code> from an <code>int</code>.
|
||||
* @param valueIndex should be either 0 (<i>unspecified</i>), or one of
|
||||
* the values defined in RFC 2579.
|
||||
* @exception IllegalArgumentException if the given
|
||||
* <code>valueIndex</code> is not valid.
|
||||
**/
|
||||
public EnumRowStatus(int valueIndex)
|
||||
throws IllegalArgumentException {
|
||||
super(valueIndex);
|
||||
}
|
||||
|
||||
/**
|
||||
* Build an <code>EnumRowStatus</code> from an <code>Enumerated</code>.
|
||||
* @param valueIndex should be either 0 (<i>unspecified</i>), or one of
|
||||
* the values defined in RFC 2579.
|
||||
* @exception IllegalArgumentException if the given
|
||||
* <code>valueIndex</code> is not valid.
|
||||
**/
|
||||
public EnumRowStatus(Enumerated valueIndex)
|
||||
throws IllegalArgumentException {
|
||||
this(valueIndex.intValue());
|
||||
}
|
||||
|
||||
/**
|
||||
* Build an <code>EnumRowStatus</code> from a <code>long</code>.
|
||||
* @param valueIndex should be either 0 (<i>unspecified</i>), or one of
|
||||
* the values defined in RFC 2579.
|
||||
* @exception IllegalArgumentException if the given
|
||||
* <code>valueIndex</code> is not valid.
|
||||
**/
|
||||
public EnumRowStatus(long valueIndex)
|
||||
throws IllegalArgumentException {
|
||||
this((int)valueIndex);
|
||||
}
|
||||
|
||||
/**
|
||||
* Build an <code>EnumRowStatus</code> from an <code>Integer</code>.
|
||||
* @param valueIndex should be either 0 (<i>unspecified</i>), or one of
|
||||
* the values defined in RFC 2579.
|
||||
* @exception IllegalArgumentException if the given
|
||||
* <code>valueIndex</code> is not valid.
|
||||
**/
|
||||
public EnumRowStatus(Integer valueIndex)
|
||||
throws IllegalArgumentException {
|
||||
super(valueIndex);
|
||||
}
|
||||
|
||||
/**
|
||||
* Build an <code>EnumRowStatus</code> from a <code>Long</code>.
|
||||
* @param valueIndex should be either 0 (<i>unspecified</i>), or one of
|
||||
* the values defined in RFC 2579.
|
||||
* @exception IllegalArgumentException if the given
|
||||
* <code>valueIndex</code> is not valid.
|
||||
**/
|
||||
public EnumRowStatus(Long valueIndex)
|
||||
throws IllegalArgumentException {
|
||||
this(valueIndex.longValue());
|
||||
}
|
||||
|
||||
/**
|
||||
* Build an <code>EnumRowStatus</code> with <i>unspecified</i> value.
|
||||
**/
|
||||
public EnumRowStatus()
|
||||
throws IllegalArgumentException {
|
||||
this(unspecified);
|
||||
}
|
||||
|
||||
/**
|
||||
* Build an <code>EnumRowStatus</code> from a <code>String</code>.
|
||||
* @param x should be either "unspecified", or one of
|
||||
* the values defined in RFC 2579 ("active", "notReady", etc...)
|
||||
* @exception IllegalArgumentException if the given String
|
||||
* <code>x</code> is not valid.
|
||||
**/
|
||||
public EnumRowStatus(String x)
|
||||
throws IllegalArgumentException {
|
||||
super(x);
|
||||
}
|
||||
|
||||
/**
|
||||
* Build an <code>EnumRowStatus</code> from an <code>SnmpInt</code>.
|
||||
* @param valueIndex should be either 0 (<i>unspecified</i>), or one of
|
||||
* the values defined in RFC 2579.
|
||||
* @exception IllegalArgumentException if the given
|
||||
* <code>valueIndex</code> is not valid.
|
||||
**/
|
||||
public EnumRowStatus(SnmpInt valueIndex)
|
||||
throws IllegalArgumentException {
|
||||
this(valueIndex.intValue());
|
||||
}
|
||||
|
||||
/**
|
||||
* Build an SnmpValue from this object.
|
||||
*
|
||||
* @exception IllegalArgumentException if this object holds an
|
||||
* <i>unspecified</i> value.
|
||||
* @return an SnmpInt containing this object value.
|
||||
**/
|
||||
public SnmpInt toSnmpValue()
|
||||
throws IllegalArgumentException {
|
||||
if (value == unspecified)
|
||||
throw new
|
||||
IllegalArgumentException("`unspecified' is not a valid SNMP value.");
|
||||
return new SnmpInt(value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check that the given <code>value</code> is valid.
|
||||
*
|
||||
* Valid values are:
|
||||
* <ul><li><i>unspecified(0)</i></li>
|
||||
* <li><i>active(1)</i></li>
|
||||
* <li><i>notInService(2)</i></li>
|
||||
* <li><i>notReady(3)</i></li>
|
||||
* <li><i>createAndGo(4)</i></li>
|
||||
* <li><i>createAndWait(5)</i></li>
|
||||
* <li><i>destroy(6)</i></li>
|
||||
* </ul>
|
||||
*
|
||||
**/
|
||||
static public boolean isValidValue(int value) {
|
||||
if (value < 0) return false;
|
||||
if (value > 6) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Documented in Enumerated
|
||||
//
|
||||
@Override
|
||||
protected Hashtable<Integer, String> getIntTable() {
|
||||
return EnumRowStatus.getRSIntTable();
|
||||
}
|
||||
|
||||
// Documented in Enumerated
|
||||
//
|
||||
@Override
|
||||
protected Hashtable<String, Integer> getStringTable() {
|
||||
return EnumRowStatus.getRSStringTable();
|
||||
}
|
||||
|
||||
static Hashtable<Integer, String> getRSIntTable() {
|
||||
return intTable ;
|
||||
}
|
||||
|
||||
static Hashtable<String, Integer> getRSStringTable() {
|
||||
return stringTable ;
|
||||
}
|
||||
|
||||
// Initialize the mapping tables.
|
||||
//
|
||||
final static Hashtable<Integer, String> intTable = new Hashtable<>();
|
||||
final static Hashtable<String, Integer> stringTable = new Hashtable<>();
|
||||
static {
|
||||
intTable.put(new Integer(0), "unspecified");
|
||||
intTable.put(new Integer(3), "notReady");
|
||||
intTable.put(new Integer(6), "destroy");
|
||||
intTable.put(new Integer(2), "notInService");
|
||||
intTable.put(new Integer(5), "createAndWait");
|
||||
intTable.put(new Integer(1), "active");
|
||||
intTable.put(new Integer(4), "createAndGo");
|
||||
stringTable.put("unspecified", new Integer(0));
|
||||
stringTable.put("notReady", new Integer(3));
|
||||
stringTable.put("destroy", new Integer(6));
|
||||
stringTable.put("notInService", new Integer(2));
|
||||
stringTable.put("createAndWait", new Integer(5));
|
||||
stringTable.put("active", new Integer(1));
|
||||
stringTable.put("createAndGo", new Integer(4));
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
221
jdkSrc/jdk8/com/sun/jmx/snmp/Enumerated.java
Normal file
221
jdkSrc/jdk8/com/sun/jmx/snmp/Enumerated.java
Normal file
@@ -0,0 +1,221 @@
|
||||
/*
|
||||
* Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package com.sun.jmx.snmp;
|
||||
|
||||
|
||||
import java.io.*;
|
||||
import java.util.Hashtable;
|
||||
import java.util.*;
|
||||
|
||||
|
||||
|
||||
/** This class is used for implementing enumerated values.
|
||||
*
|
||||
* An enumeration is represented by a class derived from Enumerated.
|
||||
* The derived class defines what are the permitted values in the enumeration.
|
||||
*
|
||||
* An enumerated value is represented by an instance of the derived class.
|
||||
* It can be represented :
|
||||
* - as an integer
|
||||
* - as a string
|
||||
*
|
||||
* <p><b>This API is a Sun Microsystems internal API and is subject
|
||||
* to change without notice.</b></p>
|
||||
*/
|
||||
|
||||
abstract public class Enumerated implements Serializable {
|
||||
|
||||
/**
|
||||
* Construct an enumerated with a default value.
|
||||
* The default value is the first available in getIntTable().
|
||||
* @exception IllegalArgumentException One of the arguments passed to the method is illegal or inappropriate.
|
||||
*/
|
||||
public Enumerated() throws IllegalArgumentException {
|
||||
Enumeration<Integer> e =getIntTable().keys();
|
||||
if (e.hasMoreElements()) {
|
||||
value = e.nextElement().intValue() ;
|
||||
}
|
||||
else {
|
||||
throw new IllegalArgumentException() ;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct an enumerated from its integer form.
|
||||
*
|
||||
* @param valueIndex The integer form.
|
||||
* @exception IllegalArgumentException One of the arguments passed to
|
||||
* the method is illegal or inappropriate.
|
||||
*/
|
||||
public Enumerated(int valueIndex) throws IllegalArgumentException {
|
||||
if (getIntTable().get(new Integer(valueIndex)) == null) {
|
||||
throw new IllegalArgumentException() ;
|
||||
}
|
||||
value = valueIndex ;
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct an enumerated from its Integer form.
|
||||
*
|
||||
* @param valueIndex The Integer form.
|
||||
* @exception IllegalArgumentException One of the arguments passed to
|
||||
* the method is illegal or inappropriate.
|
||||
*/
|
||||
public Enumerated(Integer valueIndex) throws IllegalArgumentException {
|
||||
if (getIntTable().get(valueIndex) == null) {
|
||||
throw new IllegalArgumentException() ;
|
||||
}
|
||||
value = valueIndex.intValue() ;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Construct an enumerated from its string form.
|
||||
*
|
||||
* @param valueString The string form.
|
||||
* @exception IllegalArgumentException One of the arguments passed
|
||||
* to the method is illegal or inappropriate.
|
||||
*/
|
||||
public Enumerated(String valueString) throws IllegalArgumentException {
|
||||
Integer index = getStringTable().get(valueString) ;
|
||||
if (index == null) {
|
||||
throw new IllegalArgumentException() ;
|
||||
}
|
||||
else {
|
||||
value = index.intValue() ;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return the integer form of the enumerated.
|
||||
*
|
||||
* @return The integer form
|
||||
*/
|
||||
|
||||
public int intValue() {
|
||||
return value ;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns an Java enumeration of the permitted integers.
|
||||
*
|
||||
* @return An enumeration of Integer instances
|
||||
*/
|
||||
|
||||
public Enumeration<Integer> valueIndexes() {
|
||||
return getIntTable().keys() ;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns an Java enumeration of the permitted strings.
|
||||
*
|
||||
* @return An enumeration of String instances
|
||||
*/
|
||||
|
||||
public Enumeration<String> valueStrings() {
|
||||
return getStringTable().keys() ;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Compares this enumerated to the specified enumerated.
|
||||
*
|
||||
* The result is true if and only if the argument is not null
|
||||
* and is of the same class.
|
||||
*
|
||||
* @param obj The object to compare with.
|
||||
*
|
||||
* @return True if this and obj are the same; false otherwise
|
||||
*/
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
|
||||
return ((obj != null) &&
|
||||
(getClass() == obj.getClass()) &&
|
||||
(value == ((Enumerated)obj).value)) ;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the hash code for this enumerated.
|
||||
*
|
||||
* @return A hash code value for this object.
|
||||
*/
|
||||
@Override
|
||||
public int hashCode() {
|
||||
String hashString = getClass().getName() + String.valueOf(value) ;
|
||||
return hashString.hashCode() ;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the string form of this enumerated.
|
||||
*
|
||||
* @return The string for for this object.
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
return getIntTable().get(new Integer(value)) ;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the hashtable of the integer forms.
|
||||
* getIntTable().get(x) returns the string form associated
|
||||
* to the integer x.
|
||||
*
|
||||
* This method must be implemented by the derived class.
|
||||
*
|
||||
* @return An hashtable for read-only purpose
|
||||
*/
|
||||
|
||||
protected abstract Hashtable<Integer,String> getIntTable() ;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Returns the hashtable of the string forms.
|
||||
* getStringTable().get(s) returns the integer form associated
|
||||
* to the string s.
|
||||
*
|
||||
* This method must be implemented by the derived class.
|
||||
*
|
||||
* @return An hashtable for read-only purpose
|
||||
*/
|
||||
|
||||
protected abstract Hashtable<String,Integer> getStringTable() ;
|
||||
|
||||
|
||||
/**
|
||||
* This variable keeps the integer form of the enumerated.
|
||||
* The string form is retrieved using getIntTable().
|
||||
*/
|
||||
protected int value ;
|
||||
|
||||
}
|
||||
402
jdkSrc/jdk8/com/sun/jmx/snmp/IPAcl/ASCII_CharStream.java
Normal file
402
jdkSrc/jdk8/com/sun/jmx/snmp/IPAcl/ASCII_CharStream.java
Normal file
@@ -0,0 +1,402 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 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.
|
||||
*/
|
||||
|
||||
/* Generated By:JavaCC: Do not edit this line. ASCII_CharStream.java Version 0.7pre6 */
|
||||
package com.sun.jmx.snmp.IPAcl;
|
||||
|
||||
/**
|
||||
* An implementation of interface CharStream, where the stream is assumed to
|
||||
* contain only ASCII characters (without unicode processing).
|
||||
*/
|
||||
|
||||
final class ASCII_CharStream
|
||||
{
|
||||
public static final boolean staticFlag = false;
|
||||
int bufsize;
|
||||
int available;
|
||||
int tokenBegin;
|
||||
public int bufpos = -1;
|
||||
private int bufline[];
|
||||
private int bufcolumn[];
|
||||
|
||||
private int column = 0;
|
||||
private int line = 1;
|
||||
|
||||
private boolean prevCharIsCR = false;
|
||||
private boolean prevCharIsLF = false;
|
||||
|
||||
private java.io.Reader inputStream;
|
||||
|
||||
private char[] buffer;
|
||||
private int maxNextCharInd = 0;
|
||||
private int inBuf = 0;
|
||||
|
||||
private final void ExpandBuff(boolean wrapAround)
|
||||
{
|
||||
char[] newbuffer = new char[bufsize + 2048];
|
||||
int newbufline[] = new int[bufsize + 2048];
|
||||
int newbufcolumn[] = new int[bufsize + 2048];
|
||||
|
||||
try
|
||||
{
|
||||
if (wrapAround)
|
||||
{
|
||||
System.arraycopy(buffer, tokenBegin, newbuffer, 0, bufsize - tokenBegin);
|
||||
System.arraycopy(buffer, 0, newbuffer,
|
||||
bufsize - tokenBegin, bufpos);
|
||||
buffer = newbuffer;
|
||||
|
||||
System.arraycopy(bufline, tokenBegin, newbufline, 0, bufsize - tokenBegin);
|
||||
System.arraycopy(bufline, 0, newbufline, bufsize - tokenBegin, bufpos);
|
||||
bufline = newbufline;
|
||||
|
||||
System.arraycopy(bufcolumn, tokenBegin, newbufcolumn, 0, bufsize - tokenBegin);
|
||||
System.arraycopy(bufcolumn, 0, newbufcolumn, bufsize - tokenBegin, bufpos);
|
||||
bufcolumn = newbufcolumn;
|
||||
|
||||
maxNextCharInd = (bufpos += (bufsize - tokenBegin));
|
||||
}
|
||||
else
|
||||
{
|
||||
System.arraycopy(buffer, tokenBegin, newbuffer, 0, bufsize - tokenBegin);
|
||||
buffer = newbuffer;
|
||||
|
||||
System.arraycopy(bufline, tokenBegin, newbufline, 0, bufsize - tokenBegin);
|
||||
bufline = newbufline;
|
||||
|
||||
System.arraycopy(bufcolumn, tokenBegin, newbufcolumn, 0, bufsize - tokenBegin);
|
||||
bufcolumn = newbufcolumn;
|
||||
|
||||
maxNextCharInd = (bufpos -= tokenBegin);
|
||||
}
|
||||
}
|
||||
catch (Throwable t)
|
||||
{
|
||||
throw new Error(t.getMessage());
|
||||
}
|
||||
|
||||
|
||||
bufsize += 2048;
|
||||
available = bufsize;
|
||||
tokenBegin = 0;
|
||||
}
|
||||
|
||||
private final void FillBuff() throws java.io.IOException
|
||||
{
|
||||
if (maxNextCharInd == available)
|
||||
{
|
||||
if (available == bufsize)
|
||||
{
|
||||
if (tokenBegin > 2048)
|
||||
{
|
||||
bufpos = maxNextCharInd = 0;
|
||||
available = tokenBegin;
|
||||
}
|
||||
else if (tokenBegin < 0)
|
||||
bufpos = maxNextCharInd = 0;
|
||||
else
|
||||
ExpandBuff(false);
|
||||
}
|
||||
else if (available > tokenBegin)
|
||||
available = bufsize;
|
||||
else if ((tokenBegin - available) < 2048)
|
||||
ExpandBuff(true);
|
||||
else
|
||||
available = tokenBegin;
|
||||
}
|
||||
|
||||
int i;
|
||||
try {
|
||||
if ((i = inputStream.read(buffer, maxNextCharInd,
|
||||
available - maxNextCharInd)) == -1)
|
||||
{
|
||||
inputStream.close();
|
||||
throw new java.io.IOException();
|
||||
}
|
||||
else
|
||||
maxNextCharInd += i;
|
||||
return;
|
||||
}
|
||||
catch(java.io.IOException e) {
|
||||
--bufpos;
|
||||
backup(0);
|
||||
if (tokenBegin == -1)
|
||||
tokenBegin = bufpos;
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
public final char BeginToken() throws java.io.IOException
|
||||
{
|
||||
tokenBegin = -1;
|
||||
char c = readChar();
|
||||
tokenBegin = bufpos;
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
private final void UpdateLineColumn(char c)
|
||||
{
|
||||
column++;
|
||||
|
||||
if (prevCharIsLF)
|
||||
{
|
||||
prevCharIsLF = false;
|
||||
line += (column = 1);
|
||||
}
|
||||
else if (prevCharIsCR)
|
||||
{
|
||||
prevCharIsCR = false;
|
||||
if (c == '\n')
|
||||
{
|
||||
prevCharIsLF = true;
|
||||
}
|
||||
else
|
||||
line += (column = 1);
|
||||
}
|
||||
|
||||
switch (c)
|
||||
{
|
||||
case '\r' :
|
||||
prevCharIsCR = true;
|
||||
break;
|
||||
case '\n' :
|
||||
prevCharIsLF = true;
|
||||
break;
|
||||
case '\t' :
|
||||
column--;
|
||||
column += (8 - (column & 07));
|
||||
break;
|
||||
default :
|
||||
break;
|
||||
}
|
||||
|
||||
bufline[bufpos] = line;
|
||||
bufcolumn[bufpos] = column;
|
||||
}
|
||||
|
||||
public final char readChar() throws java.io.IOException
|
||||
{
|
||||
if (inBuf > 0)
|
||||
{
|
||||
--inBuf;
|
||||
return (char)((char)0xff & buffer[(bufpos == bufsize - 1) ? (bufpos = 0) : ++bufpos]);
|
||||
}
|
||||
|
||||
if (++bufpos >= maxNextCharInd)
|
||||
FillBuff();
|
||||
|
||||
char c = (char)((char)0xff & buffer[bufpos]);
|
||||
|
||||
UpdateLineColumn(c);
|
||||
return (c);
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated
|
||||
* @see #getEndColumn
|
||||
*/
|
||||
@Deprecated
|
||||
public final int getColumn() {
|
||||
return bufcolumn[bufpos];
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated
|
||||
* @see #getEndLine
|
||||
*/
|
||||
@Deprecated
|
||||
public final int getLine() {
|
||||
return bufline[bufpos];
|
||||
}
|
||||
|
||||
public final int getEndColumn() {
|
||||
return bufcolumn[bufpos];
|
||||
}
|
||||
|
||||
public final int getEndLine() {
|
||||
return bufline[bufpos];
|
||||
}
|
||||
|
||||
public final int getBeginColumn() {
|
||||
return bufcolumn[tokenBegin];
|
||||
}
|
||||
|
||||
public final int getBeginLine() {
|
||||
return bufline[tokenBegin];
|
||||
}
|
||||
|
||||
public final void backup(int amount) {
|
||||
|
||||
inBuf += amount;
|
||||
if ((bufpos -= amount) < 0)
|
||||
bufpos += bufsize;
|
||||
}
|
||||
|
||||
public ASCII_CharStream(java.io.Reader dstream, int startline,
|
||||
int startcolumn, int buffersize)
|
||||
{
|
||||
inputStream = dstream;
|
||||
line = startline;
|
||||
column = startcolumn - 1;
|
||||
|
||||
available = bufsize = buffersize;
|
||||
buffer = new char[buffersize];
|
||||
bufline = new int[buffersize];
|
||||
bufcolumn = new int[buffersize];
|
||||
}
|
||||
|
||||
public ASCII_CharStream(java.io.Reader dstream, int startline,
|
||||
int startcolumn)
|
||||
{
|
||||
this(dstream, startline, startcolumn, 4096);
|
||||
}
|
||||
public void ReInit(java.io.Reader dstream, int startline,
|
||||
int startcolumn, int buffersize)
|
||||
{
|
||||
inputStream = dstream;
|
||||
line = startline;
|
||||
column = startcolumn - 1;
|
||||
|
||||
if (buffer == null || buffersize != buffer.length)
|
||||
{
|
||||
available = bufsize = buffersize;
|
||||
buffer = new char[buffersize];
|
||||
bufline = new int[buffersize];
|
||||
bufcolumn = new int[buffersize];
|
||||
}
|
||||
prevCharIsLF = prevCharIsCR = false;
|
||||
tokenBegin = inBuf = maxNextCharInd = 0;
|
||||
bufpos = -1;
|
||||
}
|
||||
|
||||
public void ReInit(java.io.Reader dstream, int startline,
|
||||
int startcolumn)
|
||||
{
|
||||
ReInit(dstream, startline, startcolumn, 4096);
|
||||
}
|
||||
public ASCII_CharStream(java.io.InputStream dstream, int startline,
|
||||
int startcolumn, int buffersize)
|
||||
{
|
||||
this(new java.io.InputStreamReader(dstream), startline, startcolumn, 4096);
|
||||
}
|
||||
|
||||
public ASCII_CharStream(java.io.InputStream dstream, int startline,
|
||||
int startcolumn)
|
||||
{
|
||||
this(dstream, startline, startcolumn, 4096);
|
||||
}
|
||||
|
||||
public void ReInit(java.io.InputStream dstream, int startline,
|
||||
int startcolumn, int buffersize)
|
||||
{
|
||||
ReInit(new java.io.InputStreamReader(dstream), startline, startcolumn, 4096);
|
||||
}
|
||||
public void ReInit(java.io.InputStream dstream, int startline,
|
||||
int startcolumn)
|
||||
{
|
||||
ReInit(dstream, startline, startcolumn, 4096);
|
||||
}
|
||||
public final String GetImage()
|
||||
{
|
||||
if (bufpos >= tokenBegin)
|
||||
return new String(buffer, tokenBegin, bufpos - tokenBegin + 1);
|
||||
else
|
||||
return new String(buffer, tokenBegin, bufsize - tokenBegin) +
|
||||
new String(buffer, 0, bufpos + 1);
|
||||
}
|
||||
|
||||
public final char[] GetSuffix(int len)
|
||||
{
|
||||
char[] ret = new char[len];
|
||||
|
||||
if ((bufpos + 1) >= len)
|
||||
System.arraycopy(buffer, bufpos - len + 1, ret, 0, len);
|
||||
else
|
||||
{
|
||||
System.arraycopy(buffer, bufsize - (len - bufpos - 1), ret, 0,
|
||||
len - bufpos - 1);
|
||||
System.arraycopy(buffer, 0, ret, len - bufpos - 1, bufpos + 1);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
public void Done()
|
||||
{
|
||||
buffer = null;
|
||||
bufline = null;
|
||||
bufcolumn = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to adjust line and column numbers for the start of a token.
|
||||
*/
|
||||
public void adjustBeginLineColumn(int newLine, int newCol)
|
||||
{
|
||||
int start = tokenBegin;
|
||||
int len;
|
||||
|
||||
if (bufpos >= tokenBegin)
|
||||
{
|
||||
len = bufpos - tokenBegin + inBuf + 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
len = bufsize - tokenBegin + bufpos + 1 + inBuf;
|
||||
}
|
||||
|
||||
int i = 0, j = 0, k = 0;
|
||||
int nextColDiff = 0, columnDiff = 0;
|
||||
|
||||
while (i < len &&
|
||||
bufline[j = start % bufsize] == bufline[k = ++start % bufsize])
|
||||
{
|
||||
bufline[j] = newLine;
|
||||
nextColDiff = columnDiff + bufcolumn[k] - bufcolumn[j];
|
||||
bufcolumn[j] = newCol + columnDiff;
|
||||
columnDiff = nextColDiff;
|
||||
i++;
|
||||
}
|
||||
|
||||
if (i < len)
|
||||
{
|
||||
bufline[j] = newLine++;
|
||||
bufcolumn[j] = newCol + columnDiff;
|
||||
|
||||
while (i++ < len)
|
||||
{
|
||||
if (bufline[j = start % bufsize] != bufline[++start % bufsize])
|
||||
bufline[j] = newLine++;
|
||||
else
|
||||
bufline[j] = newLine;
|
||||
}
|
||||
}
|
||||
|
||||
line = bufline[j];
|
||||
column = bufcolumn[j];
|
||||
}
|
||||
|
||||
}
|
||||
263
jdkSrc/jdk8/com/sun/jmx/snmp/IPAcl/AclEntryImpl.java
Normal file
263
jdkSrc/jdk8/com/sun/jmx/snmp/IPAcl/AclEntryImpl.java
Normal file
@@ -0,0 +1,263 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2007, 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.snmp.IPAcl;
|
||||
|
||||
|
||||
|
||||
import java.security.acl.Permission;
|
||||
import java.util.Vector;
|
||||
import java.util.Enumeration;
|
||||
import java.io.Serializable;
|
||||
import java.net.UnknownHostException;
|
||||
|
||||
import java.security.Principal;
|
||||
import java.security.acl.AclEntry;
|
||||
|
||||
|
||||
/**
|
||||
* Represent one entry in the Access Control List (ACL).
|
||||
* This ACL entry object contains a permission associated with a particular principal.
|
||||
* (A principal represents an entity such as an individual machine or a group).
|
||||
*
|
||||
* @see java.security.acl.AclEntry
|
||||
*/
|
||||
|
||||
class AclEntryImpl implements AclEntry, Serializable {
|
||||
private static final long serialVersionUID = -5047185131260073216L;
|
||||
|
||||
private AclEntryImpl (AclEntryImpl i) throws UnknownHostException {
|
||||
setPrincipal(i.getPrincipal());
|
||||
permList = new Vector<Permission>();
|
||||
commList = new Vector<String>();
|
||||
|
||||
for (Enumeration<String> en = i.communities(); en.hasMoreElements();){
|
||||
addCommunity(en.nextElement());
|
||||
}
|
||||
|
||||
for (Enumeration<Permission> en = i.permissions(); en.hasMoreElements();){
|
||||
addPermission(en.nextElement());
|
||||
}
|
||||
if (i.isNegative()) setNegativePermissions();
|
||||
}
|
||||
|
||||
/**
|
||||
* Contructs an empty ACL entry.
|
||||
*/
|
||||
public AclEntryImpl (){
|
||||
princ = null;
|
||||
permList = new Vector<Permission>();
|
||||
commList = new Vector<String>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs an ACL entry with a specified principal.
|
||||
*
|
||||
* @param p the principal to be set for this entry.
|
||||
*/
|
||||
public AclEntryImpl (Principal p) throws UnknownHostException {
|
||||
princ = p;
|
||||
permList = new Vector<Permission>();
|
||||
commList = new Vector<String>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Clones this ACL entry.
|
||||
*
|
||||
* @return a clone of this ACL entry.
|
||||
*/
|
||||
public Object clone() {
|
||||
AclEntryImpl i;
|
||||
try {
|
||||
i = new AclEntryImpl(this);
|
||||
}catch (UnknownHostException e) {
|
||||
i = null;
|
||||
}
|
||||
return (Object) i;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if this is a negative ACL entry (one denying the associated principal
|
||||
* the set of permissions in the entry), false otherwise.
|
||||
*
|
||||
* @return true if this is a negative ACL entry, false if it's not.
|
||||
*/
|
||||
public boolean isNegative(){
|
||||
return neg;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the specified permission to this ACL entry. Note: An entry can
|
||||
* have multiple permissions.
|
||||
*
|
||||
* @param perm the permission to be associated with the principal in this
|
||||
* entry
|
||||
* @return true if the permission is removed, false if the permission was
|
||||
* not part of this entry's permission set.
|
||||
*
|
||||
*/
|
||||
public boolean addPermission(java.security.acl.Permission perm){
|
||||
if (permList.contains(perm)) return false;
|
||||
permList.addElement(perm);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the specified permission from this ACL entry.
|
||||
*
|
||||
* @param perm the permission to be removed from this entry.
|
||||
* @return true if the permission is removed, false if the permission
|
||||
* was not part of this entry's permission set.
|
||||
*/
|
||||
public boolean removePermission(java.security.acl.Permission perm){
|
||||
if (!permList.contains(perm)) return false;
|
||||
permList.removeElement(perm);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the specified permission is part of the permission set in
|
||||
* this entry.
|
||||
*
|
||||
* @param perm the permission to be checked for.
|
||||
* @return true if the permission is part of the permission set in this
|
||||
* entry, false otherwise.
|
||||
*/
|
||||
|
||||
public boolean checkPermission(java.security.acl.Permission perm){
|
||||
return (permList.contains(perm));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an enumeration of the permissions in this ACL entry.
|
||||
*
|
||||
* @return an enumeration of the permissions in this ACL entry.
|
||||
*/
|
||||
public Enumeration<Permission> permissions(){
|
||||
return permList.elements();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets this ACL entry to be a negative one. That is, the associated principal
|
||||
* (e.g., a user or a group) will be denied the permission set specified in the
|
||||
* entry. Note: ACL entries are by default positive. An entry becomes a negative
|
||||
* entry only if this setNegativePermissions method is called on it.
|
||||
*
|
||||
* Not Implemented.
|
||||
*/
|
||||
public void setNegativePermissions(){
|
||||
neg = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the principal for which permissions are granted or denied by this ACL
|
||||
* entry. Returns null if there is no principal set for this entry yet.
|
||||
*
|
||||
* @return the principal associated with this entry.
|
||||
*/
|
||||
public Principal getPrincipal(){
|
||||
return princ;
|
||||
}
|
||||
|
||||
/**
|
||||
* Specifies the principal for which permissions are granted or denied by
|
||||
* this ACL entry. If a principal was already set for this ACL entry,
|
||||
* false is returned, otherwise true is returned.
|
||||
*
|
||||
* @param p the principal to be set for this entry.
|
||||
* @return true if the principal is set, false if there was already a
|
||||
* principal set for this entry.
|
||||
*/
|
||||
public boolean setPrincipal(Principal p) {
|
||||
if (princ != null )
|
||||
return false;
|
||||
princ = p;
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a string representation of the contents of this ACL entry.
|
||||
*
|
||||
* @return a string representation of the contents.
|
||||
*/
|
||||
public String toString(){
|
||||
return "AclEntry:"+princ.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an enumeration of the communities in this ACL entry.
|
||||
*
|
||||
* @return an enumeration of the communities in this ACL entry.
|
||||
*/
|
||||
public Enumeration<String> communities(){
|
||||
return commList.elements();
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the specified community to this ACL entry. Note: An entry can
|
||||
* have multiple communities.
|
||||
*
|
||||
* @param comm the community to be associated with the principal
|
||||
* in this entry.
|
||||
* @return true if the community was added, false if the community was
|
||||
* already part of this entry's community set.
|
||||
*/
|
||||
public boolean addCommunity(String comm){
|
||||
if (commList.contains(comm)) return false;
|
||||
commList.addElement(comm);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the specified community from this ACL entry.
|
||||
*
|
||||
* @param comm the community to be removed from this entry.
|
||||
* @return true if the community is removed, false if the community was
|
||||
* not part of this entry's community set.
|
||||
*/
|
||||
public boolean removeCommunity(String comm){
|
||||
if (!commList.contains(comm)) return false;
|
||||
commList.removeElement(comm);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the specified community is part of the community set in this
|
||||
* entry.
|
||||
*
|
||||
* @param comm the community to be checked for.
|
||||
* @return true if the community is part of the community set in this
|
||||
* entry, false otherwise.
|
||||
*/
|
||||
public boolean checkCommunity(String comm){
|
||||
return (commList.contains(comm));
|
||||
}
|
||||
|
||||
private Principal princ = null;
|
||||
private boolean neg = false;
|
||||
private Vector<Permission> permList = null;
|
||||
private Vector<String> commList = null;
|
||||
}
|
||||
295
jdkSrc/jdk8/com/sun/jmx/snmp/IPAcl/AclImpl.java
Normal file
295
jdkSrc/jdk8/com/sun/jmx/snmp/IPAcl/AclImpl.java
Normal file
@@ -0,0 +1,295 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
|
||||
package com.sun.jmx.snmp.IPAcl;
|
||||
|
||||
|
||||
|
||||
import java.security.Principal;
|
||||
import java.security.acl.Acl;
|
||||
import java.security.acl.AclEntry;
|
||||
import java.security.acl.NotOwnerException;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.security.acl.Permission;
|
||||
import java.util.Vector;
|
||||
import java.util.Enumeration;
|
||||
|
||||
|
||||
/**
|
||||
* Represent an Access Control List (ACL) which is used to guard access to http adaptor.
|
||||
* <P>
|
||||
* It is a data structure with multiple ACL entries. Each ACL entry, of interface type
|
||||
* AclEntry, contains a set of permissions and a set of communities associated with a
|
||||
* particular principal. (A principal represents an entity such as a host or a group of host).
|
||||
* Additionally, each ACL entry is specified as being either positive or negative.
|
||||
* If positive, the permissions are to be granted to the associated principal.
|
||||
* If negative, the permissions are to be denied.
|
||||
*
|
||||
* @see java.security.acl.Acl
|
||||
*/
|
||||
|
||||
class AclImpl extends OwnerImpl implements Acl, Serializable {
|
||||
private static final long serialVersionUID = -2250957591085270029L;
|
||||
|
||||
private Vector<AclEntry> entryList = null;
|
||||
private String aclName = null;
|
||||
|
||||
/**
|
||||
* Constructs the ACL with a specified owner
|
||||
*
|
||||
* @param owner owner of the ACL.
|
||||
* @param name name of this ACL.
|
||||
*/
|
||||
public AclImpl (PrincipalImpl owner, String name) {
|
||||
super(owner);
|
||||
entryList = new Vector<>();
|
||||
aclName = name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the name of this ACL.
|
||||
*
|
||||
* @param caller the principal invoking this method. It must be an owner
|
||||
* of this ACL.
|
||||
* @param name the name to be given to this ACL.
|
||||
*
|
||||
* @exception NotOwnerException if the caller principal is not an owner
|
||||
* of this ACL.
|
||||
* @see java.security.Principal
|
||||
*/
|
||||
@Override
|
||||
public void setName(Principal caller, String name)
|
||||
throws NotOwnerException {
|
||||
if (!isOwner(caller))
|
||||
throw new NotOwnerException();
|
||||
aclName = name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the name of this ACL.
|
||||
*
|
||||
* @return the name of this ACL.
|
||||
*/
|
||||
@Override
|
||||
public String getName(){
|
||||
return aclName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds an ACL entry to this ACL. An entry associates a principal (e.g., an individual or a group)
|
||||
* with a set of permissions. Each principal can have at most one positive ACL entry
|
||||
* (specifying permissions to be granted to the principal) and one negative ACL entry
|
||||
* (specifying permissions to be denied). If there is already an ACL entry
|
||||
* of the same type (negative or positive) already in the ACL, false is returned.
|
||||
*
|
||||
* @param caller the principal invoking this method. It must be an owner
|
||||
* of this ACL.
|
||||
* @param entry the ACL entry to be added to this ACL.
|
||||
* @return true on success, false if an entry of the same type (positive
|
||||
* or negative) for the same principal is already present in this ACL.
|
||||
* @exception NotOwnerException if the caller principal is not an owner of
|
||||
* this ACL.
|
||||
* @see java.security.Principal
|
||||
*/
|
||||
@Override
|
||||
public boolean addEntry(Principal caller, AclEntry entry)
|
||||
throws NotOwnerException {
|
||||
if (!isOwner(caller))
|
||||
throw new NotOwnerException();
|
||||
|
||||
if (entryList.contains(entry))
|
||||
return false;
|
||||
/*
|
||||
for (Enumeration e = entryList.elements();e.hasMoreElements();){
|
||||
AclEntry ent = (AclEntry) e.nextElement();
|
||||
if (ent.getPrincipal().equals(entry.getPrincipal()))
|
||||
return false;
|
||||
}
|
||||
*/
|
||||
|
||||
entryList.addElement(entry);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes an ACL entry from this ACL.
|
||||
*
|
||||
* @param caller the principal invoking this method. It must be an owner
|
||||
* of this ACL.
|
||||
* @param entry the ACL entry to be removed from this ACL.
|
||||
* @return true on success, false if the entry is not part of this ACL.
|
||||
* @exception NotOwnerException if the caller principal is not an owner
|
||||
* of this Acl.
|
||||
* @see java.security.Principal
|
||||
* @see java.security.acl.AclEntry
|
||||
*/
|
||||
@Override
|
||||
public boolean removeEntry(Principal caller, AclEntry entry)
|
||||
throws NotOwnerException {
|
||||
if (!isOwner(caller))
|
||||
throw new NotOwnerException();
|
||||
|
||||
return (entryList.removeElement(entry));
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes all ACL entries from this ACL.
|
||||
*
|
||||
* @param caller the principal invoking this method. It must be an owner
|
||||
* of this ACL.
|
||||
* @exception NotOwnerException if the caller principal is not an owner of
|
||||
* this Acl.
|
||||
* @see java.security.Principal
|
||||
*/
|
||||
public void removeAll(Principal caller)
|
||||
throws NotOwnerException {
|
||||
if (!isOwner(caller))
|
||||
throw new NotOwnerException();
|
||||
entryList.removeAllElements();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an enumeration for the set of allowed permissions for
|
||||
* the specified principal
|
||||
* (representing an entity such as an individual or a group).
|
||||
* This set of allowed permissions is calculated as follows:
|
||||
* <UL>
|
||||
* <LI>If there is no entry in this Access Control List for the specified
|
||||
* principal, an empty permission set is returned.</LI>
|
||||
* <LI>Otherwise, the principal's group permission sets are determined.
|
||||
* (A principal can belong to one or more groups, where a group is a group
|
||||
* of principals, represented by the Group interface.)</LI>
|
||||
* </UL>
|
||||
* @param user the principal whose permission set is to be returned.
|
||||
* @return the permission set specifying the permissions the principal
|
||||
* is allowed.
|
||||
* @see java.security.Principal
|
||||
*/
|
||||
@Override
|
||||
public Enumeration<Permission> getPermissions(Principal user){
|
||||
Vector<Permission> empty = new Vector<>();
|
||||
for (Enumeration<AclEntry> e = entryList.elements();e.hasMoreElements();){
|
||||
AclEntry ent = e.nextElement();
|
||||
if (ent.getPrincipal().equals(user))
|
||||
return ent.permissions();
|
||||
}
|
||||
return empty.elements();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an enumeration of the entries in this ACL. Each element in the
|
||||
* enumeration is of type AclEntry.
|
||||
*
|
||||
* @return an enumeration of the entries in this ACL.
|
||||
*/
|
||||
@Override
|
||||
public Enumeration<AclEntry> entries(){
|
||||
return entryList.elements();
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether or not the specified principal has the specified
|
||||
* permission.
|
||||
* If it does, true is returned, otherwise false is returned.
|
||||
* More specifically, this method checks whether the passed permission
|
||||
* is a member of the allowed permission set of the specified principal.
|
||||
* The allowed permission set is determined by the same algorithm as is
|
||||
* used by the getPermissions method.
|
||||
*
|
||||
* @param user the principal, assumed to be a valid authenticated Principal.
|
||||
* @param perm the permission to be checked for.
|
||||
* @return true if the principal has the specified permission,
|
||||
* false otherwise.
|
||||
* @see java.security.Principal
|
||||
* @see java.security.Permission
|
||||
*/
|
||||
@Override
|
||||
public boolean checkPermission(Principal user,
|
||||
java.security.acl.Permission perm) {
|
||||
for (Enumeration<AclEntry> e = entryList.elements();e.hasMoreElements();){
|
||||
AclEntry ent = e.nextElement();
|
||||
if (ent.getPrincipal().equals(user))
|
||||
if (ent.checkPermission(perm)) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether or not the specified principal has the specified
|
||||
* permission.
|
||||
* If it does, true is returned, otherwise false is returned.
|
||||
* More specifically, this method checks whether the passed permission
|
||||
* is a member of the allowed permission set of the specified principal.
|
||||
* The allowed permission set is determined by the same algorithm as is
|
||||
* used by the getPermissions method.
|
||||
*
|
||||
* @param user the principal, assumed to be a valid authenticated Principal.
|
||||
* @param community the community name associated with the principal.
|
||||
* @param perm the permission to be checked for.
|
||||
* @return true if the principal has the specified permission, false
|
||||
* otherwise.
|
||||
* @see java.security.Principal
|
||||
* @see java.security.Permission
|
||||
*/
|
||||
public boolean checkPermission(Principal user, String community,
|
||||
java.security.acl.Permission perm) {
|
||||
for (Enumeration<AclEntry> e = entryList.elements();e.hasMoreElements();){
|
||||
AclEntryImpl ent = (AclEntryImpl) e.nextElement();
|
||||
if (ent.getPrincipal().equals(user))
|
||||
if (ent.checkPermission(perm) && ent.checkCommunity(community)) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether or not the specified community string is defined.
|
||||
*
|
||||
* @param community the community name associated with the principal.
|
||||
*
|
||||
* @return true if the specified community string is defined, false
|
||||
* otherwise.
|
||||
* @see java.security.Principal
|
||||
* @see java.security.Permission
|
||||
*/
|
||||
public boolean checkCommunity(String community) {
|
||||
for (Enumeration<AclEntry> e = entryList.elements();e.hasMoreElements();){
|
||||
AclEntryImpl ent = (AclEntryImpl) e.nextElement();
|
||||
if (ent.checkCommunity(community)) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a string representation of the ACL contents.
|
||||
*
|
||||
* @return a string representation of the ACL contents.
|
||||
*/
|
||||
@Override
|
||||
public String toString(){
|
||||
return ("AclImpl: "+ getName());
|
||||
}
|
||||
}
|
||||
142
jdkSrc/jdk8/com/sun/jmx/snmp/IPAcl/GroupImpl.java
Normal file
142
jdkSrc/jdk8/com/sun/jmx/snmp/IPAcl/GroupImpl.java
Normal file
@@ -0,0 +1,142 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2007, 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.snmp.IPAcl;
|
||||
|
||||
|
||||
|
||||
import java.util.Vector;
|
||||
import java.util.Enumeration;
|
||||
import java.io.Serializable;
|
||||
import java.net.UnknownHostException;
|
||||
|
||||
|
||||
import java.security.Principal;
|
||||
import java.security.acl.Group;
|
||||
|
||||
|
||||
/**
|
||||
* This class is used to represent a subnet mask (a group of hosts
|
||||
* matching the same
|
||||
* IP mask).
|
||||
*
|
||||
*/
|
||||
|
||||
class GroupImpl extends PrincipalImpl implements Group, Serializable {
|
||||
private static final long serialVersionUID = -7777387035032541168L;
|
||||
|
||||
/**
|
||||
* Constructs an empty group.
|
||||
* @exception UnknownHostException Not implemented
|
||||
*/
|
||||
public GroupImpl () throws UnknownHostException {
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a group using the specified subnet mask.
|
||||
*
|
||||
* @param mask The subnet mask to use to build the group.
|
||||
* @exception UnknownHostException if the subnet mask cann't be built.
|
||||
*/
|
||||
public GroupImpl (String mask) throws UnknownHostException {
|
||||
super(mask);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the specified member to the group.
|
||||
*
|
||||
* @param p the principal to add to this group.
|
||||
* @return true if the member was successfully added, false if the
|
||||
* principal was already a member.
|
||||
*/
|
||||
public boolean addMember(Principal p) {
|
||||
// we don't need to add members because the ip address is a
|
||||
// subnet mask
|
||||
return true;
|
||||
}
|
||||
|
||||
public int hashCode() {
|
||||
return super.hashCode();
|
||||
}
|
||||
|
||||
/**
|
||||
* Compares this group to the specified object. Returns true if the object
|
||||
* passed in matches the group represented.
|
||||
*
|
||||
* @param p the object to compare with.
|
||||
* @return true if the object passed in matches the subnet mask,
|
||||
* false otherwise.
|
||||
*/
|
||||
public boolean equals (Object p) {
|
||||
if (p instanceof PrincipalImpl || p instanceof GroupImpl){
|
||||
if ((super.hashCode() & p.hashCode()) == p.hashCode()) return true;
|
||||
else return false;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the passed principal is a member of the group.
|
||||
*
|
||||
* @param p the principal whose membership is to be checked.
|
||||
* @return true if the principal is a member of this group, false otherwise.
|
||||
*/
|
||||
public boolean isMember(Principal p) {
|
||||
if ((p.hashCode() & super.hashCode()) == p.hashCode()) return true;
|
||||
else return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an enumeration which contains the subnet mask.
|
||||
*
|
||||
* @return an enumeration which contains the subnet mask.
|
||||
*/
|
||||
public Enumeration<? extends Principal> members(){
|
||||
Vector<Principal> v = new Vector<Principal>(1);
|
||||
v.addElement(this);
|
||||
return v.elements();
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the specified member from the group. (Not implemented)
|
||||
*
|
||||
* @param p the principal to remove from this group.
|
||||
* @return allways return true.
|
||||
*/
|
||||
public boolean removeMember(Principal p) {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prints a string representation of this group.
|
||||
*
|
||||
* @return a string representation of this group.
|
||||
*/
|
||||
public String toString() {
|
||||
return ("GroupImpl :"+super.getAddress().toString());
|
||||
}
|
||||
}
|
||||
181
jdkSrc/jdk8/com/sun/jmx/snmp/IPAcl/Host.java
Normal file
181
jdkSrc/jdk8/com/sun/jmx/snmp/IPAcl/Host.java
Normal file
@@ -0,0 +1,181 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2007, 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.snmp.IPAcl;
|
||||
|
||||
|
||||
|
||||
// java import
|
||||
//
|
||||
import java.io.Serializable;
|
||||
import java.net.InetAddress;
|
||||
import java.net.UnknownHostException;
|
||||
import java.util.Hashtable;
|
||||
import java.util.logging.Level;
|
||||
import java.util.Vector;
|
||||
import java.security.acl.NotOwnerException;
|
||||
|
||||
import static com.sun.jmx.defaults.JmxProperties.SNMP_LOGGER;
|
||||
|
||||
/**
|
||||
* The class defines an abstract representation of a host.
|
||||
*
|
||||
*/
|
||||
abstract class Host extends SimpleNode implements Serializable {
|
||||
|
||||
public Host(int id) {
|
||||
super(id);
|
||||
}
|
||||
|
||||
public Host(Parser p, int id) {
|
||||
super(p, id);
|
||||
}
|
||||
|
||||
protected abstract PrincipalImpl createAssociatedPrincipal()
|
||||
throws UnknownHostException;
|
||||
|
||||
protected abstract String getHname();
|
||||
|
||||
public void buildAclEntries(PrincipalImpl owner, AclImpl acl) {
|
||||
// Create a principal
|
||||
//
|
||||
PrincipalImpl p=null;
|
||||
try {
|
||||
p = createAssociatedPrincipal();
|
||||
} catch(UnknownHostException e) {
|
||||
if (SNMP_LOGGER.isLoggable(Level.FINEST)) {
|
||||
SNMP_LOGGER.logp(Level.FINEST, Host.class.getName(),
|
||||
"buildAclEntries",
|
||||
"Cannot create ACL entry; got exception", e);
|
||||
}
|
||||
throw new IllegalArgumentException("Cannot create ACL entry for " + e.getMessage());
|
||||
}
|
||||
|
||||
// Create an AclEntry
|
||||
//
|
||||
AclEntryImpl entry= null;
|
||||
try {
|
||||
entry = new AclEntryImpl(p);
|
||||
// Add permission
|
||||
//
|
||||
registerPermission(entry);
|
||||
acl.addEntry(owner, entry);
|
||||
} catch(UnknownHostException e) {
|
||||
if (SNMP_LOGGER.isLoggable(Level.FINEST)) {
|
||||
SNMP_LOGGER.logp(Level.FINEST, Host.class.getName(),
|
||||
"buildAclEntries",
|
||||
"Cannot create ACL entry; got exception", e);
|
||||
}
|
||||
return;
|
||||
} catch(NotOwnerException a) {
|
||||
if (SNMP_LOGGER.isLoggable(Level.FINEST)) {
|
||||
SNMP_LOGGER.logp(Level.FINEST, Host.class.getName(),
|
||||
"buildAclEntries",
|
||||
"Cannot create ACL entry; got exception", a);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
private void registerPermission(AclEntryImpl entry) {
|
||||
JDMHost host= (JDMHost) jjtGetParent();
|
||||
JDMManagers manager= (JDMManagers) host.jjtGetParent();
|
||||
JDMAclItem acl= (JDMAclItem) manager.jjtGetParent();
|
||||
JDMAccess access= acl.getAccess();
|
||||
access.putPermission(entry);
|
||||
JDMCommunities comm= acl.getCommunities();
|
||||
comm.buildCommunities(entry);
|
||||
}
|
||||
|
||||
public void buildTrapEntries(Hashtable<InetAddress, Vector<String>> dest) {
|
||||
|
||||
JDMHostTrap host= (JDMHostTrap) jjtGetParent();
|
||||
JDMTrapInterestedHost hosts= (JDMTrapInterestedHost) host.jjtGetParent();
|
||||
JDMTrapItem trap = (JDMTrapItem) hosts.jjtGetParent();
|
||||
JDMTrapCommunity community = trap.getCommunity();
|
||||
String comm = community.getCommunity();
|
||||
|
||||
InetAddress add = null;
|
||||
try {
|
||||
add = java.net.InetAddress.getByName(getHname());
|
||||
} catch(UnknownHostException e) {
|
||||
if (SNMP_LOGGER.isLoggable(Level.FINEST)) {
|
||||
SNMP_LOGGER.logp(Level.FINEST, Host.class.getName(),
|
||||
"buildTrapEntries",
|
||||
"Cannot create TRAP entry; got exception", e);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
Vector<String> list = null;
|
||||
if (dest.containsKey(add)){
|
||||
list = dest.get(add);
|
||||
if (!list.contains(comm)){
|
||||
list.addElement(comm);
|
||||
}
|
||||
} else {
|
||||
list = new Vector<String>();
|
||||
list.addElement(comm);
|
||||
dest.put(add,list);
|
||||
}
|
||||
}
|
||||
|
||||
public void buildInformEntries(Hashtable<InetAddress, Vector<String>> dest) {
|
||||
|
||||
JDMHostInform host= (JDMHostInform) jjtGetParent();
|
||||
JDMInformInterestedHost hosts= (JDMInformInterestedHost) host.jjtGetParent();
|
||||
JDMInformItem inform = (JDMInformItem) hosts.jjtGetParent();
|
||||
JDMInformCommunity community = inform.getCommunity();
|
||||
String comm = community.getCommunity();
|
||||
|
||||
InetAddress add = null;
|
||||
try {
|
||||
add = java.net.InetAddress.getByName(getHname());
|
||||
} catch(UnknownHostException e) {
|
||||
if (SNMP_LOGGER.isLoggable(Level.FINEST)) {
|
||||
SNMP_LOGGER.logp(Level.FINEST, Host.class.getName(),
|
||||
"buildTrapEntries",
|
||||
"Cannot create INFORM entry; got exception", e);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
Vector<String> list = null;
|
||||
if (dest.containsKey(add)){
|
||||
list = dest.get(add);
|
||||
if (!list.contains(comm)){
|
||||
list.addElement(comm);
|
||||
}
|
||||
} else {
|
||||
list = new Vector<String>();
|
||||
list.addElement(comm);
|
||||
dest.put(add,list);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
64
jdkSrc/jdk8/com/sun/jmx/snmp/IPAcl/JDMAccess.java
Normal file
64
jdkSrc/jdk8/com/sun/jmx/snmp/IPAcl/JDMAccess.java
Normal file
@@ -0,0 +1,64 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2007, 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.
|
||||
*/
|
||||
|
||||
|
||||
/* Generated By:JJTree: Do not edit this line. JDMAccess.java */
|
||||
|
||||
package com.sun.jmx.snmp.IPAcl;
|
||||
|
||||
|
||||
class JDMAccess extends SimpleNode {
|
||||
protected int access= -1;
|
||||
|
||||
JDMAccess(int id) {
|
||||
super(id);
|
||||
}
|
||||
|
||||
JDMAccess(Parser p, int id) {
|
||||
super(p, id);
|
||||
}
|
||||
|
||||
public static Node jjtCreate(int id) {
|
||||
return new JDMAccess(id);
|
||||
}
|
||||
|
||||
public static Node jjtCreate(Parser p, int id) {
|
||||
return new JDMAccess(p, id);
|
||||
}
|
||||
|
||||
protected void putPermission(AclEntryImpl entry) {
|
||||
if (access == ParserConstants.RO) {
|
||||
// We have a read-only access.
|
||||
//
|
||||
entry.addPermission(com.sun.jmx.snmp.IPAcl.SnmpAcl.getREAD());
|
||||
}
|
||||
if (access == ParserConstants.RW) {
|
||||
// We have a read-write access.
|
||||
//
|
||||
entry.addPermission(com.sun.jmx.snmp.IPAcl.SnmpAcl.getREAD());
|
||||
entry.addPermission(com.sun.jmx.snmp.IPAcl.SnmpAcl.getWRITE());
|
||||
}
|
||||
}
|
||||
}
|
||||
65
jdkSrc/jdk8/com/sun/jmx/snmp/IPAcl/JDMAclBlock.java
Normal file
65
jdkSrc/jdk8/com/sun/jmx/snmp/IPAcl/JDMAclBlock.java
Normal file
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
|
||||
/* Generated By:JJTree: Do not edit this line. JDMAclBlock.java */
|
||||
|
||||
package com.sun.jmx.snmp.IPAcl;
|
||||
|
||||
import java.net.InetAddress;
|
||||
import java.util.Hashtable;
|
||||
import java.util.Vector;
|
||||
|
||||
class JDMAclBlock extends SimpleNode {
|
||||
JDMAclBlock(int id) {
|
||||
super(id);
|
||||
}
|
||||
|
||||
JDMAclBlock(Parser p, int id) {
|
||||
super(p, id);
|
||||
}
|
||||
|
||||
public static Node jjtCreate(int id) {
|
||||
return new JDMAclBlock(id);
|
||||
}
|
||||
|
||||
public static Node jjtCreate(Parser p, int id) {
|
||||
return new JDMAclBlock(p, id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Do no need to go through this part of the tree for
|
||||
* building TrapEntry.
|
||||
*/
|
||||
@Override
|
||||
public void buildTrapEntries(Hashtable<InetAddress, Vector<String>> dest) {}
|
||||
|
||||
/**
|
||||
* Do no need to go through this part of the tree for
|
||||
* building InformEntry.
|
||||
*/
|
||||
@Override
|
||||
public void buildInformEntries(Hashtable<InetAddress, Vector<String>> dest) {}
|
||||
}
|
||||
58
jdkSrc/jdk8/com/sun/jmx/snmp/IPAcl/JDMAclItem.java
Normal file
58
jdkSrc/jdk8/com/sun/jmx/snmp/IPAcl/JDMAclItem.java
Normal file
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2007, 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.
|
||||
*/
|
||||
|
||||
|
||||
/* Generated By:JJTree: Do not edit this line. JDMAclItem.java */
|
||||
|
||||
package com.sun.jmx.snmp.IPAcl;
|
||||
|
||||
class JDMAclItem extends SimpleNode {
|
||||
protected JDMAccess access= null;
|
||||
protected JDMCommunities com= null;
|
||||
|
||||
JDMAclItem(int id) {
|
||||
super(id);
|
||||
}
|
||||
|
||||
JDMAclItem(Parser p, int id) {
|
||||
super(p, id);
|
||||
}
|
||||
|
||||
public static Node jjtCreate(int id) {
|
||||
return new JDMAclItem(id);
|
||||
}
|
||||
|
||||
public static Node jjtCreate(Parser p, int id) {
|
||||
return new JDMAclItem(p, id);
|
||||
}
|
||||
|
||||
public JDMAccess getAccess() {
|
||||
return access;
|
||||
}
|
||||
|
||||
public JDMCommunities getCommunities() {
|
||||
return com;
|
||||
}
|
||||
}
|
||||
53
jdkSrc/jdk8/com/sun/jmx/snmp/IPAcl/JDMCommunities.java
Normal file
53
jdkSrc/jdk8/com/sun/jmx/snmp/IPAcl/JDMCommunities.java
Normal file
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2007, 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.
|
||||
*/
|
||||
|
||||
|
||||
/* Generated By:JJTree: Do not edit this line. JDMCommunities.java */
|
||||
|
||||
package com.sun.jmx.snmp.IPAcl;
|
||||
|
||||
|
||||
class JDMCommunities extends SimpleNode {
|
||||
JDMCommunities(int id) {
|
||||
super(id);
|
||||
}
|
||||
|
||||
JDMCommunities(Parser p, int id) {
|
||||
super(p, id);
|
||||
}
|
||||
|
||||
public static Node jjtCreate(int id) {
|
||||
return new JDMCommunities(id);
|
||||
}
|
||||
|
||||
public static Node jjtCreate(Parser p, int id) {
|
||||
return new JDMCommunities(p, id);
|
||||
}
|
||||
|
||||
public void buildCommunities(AclEntryImpl entry){
|
||||
for (int i =0 ; i < children.length ; i++)
|
||||
entry.addCommunity(((JDMCommunity)children[i]).getCommunity());
|
||||
}
|
||||
}
|
||||
53
jdkSrc/jdk8/com/sun/jmx/snmp/IPAcl/JDMCommunity.java
Normal file
53
jdkSrc/jdk8/com/sun/jmx/snmp/IPAcl/JDMCommunity.java
Normal file
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2007, 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.
|
||||
*/
|
||||
|
||||
|
||||
/* Generated By:JJTree: Do not edit this line. JDMCommunity.java */
|
||||
|
||||
package com.sun.jmx.snmp.IPAcl;
|
||||
|
||||
class JDMCommunity extends SimpleNode {
|
||||
protected String communityString= "";
|
||||
|
||||
JDMCommunity(int id) {
|
||||
super(id);
|
||||
}
|
||||
|
||||
JDMCommunity(Parser p, int id) {
|
||||
super(p, id);
|
||||
}
|
||||
|
||||
public static Node jjtCreate(int id) {
|
||||
return new JDMCommunity(id);
|
||||
}
|
||||
|
||||
public static Node jjtCreate(Parser p, int id) {
|
||||
return new JDMCommunity(p, id);
|
||||
}
|
||||
|
||||
public String getCommunity(){
|
||||
return communityString;
|
||||
}
|
||||
}
|
||||
49
jdkSrc/jdk8/com/sun/jmx/snmp/IPAcl/JDMEnterprise.java
Normal file
49
jdkSrc/jdk8/com/sun/jmx/snmp/IPAcl/JDMEnterprise.java
Normal file
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2007, 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.
|
||||
*/
|
||||
|
||||
|
||||
/* Generated By:JJTree: Do not edit this line. JDMEnterprise.java */
|
||||
|
||||
package com.sun.jmx.snmp.IPAcl;
|
||||
|
||||
class JDMEnterprise extends SimpleNode {
|
||||
protected String enterprise= "";
|
||||
|
||||
JDMEnterprise(int id) {
|
||||
super(id);
|
||||
}
|
||||
|
||||
JDMEnterprise(Parser p, int id) {
|
||||
super(p, id);
|
||||
}
|
||||
|
||||
public static Node jjtCreate(int id) {
|
||||
return new JDMEnterprise(id);
|
||||
}
|
||||
|
||||
public static Node jjtCreate(Parser p, int id) {
|
||||
return new JDMEnterprise(p, id);
|
||||
}
|
||||
}
|
||||
51
jdkSrc/jdk8/com/sun/jmx/snmp/IPAcl/JDMHost.java
Normal file
51
jdkSrc/jdk8/com/sun/jmx/snmp/IPAcl/JDMHost.java
Normal file
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2007, 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.
|
||||
*/
|
||||
|
||||
|
||||
/* Generated By:JJTree: Do not edit this line. JDMHost.java */
|
||||
|
||||
package com.sun.jmx.snmp.IPAcl;
|
||||
|
||||
|
||||
class JDMHost extends SimpleNode {
|
||||
|
||||
JDMHost(int id) {
|
||||
super(id);
|
||||
}
|
||||
|
||||
JDMHost(Parser p, int id) {
|
||||
super(p, id);
|
||||
}
|
||||
|
||||
public static Node jjtCreate(int id) {
|
||||
return new JDMHost(id);
|
||||
}
|
||||
|
||||
public static Node jjtCreate(Parser p, int id) {
|
||||
return new JDMHost(p, id);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
48
jdkSrc/jdk8/com/sun/jmx/snmp/IPAcl/JDMHostInform.java
Normal file
48
jdkSrc/jdk8/com/sun/jmx/snmp/IPAcl/JDMHostInform.java
Normal file
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/* Generated By:JJTree: Do not edit this line. JDMHostInform.java */
|
||||
|
||||
package com.sun.jmx.snmp.IPAcl;
|
||||
|
||||
class JDMHostInform extends SimpleNode {
|
||||
protected String name= "";
|
||||
|
||||
JDMHostInform(int id) {
|
||||
super(id);
|
||||
}
|
||||
|
||||
JDMHostInform(Parser p, int id) {
|
||||
super(p, id);
|
||||
}
|
||||
|
||||
public static Node jjtCreate(int id) {
|
||||
return new JDMHostInform(id);
|
||||
}
|
||||
|
||||
public static Node jjtCreate(Parser p, int id) {
|
||||
return new JDMHostInform(p, id);
|
||||
}
|
||||
}
|
||||
62
jdkSrc/jdk8/com/sun/jmx/snmp/IPAcl/JDMHostName.java
Normal file
62
jdkSrc/jdk8/com/sun/jmx/snmp/IPAcl/JDMHostName.java
Normal file
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2007, 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.
|
||||
*/
|
||||
|
||||
|
||||
/* Generated By:JJTree: Do not edit this line. JDMHostName.java */
|
||||
|
||||
package com.sun.jmx.snmp.IPAcl;
|
||||
|
||||
import java.net.UnknownHostException;
|
||||
|
||||
class JDMHostName extends Host {
|
||||
private static final long serialVersionUID = -9120082068923591122L;
|
||||
|
||||
protected StringBuffer name = new StringBuffer();
|
||||
|
||||
JDMHostName(int id) {
|
||||
super(id);
|
||||
}
|
||||
|
||||
JDMHostName(Parser p, int id) {
|
||||
super(p, id);
|
||||
}
|
||||
|
||||
public static Node jjtCreate(int id) {
|
||||
return new JDMHostName(id);
|
||||
}
|
||||
|
||||
public static Node jjtCreate(Parser p, int id) {
|
||||
return new JDMHostName(p, id);
|
||||
}
|
||||
|
||||
protected String getHname() {
|
||||
return name.toString();
|
||||
}
|
||||
|
||||
protected PrincipalImpl createAssociatedPrincipal()
|
||||
throws UnknownHostException {
|
||||
return new PrincipalImpl(name.toString());
|
||||
}
|
||||
}
|
||||
49
jdkSrc/jdk8/com/sun/jmx/snmp/IPAcl/JDMHostTrap.java
Normal file
49
jdkSrc/jdk8/com/sun/jmx/snmp/IPAcl/JDMHostTrap.java
Normal file
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2007, 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.
|
||||
*/
|
||||
|
||||
|
||||
/* Generated By:JJTree: Do not edit this line. JDMHostTrap.java */
|
||||
|
||||
package com.sun.jmx.snmp.IPAcl;
|
||||
|
||||
class JDMHostTrap extends SimpleNode {
|
||||
protected String name= "";
|
||||
|
||||
JDMHostTrap(int id) {
|
||||
super(id);
|
||||
}
|
||||
|
||||
JDMHostTrap(Parser p, int id) {
|
||||
super(p, id);
|
||||
}
|
||||
|
||||
public static Node jjtCreate(int id) {
|
||||
return new JDMHostTrap(id);
|
||||
}
|
||||
|
||||
public static Node jjtCreate(Parser p, int id) {
|
||||
return new JDMHostTrap(p, id);
|
||||
}
|
||||
}
|
||||
64
jdkSrc/jdk8/com/sun/jmx/snmp/IPAcl/JDMInformBlock.java
Normal file
64
jdkSrc/jdk8/com/sun/jmx/snmp/IPAcl/JDMInformBlock.java
Normal file
@@ -0,0 +1,64 @@
|
||||
/*
|
||||
* Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/* Generated By:JJTree: Do not edit this line. JDMInformBlock.java */
|
||||
|
||||
package com.sun.jmx.snmp.IPAcl;
|
||||
|
||||
import java.net.InetAddress;
|
||||
import java.util.Hashtable;
|
||||
import java.util.Vector;
|
||||
|
||||
class JDMInformBlock extends SimpleNode {
|
||||
JDMInformBlock(int id) {
|
||||
super(id);
|
||||
}
|
||||
|
||||
JDMInformBlock(Parser p, int id) {
|
||||
super(p, id);
|
||||
}
|
||||
|
||||
public static Node jjtCreate(int id) {
|
||||
return new JDMInformBlock(id);
|
||||
}
|
||||
|
||||
public static Node jjtCreate(Parser p, int id) {
|
||||
return new JDMInformBlock(p, id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Do no need to go through this part of the tree for
|
||||
* building AclEntry.
|
||||
*/
|
||||
@Override
|
||||
public void buildAclEntries(PrincipalImpl owner, AclImpl acl) {}
|
||||
|
||||
/**
|
||||
* Do no need to go through this part of the tree for
|
||||
* building TrapEntry.
|
||||
*/
|
||||
@Override
|
||||
public void buildTrapEntries(Hashtable<InetAddress, Vector<String>> dest) {}
|
||||
}
|
||||
51
jdkSrc/jdk8/com/sun/jmx/snmp/IPAcl/JDMInformCommunity.java
Normal file
51
jdkSrc/jdk8/com/sun/jmx/snmp/IPAcl/JDMInformCommunity.java
Normal file
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/* Generated By:JJTree: Do not edit this line. JDMInformCommunity.java */
|
||||
|
||||
package com.sun.jmx.snmp.IPAcl;
|
||||
|
||||
class JDMInformCommunity extends SimpleNode {
|
||||
protected String community= "";
|
||||
JDMInformCommunity(int id) {
|
||||
super(id);
|
||||
}
|
||||
|
||||
JDMInformCommunity(Parser p, int id) {
|
||||
super(p, id);
|
||||
}
|
||||
|
||||
public static Node jjtCreate(int id) {
|
||||
return new JDMInformCommunity(id);
|
||||
}
|
||||
|
||||
public static Node jjtCreate(Parser p, int id) {
|
||||
return new JDMInformCommunity(p, id);
|
||||
}
|
||||
|
||||
public String getCommunity() {
|
||||
return community;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/* Generated By:JJTree: Do not edit this line. JDMInformInterestedHost.java */
|
||||
|
||||
package com.sun.jmx.snmp.IPAcl;
|
||||
|
||||
class JDMInformInterestedHost extends SimpleNode {
|
||||
JDMInformInterestedHost(int id) {
|
||||
super(id);
|
||||
}
|
||||
|
||||
JDMInformInterestedHost(Parser p, int id) {
|
||||
super(p, id);
|
||||
}
|
||||
|
||||
public static Node jjtCreate(int id) {
|
||||
return new JDMInformInterestedHost(id);
|
||||
}
|
||||
|
||||
public static Node jjtCreate(Parser p, int id) {
|
||||
return new JDMInformInterestedHost(p, id);
|
||||
}
|
||||
}
|
||||
51
jdkSrc/jdk8/com/sun/jmx/snmp/IPAcl/JDMInformItem.java
Normal file
51
jdkSrc/jdk8/com/sun/jmx/snmp/IPAcl/JDMInformItem.java
Normal file
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/* Generated By:JJTree: Do not edit this line. JDMInformItem.java */
|
||||
|
||||
package com.sun.jmx.snmp.IPAcl;
|
||||
|
||||
class JDMInformItem extends SimpleNode {
|
||||
protected JDMInformCommunity comm = null;
|
||||
JDMInformItem(int id) {
|
||||
super(id);
|
||||
}
|
||||
|
||||
JDMInformItem(Parser p, int id) {
|
||||
super(p, id);
|
||||
}
|
||||
|
||||
public static Node jjtCreate(int id) {
|
||||
return new JDMInformItem(id);
|
||||
}
|
||||
|
||||
public static Node jjtCreate(Parser p, int id) {
|
||||
return new JDMInformItem(p, id);
|
||||
}
|
||||
|
||||
public JDMInformCommunity getCommunity(){
|
||||
return comm;
|
||||
}
|
||||
}
|
||||
63
jdkSrc/jdk8/com/sun/jmx/snmp/IPAcl/JDMIpAddress.java
Normal file
63
jdkSrc/jdk8/com/sun/jmx/snmp/IPAcl/JDMIpAddress.java
Normal file
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2007, 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.
|
||||
*/
|
||||
|
||||
|
||||
/* Generated By:JJTree: Do not edit this line. JDMIpAddress.java */
|
||||
|
||||
package com.sun.jmx.snmp.IPAcl;
|
||||
|
||||
import java.lang.StringBuffer;
|
||||
import java.net.UnknownHostException;
|
||||
|
||||
class JDMIpAddress extends Host {
|
||||
private static final long serialVersionUID = 849729919486384484L;
|
||||
|
||||
protected StringBuffer address= new StringBuffer();
|
||||
|
||||
JDMIpAddress(int id) {
|
||||
super(id);
|
||||
}
|
||||
|
||||
JDMIpAddress(Parser p, int id) {
|
||||
super(p, id);
|
||||
}
|
||||
|
||||
public static Node jjtCreate(int id) {
|
||||
return new JDMIpAddress(id);
|
||||
}
|
||||
|
||||
public static Node jjtCreate(Parser p, int id) {
|
||||
return new JDMIpAddress(p, id);
|
||||
}
|
||||
|
||||
protected String getHname() {
|
||||
return address.toString();
|
||||
}
|
||||
|
||||
protected PrincipalImpl createAssociatedPrincipal()
|
||||
throws UnknownHostException {
|
||||
return new PrincipalImpl(address.toString());
|
||||
}
|
||||
}
|
||||
63
jdkSrc/jdk8/com/sun/jmx/snmp/IPAcl/JDMIpMask.java
Normal file
63
jdkSrc/jdk8/com/sun/jmx/snmp/IPAcl/JDMIpMask.java
Normal file
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2007, 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.
|
||||
*/
|
||||
|
||||
|
||||
/* Generated By:JJTree: Do not edit this line. JDMIpMask.java */
|
||||
|
||||
package com.sun.jmx.snmp.IPAcl;
|
||||
|
||||
import java.lang.StringBuffer;
|
||||
import java.net.UnknownHostException;
|
||||
|
||||
class JDMIpMask extends Host {
|
||||
private static final long serialVersionUID = -8211312690652331386L;
|
||||
|
||||
protected StringBuffer address= new StringBuffer();
|
||||
|
||||
JDMIpMask(int id) {
|
||||
super(id);
|
||||
}
|
||||
|
||||
JDMIpMask(Parser p, int id) {
|
||||
super(p, id);
|
||||
}
|
||||
|
||||
public static Node jjtCreate(int id) {
|
||||
return new JDMIpMask(id);
|
||||
}
|
||||
|
||||
public static Node jjtCreate(Parser p, int id) {
|
||||
return new JDMIpMask(p, id);
|
||||
}
|
||||
|
||||
protected String getHname() {
|
||||
return address.toString();
|
||||
}
|
||||
|
||||
protected PrincipalImpl createAssociatedPrincipal()
|
||||
throws UnknownHostException {
|
||||
return new GroupImpl(address.toString());
|
||||
}
|
||||
}
|
||||
41
jdkSrc/jdk8/com/sun/jmx/snmp/IPAcl/JDMIpV6Address.java
Normal file
41
jdkSrc/jdk8/com/sun/jmx/snmp/IPAcl/JDMIpV6Address.java
Normal file
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* Copyright (c) 2002, 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.
|
||||
*/
|
||||
|
||||
/* Generated By:JJTree: Do not edit this line. JDMIpV6Address.java */
|
||||
|
||||
package com.sun.jmx.snmp.IPAcl;
|
||||
|
||||
class JDMIpV6Address extends JDMIpAddress {
|
||||
private static final long serialVersionUID = -5929917334606674243L;
|
||||
|
||||
public JDMIpV6Address(int id) {
|
||||
super(id);
|
||||
}
|
||||
|
||||
public JDMIpV6Address(Parser p, int id) {
|
||||
super(p, id);
|
||||
}
|
||||
|
||||
}
|
||||
47
jdkSrc/jdk8/com/sun/jmx/snmp/IPAcl/JDMManagers.java
Normal file
47
jdkSrc/jdk8/com/sun/jmx/snmp/IPAcl/JDMManagers.java
Normal file
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2007, 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.
|
||||
*/
|
||||
|
||||
|
||||
/* Generated By:JJTree: Do not edit this line. JDMManagers.java */
|
||||
|
||||
package com.sun.jmx.snmp.IPAcl;
|
||||
|
||||
class JDMManagers extends SimpleNode {
|
||||
JDMManagers(int id) {
|
||||
super(id);
|
||||
}
|
||||
|
||||
JDMManagers(Parser p, int id) {
|
||||
super(p, id);
|
||||
}
|
||||
|
||||
public static Node jjtCreate(int id) {
|
||||
return new JDMManagers(id);
|
||||
}
|
||||
|
||||
public static Node jjtCreate(Parser p, int id) {
|
||||
return new JDMManagers(p, id);
|
||||
}
|
||||
}
|
||||
58
jdkSrc/jdk8/com/sun/jmx/snmp/IPAcl/JDMNetMask.java
Normal file
58
jdkSrc/jdk8/com/sun/jmx/snmp/IPAcl/JDMNetMask.java
Normal file
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
* Copyright (c) 2002, 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.
|
||||
*/
|
||||
/* Generated By:JJTree: Do not edit this line. JDMNetMask.java */
|
||||
|
||||
package com.sun.jmx.snmp.IPAcl;
|
||||
import java.net.UnknownHostException;
|
||||
|
||||
class JDMNetMask extends Host {
|
||||
private static final long serialVersionUID = -1979318280250821787L;
|
||||
|
||||
protected StringBuffer address= new StringBuffer();
|
||||
protected String mask = null;
|
||||
public JDMNetMask(int id) {
|
||||
super(id);
|
||||
}
|
||||
|
||||
public JDMNetMask(Parser p, int id) {
|
||||
super(p, id);
|
||||
}
|
||||
public static Node jjtCreate(int id) {
|
||||
return new JDMNetMask(id);
|
||||
}
|
||||
|
||||
public static Node jjtCreate(Parser p, int id) {
|
||||
return new JDMNetMask(p, id);
|
||||
}
|
||||
|
||||
protected String getHname() {
|
||||
return address.toString();
|
||||
}
|
||||
|
||||
protected PrincipalImpl createAssociatedPrincipal()
|
||||
throws UnknownHostException {
|
||||
return new NetMaskImpl(address.toString(), Integer.parseInt(mask));
|
||||
}
|
||||
}
|
||||
46
jdkSrc/jdk8/com/sun/jmx/snmp/IPAcl/JDMNetMaskV6.java
Normal file
46
jdkSrc/jdk8/com/sun/jmx/snmp/IPAcl/JDMNetMaskV6.java
Normal file
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* Copyright (c) 2002, 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.
|
||||
*/
|
||||
|
||||
/* Generated By:JJTree: Do not edit this line. JDMNetMaskV6.java */
|
||||
|
||||
package com.sun.jmx.snmp.IPAcl;
|
||||
|
||||
import java.net.UnknownHostException;
|
||||
|
||||
class JDMNetMaskV6 extends JDMNetMask {
|
||||
private static final long serialVersionUID = 4505256777680576645L;
|
||||
|
||||
public JDMNetMaskV6(int id) {
|
||||
super(id);
|
||||
}
|
||||
|
||||
public JDMNetMaskV6(Parser p, int id) {
|
||||
super(p, id);
|
||||
}
|
||||
protected PrincipalImpl createAssociatedPrincipal()
|
||||
throws UnknownHostException {
|
||||
return new NetMaskImpl(address.toString(), Integer.parseInt(mask));
|
||||
}
|
||||
}
|
||||
47
jdkSrc/jdk8/com/sun/jmx/snmp/IPAcl/JDMSecurityDefs.java
Normal file
47
jdkSrc/jdk8/com/sun/jmx/snmp/IPAcl/JDMSecurityDefs.java
Normal file
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2007, 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.
|
||||
*/
|
||||
|
||||
|
||||
/* Generated By:JJTree: Do not edit this line. JDMSecurityDefs.java */
|
||||
|
||||
package com.sun.jmx.snmp.IPAcl;
|
||||
|
||||
class JDMSecurityDefs extends SimpleNode {
|
||||
JDMSecurityDefs(int id) {
|
||||
super(id);
|
||||
}
|
||||
|
||||
JDMSecurityDefs(Parser p, int id) {
|
||||
super(p, id);
|
||||
}
|
||||
|
||||
public static Node jjtCreate(int id) {
|
||||
return new JDMSecurityDefs(id);
|
||||
}
|
||||
|
||||
public static Node jjtCreate(Parser p, int id) {
|
||||
return new JDMSecurityDefs(p, id);
|
||||
}
|
||||
}
|
||||
65
jdkSrc/jdk8/com/sun/jmx/snmp/IPAcl/JDMTrapBlock.java
Normal file
65
jdkSrc/jdk8/com/sun/jmx/snmp/IPAcl/JDMTrapBlock.java
Normal file
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
|
||||
/* Generated By:JJTree: Do not edit this line. JDMTrapBlock.java */
|
||||
|
||||
package com.sun.jmx.snmp.IPAcl;
|
||||
|
||||
import java.net.InetAddress;
|
||||
import java.util.Hashtable;
|
||||
import java.util.Vector;
|
||||
|
||||
class JDMTrapBlock extends SimpleNode {
|
||||
JDMTrapBlock(int id) {
|
||||
super(id);
|
||||
}
|
||||
|
||||
JDMTrapBlock(Parser p, int id) {
|
||||
super(p, id);
|
||||
}
|
||||
|
||||
public static Node jjtCreate(int id) {
|
||||
return new JDMTrapBlock(id);
|
||||
}
|
||||
|
||||
public static Node jjtCreate(Parser p, int id) {
|
||||
return new JDMTrapBlock(p, id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Do no need to go through this part of the tree for
|
||||
* building AclEntry.
|
||||
*/
|
||||
@Override
|
||||
public void buildAclEntries(PrincipalImpl owner, AclImpl acl) {}
|
||||
|
||||
/**
|
||||
* Do no need to go through this part of the tree for
|
||||
* building InformEntry.
|
||||
*/
|
||||
@Override
|
||||
public void buildInformEntries(Hashtable<InetAddress, Vector<String>> dest) {}
|
||||
}
|
||||
52
jdkSrc/jdk8/com/sun/jmx/snmp/IPAcl/JDMTrapCommunity.java
Normal file
52
jdkSrc/jdk8/com/sun/jmx/snmp/IPAcl/JDMTrapCommunity.java
Normal file
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2007, 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.
|
||||
*/
|
||||
|
||||
|
||||
/* Generated By:JJTree: Do not edit this line. JDMTrapCommunity.java */
|
||||
|
||||
package com.sun.jmx.snmp.IPAcl;
|
||||
|
||||
class JDMTrapCommunity extends SimpleNode {
|
||||
protected String community= "";
|
||||
JDMTrapCommunity(int id) {
|
||||
super(id);
|
||||
}
|
||||
|
||||
JDMTrapCommunity(Parser p, int id) {
|
||||
super(p, id);
|
||||
}
|
||||
|
||||
public static Node jjtCreate(int id) {
|
||||
return new JDMTrapCommunity(id);
|
||||
}
|
||||
|
||||
public static Node jjtCreate(Parser p, int id) {
|
||||
return new JDMTrapCommunity(p, id);
|
||||
}
|
||||
|
||||
public String getCommunity() {
|
||||
return community;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2007, 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.
|
||||
*/
|
||||
|
||||
|
||||
/* Generated By:JJTree: Do not edit this line. JDMTrapInterestedHost.java */
|
||||
|
||||
package com.sun.jmx.snmp.IPAcl;
|
||||
|
||||
class JDMTrapInterestedHost extends SimpleNode {
|
||||
JDMTrapInterestedHost(int id) {
|
||||
super(id);
|
||||
}
|
||||
|
||||
JDMTrapInterestedHost(Parser p, int id) {
|
||||
super(p, id);
|
||||
}
|
||||
|
||||
public static Node jjtCreate(int id) {
|
||||
return new JDMTrapInterestedHost(id);
|
||||
}
|
||||
|
||||
public static Node jjtCreate(Parser p, int id) {
|
||||
return new JDMTrapInterestedHost(p, id);
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user