OpenJDK / jdk / jdk
changeset 4156:acaa49a2768a
6851617: Remove JSR 255 (JMX API 2.0) from JDK 7
Summary: See http://weblogs.java.net/blog/2009/06/16/jsr-255-jmx-api-20-postponed
Reviewed-by: dfuchs
author | emcmanus |
---|---|
date | Wed, 21 Oct 2009 17:33:18 +0200 |
parents | 460e37d40f12 |
children | 9e3aae7675f1 |
files | jdk/make/docs/CORE_PKGS.gmk jdk/src/share/classes/com/sun/jmx/defaults/JmxProperties.java jdk/src/share/classes/com/sun/jmx/defaults/ServiceName.java jdk/src/share/classes/com/sun/jmx/event/DaemonThreadFactory.java jdk/src/share/classes/com/sun/jmx/event/EventBuffer.java jdk/src/share/classes/com/sun/jmx/event/EventClientFactory.java jdk/src/share/classes/com/sun/jmx/event/EventConnection.java jdk/src/share/classes/com/sun/jmx/event/EventParams.java jdk/src/share/classes/com/sun/jmx/event/LeaseManager.java jdk/src/share/classes/com/sun/jmx/event/LeaseRenewer.java jdk/src/share/classes/com/sun/jmx/event/ReceiverBuffer.java jdk/src/share/classes/com/sun/jmx/event/RepeatedSingletonJob.java jdk/src/share/classes/com/sun/jmx/interceptor/DefaultMBeanServerInterceptor.java jdk/src/share/classes/com/sun/jmx/interceptor/DispatchInterceptor.java jdk/src/share/classes/com/sun/jmx/interceptor/DomainDispatchInterceptor.java jdk/src/share/classes/com/sun/jmx/interceptor/MBeanServerInterceptorSupport.java jdk/src/share/classes/com/sun/jmx/interceptor/NamespaceDispatchInterceptor.java jdk/src/share/classes/com/sun/jmx/interceptor/SingleMBeanForwarder.java jdk/src/share/classes/com/sun/jmx/mbeanserver/ConvertingMethod.java jdk/src/share/classes/com/sun/jmx/mbeanserver/DefaultMXBeanMappingFactory.java jdk/src/share/classes/com/sun/jmx/mbeanserver/DynamicMBean2.java jdk/src/share/classes/com/sun/jmx/mbeanserver/Introspector.java jdk/src/share/classes/com/sun/jmx/mbeanserver/JmxMBeanServer.java jdk/src/share/classes/com/sun/jmx/mbeanserver/MBeanAnalyzer.java jdk/src/share/classes/com/sun/jmx/mbeanserver/MBeanInjector.java jdk/src/share/classes/com/sun/jmx/mbeanserver/MBeanInstantiator.java jdk/src/share/classes/com/sun/jmx/mbeanserver/MBeanIntrospector.java jdk/src/share/classes/com/sun/jmx/mbeanserver/MBeanSupport.java jdk/src/share/classes/com/sun/jmx/mbeanserver/MXBeanIntrospector.java jdk/src/share/classes/com/sun/jmx/mbeanserver/MXBeanLookup.java jdk/src/share/classes/com/sun/jmx/mbeanserver/MXBeanMapping.java jdk/src/share/classes/com/sun/jmx/mbeanserver/MXBeanMappingFactory.java jdk/src/share/classes/com/sun/jmx/mbeanserver/MXBeanProxy.java jdk/src/share/classes/com/sun/jmx/mbeanserver/MXBeanSupport.java jdk/src/share/classes/com/sun/jmx/mbeanserver/NotificationMBeanSupport.java jdk/src/share/classes/com/sun/jmx/mbeanserver/NotifySupport.java jdk/src/share/classes/com/sun/jmx/mbeanserver/PerInterface.java jdk/src/share/classes/com/sun/jmx/mbeanserver/PerThreadGroupPool.java jdk/src/share/classes/com/sun/jmx/mbeanserver/Repository.java jdk/src/share/classes/com/sun/jmx/mbeanserver/StandardMBeanIntrospector.java jdk/src/share/classes/com/sun/jmx/mbeanserver/StandardMBeanSupport.java jdk/src/share/classes/com/sun/jmx/mbeanserver/Util.java jdk/src/share/classes/com/sun/jmx/namespace/DomainInterceptor.java jdk/src/share/classes/com/sun/jmx/namespace/HandlerInterceptor.java jdk/src/share/classes/com/sun/jmx/namespace/NamespaceInterceptor.java jdk/src/share/classes/com/sun/jmx/namespace/ObjectNameRouter.java jdk/src/share/classes/com/sun/jmx/namespace/RoutingConnectionProxy.java jdk/src/share/classes/com/sun/jmx/namespace/RoutingMBeanServerConnection.java jdk/src/share/classes/com/sun/jmx/namespace/RoutingProxy.java jdk/src/share/classes/com/sun/jmx/namespace/RoutingServerProxy.java jdk/src/share/classes/com/sun/jmx/namespace/package.html jdk/src/share/classes/com/sun/jmx/namespace/serial/DefaultRewritingProcessor.java jdk/src/share/classes/com/sun/jmx/namespace/serial/IdentityProcessor.java jdk/src/share/classes/com/sun/jmx/namespace/serial/JMXNamespaceContext.java jdk/src/share/classes/com/sun/jmx/namespace/serial/RewritingProcessor.java jdk/src/share/classes/com/sun/jmx/namespace/serial/RoutingOnlyProcessor.java jdk/src/share/classes/com/sun/jmx/namespace/serial/SerialRewritingProcessor.java jdk/src/share/classes/com/sun/jmx/namespace/serial/package.html jdk/src/share/classes/com/sun/jmx/remote/internal/ServerNotifForwarder.java jdk/src/share/classes/com/sun/jmx/remote/util/EnvHelp.java jdk/src/share/classes/com/sun/jmx/remote/util/EventClientConnection.java jdk/src/share/classes/java/lang/management/PlatformComponent.java jdk/src/share/classes/java/util/logging/Logging.java jdk/src/share/classes/javax/management/AndQueryExp.java jdk/src/share/classes/javax/management/AttributeList.java jdk/src/share/classes/javax/management/AttributeValueExp.java jdk/src/share/classes/javax/management/BetweenQueryExp.java jdk/src/share/classes/javax/management/BinaryOpValueExp.java jdk/src/share/classes/javax/management/BinaryRelQueryExp.java jdk/src/share/classes/javax/management/ClientContext.java jdk/src/share/classes/javax/management/Description.java jdk/src/share/classes/javax/management/Descriptor.java jdk/src/share/classes/javax/management/DescriptorFields.java jdk/src/share/classes/javax/management/DescriptorKey.java jdk/src/share/classes/javax/management/DynamicWrapperMBean.java jdk/src/share/classes/javax/management/GenericMBeanException.java jdk/src/share/classes/javax/management/Impact.java jdk/src/share/classes/javax/management/InstanceNotFoundException.java jdk/src/share/classes/javax/management/JMRuntimeException.java jdk/src/share/classes/javax/management/JMX.java jdk/src/share/classes/javax/management/MBean.java jdk/src/share/classes/javax/management/MBeanAttributeInfo.java jdk/src/share/classes/javax/management/MBeanConstructorInfo.java jdk/src/share/classes/javax/management/MBeanException.java jdk/src/share/classes/javax/management/MBeanInfo.java jdk/src/share/classes/javax/management/MBeanOperationInfo.java jdk/src/share/classes/javax/management/MBeanPermission.java jdk/src/share/classes/javax/management/MBeanRegistration.java jdk/src/share/classes/javax/management/MBeanServer.java jdk/src/share/classes/javax/management/MBeanServerConnection.java jdk/src/share/classes/javax/management/MBeanServerDelegate.java jdk/src/share/classes/javax/management/MBeanServerFactory.java jdk/src/share/classes/javax/management/MBeanServerInvocationHandler.java jdk/src/share/classes/javax/management/MBeanServerNotification.java jdk/src/share/classes/javax/management/MXBean.java jdk/src/share/classes/javax/management/ManagedAttribute.java jdk/src/share/classes/javax/management/ManagedOperation.java jdk/src/share/classes/javax/management/NotQueryExp.java jdk/src/share/classes/javax/management/Notification.java jdk/src/share/classes/javax/management/NotificationBroadcasterSupport.java jdk/src/share/classes/javax/management/NotificationInfo.java jdk/src/share/classes/javax/management/NotificationInfos.java jdk/src/share/classes/javax/management/ObjectName.java jdk/src/share/classes/javax/management/ObjectNameTemplate.java jdk/src/share/classes/javax/management/OrQueryExp.java jdk/src/share/classes/javax/management/QualifiedAttributeValueExp.java jdk/src/share/classes/javax/management/Query.java jdk/src/share/classes/javax/management/QueryEval.java jdk/src/share/classes/javax/management/QueryNotificationFilter.java jdk/src/share/classes/javax/management/QueryParser.java jdk/src/share/classes/javax/management/SendNotification.java jdk/src/share/classes/javax/management/StandardEmitterMBean.java jdk/src/share/classes/javax/management/StandardMBean.java jdk/src/share/classes/javax/management/event/EventClient.java jdk/src/share/classes/javax/management/event/EventClientDelegate.java jdk/src/share/classes/javax/management/event/EventClientDelegateMBean.java jdk/src/share/classes/javax/management/event/EventClientNotFoundException.java jdk/src/share/classes/javax/management/event/EventConsumer.java jdk/src/share/classes/javax/management/event/EventForwarder.java jdk/src/share/classes/javax/management/event/EventReceiver.java jdk/src/share/classes/javax/management/event/EventRelay.java jdk/src/share/classes/javax/management/event/EventSubscriber.java jdk/src/share/classes/javax/management/event/FetchingEventForwarder.java jdk/src/share/classes/javax/management/event/FetchingEventRelay.java jdk/src/share/classes/javax/management/event/ListenerInfo.java jdk/src/share/classes/javax/management/event/NotificationManager.java jdk/src/share/classes/javax/management/event/RMIPushEventForwarder.java jdk/src/share/classes/javax/management/event/RMIPushEventRelay.java jdk/src/share/classes/javax/management/event/RMIPushServer.java jdk/src/share/classes/javax/management/event/package-info.java jdk/src/share/classes/javax/management/modelmbean/DescriptorSupport.java jdk/src/share/classes/javax/management/modelmbean/ModelMBeanAttributeInfo.java jdk/src/share/classes/javax/management/modelmbean/ModelMBeanConstructorInfo.java jdk/src/share/classes/javax/management/modelmbean/ModelMBeanInfoSupport.java jdk/src/share/classes/javax/management/modelmbean/ModelMBeanNotificationInfo.java jdk/src/share/classes/javax/management/modelmbean/ModelMBeanOperationInfo.java jdk/src/share/classes/javax/management/modelmbean/RequiredModelMBean.java jdk/src/share/classes/javax/management/monitor/MonitorNotification.java jdk/src/share/classes/javax/management/namespace/JMXDomain.java jdk/src/share/classes/javax/management/namespace/JMXNamespace.java jdk/src/share/classes/javax/management/namespace/JMXNamespaceMBean.java jdk/src/share/classes/javax/management/namespace/JMXNamespacePermission.java jdk/src/share/classes/javax/management/namespace/JMXNamespaceView.java jdk/src/share/classes/javax/management/namespace/JMXNamespaces.java jdk/src/share/classes/javax/management/namespace/JMXRemoteNamespace.java jdk/src/share/classes/javax/management/namespace/JMXRemoteNamespaceMBean.java jdk/src/share/classes/javax/management/namespace/MBeanServerConnectionWrapper.java jdk/src/share/classes/javax/management/namespace/MBeanServerSupport.java jdk/src/share/classes/javax/management/namespace/VirtualEventManager.java jdk/src/share/classes/javax/management/namespace/package-info.java jdk/src/share/classes/javax/management/openmbean/CompositeDataInvocationHandler.java jdk/src/share/classes/javax/management/openmbean/CompositeDataSupport.java jdk/src/share/classes/javax/management/openmbean/CompositeType.java jdk/src/share/classes/javax/management/openmbean/MXBeanMapping.java jdk/src/share/classes/javax/management/openmbean/MXBeanMappingClass.java jdk/src/share/classes/javax/management/openmbean/MXBeanMappingFactory.java jdk/src/share/classes/javax/management/openmbean/MXBeanMappingFactoryClass.java jdk/src/share/classes/javax/management/openmbean/OpenType.java jdk/src/share/classes/javax/management/package.html jdk/src/share/classes/javax/management/remote/IdentityMBeanServerForwarder.java jdk/src/share/classes/javax/management/remote/JMXConnector.java jdk/src/share/classes/javax/management/remote/JMXConnectorServer.java jdk/src/share/classes/javax/management/remote/JMXConnectorServerMBean.java jdk/src/share/classes/javax/management/remote/JMXServiceURL.java jdk/src/share/classes/javax/management/remote/rmi/RMIConnectionImpl.java jdk/src/share/classes/javax/management/remote/rmi/RMIConnector.java jdk/src/share/classes/javax/management/remote/rmi/RMIConnectorServer.java jdk/src/share/classes/javax/management/remote/rmi/RMIServerImpl.java jdk/src/share/classes/sun/management/ClassLoadingImpl.java jdk/src/share/classes/sun/management/CompilationImpl.java jdk/src/share/classes/sun/management/HotSpotDiagnostic.java jdk/src/share/classes/sun/management/HotspotInternal.java jdk/src/share/classes/sun/management/ManagementFactoryHelper.java jdk/src/share/classes/sun/management/MemoryImpl.java jdk/src/share/classes/sun/management/OperatingSystemImpl.java jdk/src/share/classes/sun/management/RuntimeImpl.java jdk/src/share/classes/sun/management/ThreadImpl.java jdk/src/share/classes/sun/management/Util.java jdk/test/javax/management/Introspector/AnnotatedMBeanTest.java jdk/test/javax/management/Introspector/AnnotatedNotificationInfoTest.java jdk/test/javax/management/Introspector/AnnotationTest.java jdk/test/javax/management/Introspector/ExceptionsDescriptorTest.java jdk/test/javax/management/Introspector/MBeanDescriptionTest.java jdk/test/javax/management/Introspector/ObjectNameTemplateTest.java jdk/test/javax/management/Introspector/ParameterNameTest.java jdk/test/javax/management/Introspector/ResourceInjectionTest.java jdk/test/javax/management/MBeanServer/AttributeListMapTest.java jdk/test/javax/management/MBeanServer/DynamicWrapperMBeanTest.java jdk/test/javax/management/MBeanServer/InstanceNotFoundExceptionTest.java jdk/test/javax/management/MBeanServer/MBeanExceptionTest.java jdk/test/javax/management/MBeanServerFactory/NamedMBeanServerTest.java jdk/test/javax/management/ObjectName/ApplyWildcardTest.java jdk/test/javax/management/ObjectName/ValueOfTest.java jdk/test/javax/management/context/ContextForwarderTest.java jdk/test/javax/management/context/ContextTest.java jdk/test/javax/management/context/LocaleAwareBroadcasterTest.java jdk/test/javax/management/context/LocaleTest.java jdk/test/javax/management/context/LocalizableTest.java jdk/test/javax/management/context/RemoteContextTest.java jdk/test/javax/management/context/localizable/MBeanDescriptions.properties jdk/test/javax/management/context/localizable/MBeanDescriptions_fr.java jdk/test/javax/management/context/localizable/Whatsit.java jdk/test/javax/management/context/localizable/WhatsitMBean.java jdk/test/javax/management/descriptor/DescriptorConstructorTest.java jdk/test/javax/management/eventService/AddRemoveListenerTest.java jdk/test/javax/management/eventService/CustomForwarderTest.java jdk/test/javax/management/eventService/EventClientExecutorTest.java jdk/test/javax/management/eventService/EventClientThreadTest.java jdk/test/javax/management/eventService/EventDelegateSecurityTest.java jdk/test/javax/management/eventService/EventManagerTest.java jdk/test/javax/management/eventService/FetchingTest.java jdk/test/javax/management/eventService/LeaseManagerDeadlockTest.java jdk/test/javax/management/eventService/LeaseTest.java jdk/test/javax/management/eventService/ListenerTest.java jdk/test/javax/management/eventService/MyFetchingEventForwarder.java jdk/test/javax/management/eventService/NotSerializableNotifTest.java jdk/test/javax/management/eventService/PublishTest.java jdk/test/javax/management/eventService/ReconnectableConnectorTest.java jdk/test/javax/management/eventService/SharingThreadTest.java jdk/test/javax/management/eventService/SubUnsubTest.java jdk/test/javax/management/eventService/SubscribeTest.java jdk/test/javax/management/eventService/UsingEventService.java jdk/test/javax/management/interop/MBeanExceptionInteropTest.java jdk/test/javax/management/modelmbean/DefaultDescriptorFieldTest.java jdk/test/javax/management/monitor/AttributeArbitraryDataTypeTest.java jdk/test/javax/management/monitor/InstantiateMonitorNotificationTest.java jdk/test/javax/management/mxbean/CustomTypeTest.java jdk/test/javax/management/mxbean/ExceptionDiagnosisTest.java jdk/test/javax/management/mxbean/JMXServiceURLTest.java jdk/test/javax/management/mxbean/customtypes/CustomLongMXBean.java jdk/test/javax/management/mxbean/customtypes/CustomMXBean.java jdk/test/javax/management/mxbean/customtypes/IntegerIsLongFactory.java jdk/test/javax/management/mxbean/customtypes/IntegerIsStringFactory.java jdk/test/javax/management/mxbean/customtypes/package-info.java jdk/test/javax/management/namespace/DomainCreationTest.java jdk/test/javax/management/namespace/EventWithNamespaceControlTest.java jdk/test/javax/management/namespace/EventWithNamespaceTest.java jdk/test/javax/management/namespace/ExportNamespaceTest.java jdk/test/javax/management/namespace/JMXDomainTest.java jdk/test/javax/management/namespace/JMXNamespaceSecurityTest.java jdk/test/javax/management/namespace/JMXNamespaceTest.java jdk/test/javax/management/namespace/JMXNamespaceViewTest.java jdk/test/javax/management/namespace/JMXNamespacesTest.java jdk/test/javax/management/namespace/JMXRemoteNamespaceTest.java jdk/test/javax/management/namespace/JMXRemoteTargetNamespace.java jdk/test/javax/management/namespace/LazyDomainTest.java jdk/test/javax/management/namespace/LeadingSeparatorsTest.java jdk/test/javax/management/namespace/MXBeanRefTest.java jdk/test/javax/management/namespace/NamespaceController.java jdk/test/javax/management/namespace/NamespaceControllerMBean.java jdk/test/javax/management/namespace/NamespaceCreationTest.java jdk/test/javax/management/namespace/NamespaceNotificationsTest.java jdk/test/javax/management/namespace/NullDomainObjectNameTest.java jdk/test/javax/management/namespace/NullObjectNameTest.java jdk/test/javax/management/namespace/QueryNamesTest.java jdk/test/javax/management/namespace/RemoveNotificationListenerTest.java jdk/test/javax/management/namespace/RoutingServerProxyTest.java jdk/test/javax/management/namespace/SerialParamProcessorTest.java jdk/test/javax/management/namespace/SourceNamespaceTest.java jdk/test/javax/management/namespace/VirtualMBeanNotifTest.java jdk/test/javax/management/namespace/VirtualMBeanTest.java jdk/test/javax/management/namespace/VirtualNamespaceQueryTest.java jdk/test/javax/management/namespace/VirtualPropsTest.java jdk/test/javax/management/namespace/Wombat.java jdk/test/javax/management/namespace/WombatMBean.java jdk/test/javax/management/namespace/namespace.policy jdk/test/javax/management/notification/SupportClearTest.java jdk/test/javax/management/openmbean/CompositeDataToMapTest.java jdk/test/javax/management/openmbean/GenericMBeanExceptionTest.java jdk/test/javax/management/query/QueryDottedAttrTest.java jdk/test/javax/management/query/QueryExpStringTest.java jdk/test/javax/management/query/QueryNotifFilterTest.java jdk/test/javax/management/query/QueryParseTest.java jdk/test/javax/management/remote/mandatory/connection/CloseServerTest.java jdk/test/javax/management/remote/mandatory/connection/DeadLockTest.java jdk/test/javax/management/remote/mandatory/connection/IdleTimeoutTest.java jdk/test/javax/management/remote/mandatory/connection/RMIExitTest.java jdk/test/javax/management/remote/mandatory/connection/ReconnectTest.java jdk/test/javax/management/remote/mandatory/connectorServer/CloseConnectionTest.java jdk/test/javax/management/remote/mandatory/connectorServer/ForwarderChainTest.java jdk/test/javax/management/remote/mandatory/connectorServer/StandardForwardersTest.java jdk/test/javax/management/remote/mandatory/loading/MissingClassTest.java jdk/test/javax/management/remote/mandatory/notif/AddRemoveTest.java jdk/test/javax/management/remote/mandatory/notif/DiffHBTest.java jdk/test/javax/management/remote/mandatory/notif/EmptyDomainNotificationTest.java jdk/test/javax/management/remote/mandatory/notif/ListenerScaleTest.java jdk/test/javax/management/remote/mandatory/notif/NotifBufferSizePropertyNameTest.java jdk/test/javax/management/remote/mandatory/notif/NotifReconnectDeadlockTest.java jdk/test/javax/management/remote/mandatory/notif/NotificationBufferCreationTest.java jdk/test/javax/management/remote/mandatory/notif/NotificationBufferDeadlockTest.java jdk/test/javax/management/remote/mandatory/notif/NotificationEmissionTest.java jdk/test/javax/management/remote/mandatory/notif/RMINotifTest.java jdk/test/javax/management/remote/mandatory/notif/UnexpectedNotifTest.java jdk/test/javax/management/remote/mandatory/version/JMXSpecVersionTest.java jdk/test/javax/management/standardmbean/FindMethodTest.java jdk/test/javax/management/standardmbean/RegistrationTest.java |
diffstat | 296 files changed, 1566 insertions(+), 57624 deletions(-) [+] |
line wrap: on
line diff
--- a/jdk/make/docs/CORE_PKGS.gmk Wed Oct 21 16:28:57 2009 +0200 +++ b/jdk/make/docs/CORE_PKGS.gmk Wed Oct 21 17:33:18 2009 +0200 @@ -160,10 +160,8 @@ javax.lang.model.type \ javax.lang.model.util \ javax.management \ - javax.management.event \ javax.management.loading \ javax.management.monitor \ - javax.management.namespace \ javax.management.relation \ javax.management.openmbean \ javax.management.timer \
--- a/jdk/src/share/classes/com/sun/jmx/defaults/JmxProperties.java Wed Oct 21 16:28:57 2009 +0200 +++ b/jdk/src/share/classes/com/sun/jmx/defaults/JmxProperties.java Wed Oct 21 17:33:18 2009 +0200 @@ -1,5 +1,5 @@ /* - * Copyright 1999-2008 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1999-2007 Sun Microsystems, Inc. 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 @@ -177,18 +177,6 @@ "javax.management.relation"; /** - * Logger name for Namespaces. - */ - public static final String NAMESPACE_LOGGER_NAME = - "javax.management.namespace"; - - /** - * Logger name for Namespaces. - */ - public static final Logger NAMESPACE_LOGGER = - Logger.getLogger(NAMESPACE_LOGGER_NAME); - - /** * Logger for Relation Service. */ public static final Logger RELATION_LOGGER =
--- a/jdk/src/share/classes/com/sun/jmx/defaults/ServiceName.java Wed Oct 21 16:28:57 2009 +0200 +++ b/jdk/src/share/classes/com/sun/jmx/defaults/ServiceName.java Wed Oct 21 17:33:18 2009 +0200 @@ -69,9 +69,9 @@ /** * The version of the JMX specification implemented by this product. * <BR> - * The value is <CODE>2.0</CODE>. + * The value is <CODE>1.4</CODE>. */ - public static final String JMX_SPEC_VERSION = "2.0"; + public static final String JMX_SPEC_VERSION = "1.4"; /** * The vendor of the JMX specification implemented by this product.
--- a/jdk/src/share/classes/com/sun/jmx/event/DaemonThreadFactory.java Wed Oct 21 16:28:57 2009 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,77 +0,0 @@ -/* - * Copyright 2007-2008 Sun Microsystems, Inc. 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. Sun designates this - * particular file as subject to the "Classpath" exception as provided - * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, - * CA 95054 USA or visit www.sun.com if you need additional information or - * have any questions. - */ - -package com.sun.jmx.event; - -import com.sun.jmx.remote.util.ClassLogger; -import java.util.concurrent.ThreadFactory; -import java.util.concurrent.atomic.AtomicInteger; - -public class DaemonThreadFactory implements ThreadFactory { - public DaemonThreadFactory(String nameTemplate) { - this(nameTemplate, null); - } - - // nameTemplate should be a format with %d in it, which will be replaced - // by a sequence number of threads created by this factory. - public DaemonThreadFactory(String nameTemplate, ThreadGroup threadGroup) { - if (logger.debugOn()) { - logger.debug("DaemonThreadFactory", - "Construct a new daemon factory: "+nameTemplate); - } - - if (threadGroup == null) { - SecurityManager s = System.getSecurityManager(); - threadGroup = (s != null) ? s.getThreadGroup() : - Thread.currentThread().getThreadGroup(); - } - - this.nameTemplate = nameTemplate; - this.threadGroup = threadGroup; - } - - public Thread newThread(Runnable r) { - final String name = - String.format(nameTemplate, threadNumber.getAndIncrement()); - Thread t = new Thread(threadGroup, r, name, 0); - t.setDaemon(true); - if (t.getPriority() != Thread.NORM_PRIORITY) - t.setPriority(Thread.NORM_PRIORITY); - - if (logger.debugOn()) { - logger.debug("newThread", - "Create a new daemon thread with the name "+t.getName()); - } - - return t; - } - - private final String nameTemplate; - private final ThreadGroup threadGroup; - private final AtomicInteger threadNumber = new AtomicInteger(1); - - private static final ClassLogger logger = - new ClassLogger("com.sun.jmx.event", "DaemonThreadFactory"); -}
--- a/jdk/src/share/classes/com/sun/jmx/event/EventBuffer.java Wed Oct 21 16:28:57 2009 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,252 +0,0 @@ -/* - * Copyright 2007-2008 Sun Microsystems, Inc. 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. Sun designates this - * particular file as subject to the "Classpath" exception as provided - * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, - * CA 95054 USA or visit www.sun.com if you need additional information or - * have any questions. - */ - -package com.sun.jmx.event; - -import com.sun.jmx.remote.util.ClassLogger; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import javax.management.remote.NotificationResult; -import javax.management.remote.TargetedNotification; - -public class EventBuffer { - - public EventBuffer() { - this(Integer.MAX_VALUE, null); - } - - public EventBuffer(int capacity) { - this(capacity, new ArrayList<TargetedNotification>()); - } - - public EventBuffer(int capacity, final List<TargetedNotification> list) { - if (logger.traceOn()) { - logger.trace("EventBuffer", "New buffer with the capacity: " - +capacity); - } - if (capacity < 1) { - throw new IllegalArgumentException( - "The capacity must be bigger than 0"); - } - - if (list == null) { - throw new NullPointerException("Null list."); - } - - this.capacity = capacity; - this.list = list; - } - - public void add(TargetedNotification tn) { - if (logger.traceOn()) { - logger.trace("add", "Add one notif."); - } - - synchronized(lock) { - if (list.size() == capacity) { // have to throw one - passed++; - list.remove(0); - - if (logger.traceOn()) { - logger.trace("add", "Over, remove the oldest one."); - } - } - - list.add(tn); - lock.notify(); - } - } - - public void add(TargetedNotification[] tns) { - if (tns == null || tns.length == 0) { - return; - } - - if (logger.traceOn()) { - logger.trace("add", "Add notifs: "+tns.length); - } - - synchronized(lock) { - final int d = list.size() - capacity + tns.length; - if (d > 0) { // have to throw - passed += d; - if (logger.traceOn()) { - logger.trace("add", - "Over, remove the oldest: "+d); - } - if (tns.length <= capacity){ - list.subList(0, d).clear(); - } else { - list.clear(); - TargetedNotification[] tmp = - new TargetedNotification[capacity]; - System.arraycopy(tns, tns.length-capacity, tmp, 0, capacity); - tns = tmp; - } - } - - Collections.addAll(list,tns); - lock.notify(); - } - } - - public NotificationResult fetchNotifications(long startSequenceNumber, - long timeout, - int maxNotifications) { - if (logger.traceOn()) { - logger.trace("fetchNotifications", - "Being called: " - +startSequenceNumber+" " - +timeout+" "+maxNotifications); - } - if (startSequenceNumber < 0 || - timeout < 0 || - maxNotifications < 0) { - throw new IllegalArgumentException("Negative value."); - } - - TargetedNotification[] tns = new TargetedNotification[0]; - long earliest = startSequenceNumber < passed ? - passed : startSequenceNumber; - long next = earliest; - - final long startTime = System.currentTimeMillis(); - long toWait = timeout; - synchronized(lock) { - int toSkip = (int)(startSequenceNumber - passed); - - // skip those before startSequenceNumber. - while (!closed && toSkip > 0) { - toWait = timeout - (System.currentTimeMillis() - startTime); - if (list.size() == 0) { - if (toWait <= 0) { - // the notification of startSequenceNumber - // does not arrive yet. - return new NotificationResult(startSequenceNumber, - startSequenceNumber, - new TargetedNotification[0]); - } - - waiting(toWait); - continue; - } - - if (toSkip <= list.size()) { - list.subList(0, toSkip).clear(); - passed += toSkip; - - break; - } else { - passed += list.size(); - toSkip -= list.size(); - - list.clear(); - } - } - - earliest = passed; - - if (list.size() == 0) { - toWait = timeout - (System.currentTimeMillis() - startTime); - - waiting(toWait); - } - - if (list.size() == 0) { - tns = new TargetedNotification[0]; - } else if (list.size() <= maxNotifications) { - tns = list.toArray(new TargetedNotification[0]); - } else { - tns = new TargetedNotification[maxNotifications]; - for (int i=0; i<maxNotifications; i++) { - tns[i] = list.get(i); - } - } - - next = earliest + tns.length; - } - - if (logger.traceOn()) { - logger.trace("fetchNotifications", - "Return: "+earliest+" "+next+" "+tns.length); - } - - return new NotificationResult(earliest, next, tns); - } - - public int size() { - return list.size(); - } - - public void addLost(long nb) { - synchronized(lock) { - passed += nb; - } - } - - public void close() { - if (logger.traceOn()) { - logger.trace("clear", "done"); - } - - synchronized(lock) { - list.clear(); - closed = true; - lock.notifyAll(); - } - } - - - // ------------------------------------------- - // private classes - // ------------------------------------------- - private void waiting(long timeout) { - final long startTime = System.currentTimeMillis(); - long toWait = timeout; - synchronized(lock) { - while (!closed && list.size() == 0 && toWait > 0) { - try { - lock.wait(toWait); - - toWait = timeout - (System.currentTimeMillis() - startTime); - } catch (InterruptedException ire) { - logger.trace("waiting", ire); - break; - } - } - } - } - - private final int capacity; - private final List<TargetedNotification> list; - private boolean closed; - - private long passed = 0; - private final int[] lock = new int[0]; - - private static final ClassLogger logger = - new ClassLogger("javax.management.event", "EventBuffer"); -}
--- a/jdk/src/share/classes/com/sun/jmx/event/EventClientFactory.java Wed Oct 21 16:28:57 2009 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,46 +0,0 @@ -/* - * Copyright 2007-2008 Sun Microsystems, Inc. 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. Sun designates this - * particular file as subject to the "Classpath" exception as provided - * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, - * CA 95054 USA or visit www.sun.com if you need additional information or - * have any questions. - */ - -package com.sun.jmx.event; - -import javax.management.event.*; - -/** - * Implemented by objects which are using an {@link EventClient} to - * subscribe for Notifications. - * - */ -public interface EventClientFactory { - /** - * Returns the {@code EventClient} that the object implementing this - * interface uses to subscribe for Notifications. This method returns - * {@code null} if no {@code EventClient} can be used - e.g. because - * the underlying server does not have any {@link EventDelegate}. - * - * @return an {@code EventClient} or {@code null}. - **/ - public EventClient getEventClient(); - -}
--- a/jdk/src/share/classes/com/sun/jmx/event/EventConnection.java Wed Oct 21 16:28:57 2009 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,81 +0,0 @@ -/* - * Copyright 2002-2008 Sun Microsystems, Inc. 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. Sun designates this - * particular file as subject to the "Classpath" exception as provided - * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, - * CA 95054 USA or visit www.sun.com if you need additional information or - * have any questions. - */ - -package com.sun.jmx.event; - -import java.io.IOException; -import java.lang.reflect.InvocationHandler; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.lang.reflect.Proxy; -import javax.management.MBeanServerConnection; -import javax.management.event.EventClient; -import javax.management.event.EventClientDelegate; -import javax.management.event.EventConsumer; -import javax.management.event.NotificationManager; - -/** - * Override the methods related to the notification to use the - * Event service. - */ -public interface EventConnection extends MBeanServerConnection, EventConsumer { - public EventClient getEventClient(); - - public static class Factory { - public static EventConnection make( - final MBeanServerConnection mbsc, - final EventClient eventClient) - throws IOException { - if (!mbsc.isRegistered(EventClientDelegate.OBJECT_NAME)) { - throw new IOException( - "The server does not support the event service."); - } - InvocationHandler ih = new InvocationHandler() { - public Object invoke(Object proxy, Method method, Object[] args) - throws Throwable { - Class<?> intf = method.getDeclaringClass(); - try { - if (intf.isInstance(eventClient)) - return method.invoke(eventClient, args); - else - return method.invoke(mbsc, args); - } catch (InvocationTargetException e) { - throw e.getCause(); - } - } - }; - // It is important to declare NotificationManager.class first - // in the array below, so that the relevant addNL and removeNL - // methods will show up with method.getDeclaringClass() as - // being from that interface and not MBeanServerConnection. - return (EventConnection) Proxy.newProxyInstance( - NotificationManager.class.getClassLoader(), - new Class<?>[] { - NotificationManager.class, EventConnection.class, - }, - ih); - } - } -}
--- a/jdk/src/share/classes/com/sun/jmx/event/EventParams.java Wed Oct 21 16:28:57 2009 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,65 +0,0 @@ -/* - * Copyright 2007-2008 Sun Microsystems, Inc. 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. Sun designates this - * particular file as subject to the "Classpath" exception as provided - * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, - * CA 95054 USA or visit www.sun.com if you need additional information or - * have any questions. - */ - -package com.sun.jmx.event; - -import com.sun.jmx.mbeanserver.GetPropertyAction; -import com.sun.jmx.remote.util.ClassLogger; -import java.security.AccessController; -import javax.management.event.EventClient; - -/** - * - * @author sjiang - */ -public class EventParams { - public static final String DEFAULT_LEASE_TIMEOUT = - "com.sun.event.lease.time"; - - - @SuppressWarnings("cast") // cast for jdk 1.5 - public static long getLeaseTimeout() { - long timeout = EventClient.DEFAULT_REQUESTED_LEASE_TIME; - try { - final GetPropertyAction act = - new GetPropertyAction(DEFAULT_LEASE_TIMEOUT); - final String s = (String)AccessController.doPrivileged(act); - if (s != null) { - timeout = Long.parseLong(s); - } - } catch (RuntimeException e) { - logger.fine("getLeaseTimeout", "exception getting property", e); - } - - return timeout; - } - - /** Creates a new instance of EventParams */ - private EventParams() { - } - - private static final ClassLogger logger = - new ClassLogger("javax.management.event", "EventParams"); -}
--- a/jdk/src/share/classes/com/sun/jmx/event/LeaseManager.java Wed Oct 21 16:28:57 2009 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,155 +0,0 @@ -/* - * Copyright 2007-2008 Sun Microsystems, Inc. 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. Sun designates this - * particular file as subject to the "Classpath" exception as provided - * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, - * CA 95054 USA or visit www.sun.com if you need additional information or - * have any questions. - */ - -package com.sun.jmx.event; - -import com.sun.jmx.remote.util.ClassLogger; -import java.util.concurrent.Executors; -import java.util.concurrent.ScheduledExecutorService; -import java.util.concurrent.ScheduledFuture; -import java.util.concurrent.ThreadFactory; -import java.util.concurrent.TimeUnit; - -/** - * <p>Manage a renewable lease. The lease can be renewed indefinitely - * but if the lease runs to its current expiry date without being renewed - * then the expiry callback is invoked. If the lease has already expired - * when renewal is attempted then the lease method returns zero.</p> - * @author sjiang - * @author emcmanus - */ -// The synchronization logic of this class is tricky to deal correctly with the -// case where the lease expires at the same time as the |lease| or |stop| method -// is called. If the lease is active then the field |scheduled| represents -// the expiry task; otherwise |scheduled| is null. Renewing or stopping the -// lease involves canceling this task and setting |scheduled| either to a new -// task (to renew) or to null (to stop). -// -// Suppose the expiry task runs at the same time as the |lease| method is called. -// If the task enters its synchronized block before the method starts, then -// it will set |scheduled| to null and the method will return 0. If the method -// starts before the task enters its synchronized block, then the method will -// cancel the task which will see that when it later enters the block. -// Similar reasoning applies to the |stop| method. It is not expected that -// different threads will call |lease| or |stop| simultaneously, although the -// logic should be correct then too. -public class LeaseManager { - public LeaseManager(Runnable callback) { - this(callback, EventParams.getLeaseTimeout()); - } - - public LeaseManager(Runnable callback, long timeout) { - if (logger.traceOn()) { - logger.trace("LeaseManager", "new manager with lease: "+timeout); - } - if (callback == null) { - throw new NullPointerException("Null callback."); - } - if (timeout <= 0) - throw new IllegalArgumentException("Timeout must be positive: " + timeout); - - this.callback = callback; - schedule(timeout); - } - - /** - * <p>Renew the lease for the given time. The new time can be shorter - * than the previous one, in which case the lease will expire earlier - * than it would have.</p> - * - * <p>Calling this method after the lease has expired will return zero - * immediately and have no other effect.</p> - * - * @param timeout the new lifetime. If zero, the lease - * will expire immediately. - */ - public synchronized long lease(long timeout) { - if (logger.traceOn()) { - logger.trace("lease", "new lease to: "+timeout); - } - - if (timeout < 0) - throw new IllegalArgumentException("Negative lease: " + timeout); - - if (scheduled == null) - return 0L; - - scheduled.cancel(false); - - if (logger.traceOn()) - logger.trace("lease", "start lease: "+timeout); - schedule(timeout); - - return timeout; - } - - private class Expire implements Runnable { - ScheduledFuture<?> task; - - public void run() { - synchronized (LeaseManager.this) { - if (task.isCancelled()) - return; - scheduled = null; - } - callback.run(); - executor.shutdown(); - } - } - - private synchronized void schedule(long timeout) { - Expire expire = new Expire(); - scheduled = executor.schedule(expire, timeout, TimeUnit.MILLISECONDS); - expire.task = scheduled; - } - - /** - * <p>Cancel the lease without calling the expiry callback.</p> - */ - public synchronized void stop() { - logger.trace("stop", "canceling lease"); - scheduled.cancel(false); - scheduled = null; - try { - executor.shutdown(); - } catch (SecurityException e) { - // OK: caller doesn't have RuntimePermission("modifyThread") - // which is unlikely in reality but triggers a test failure otherwise - logger.trace("stop", "exception from executor.shutdown", e); - } - } - - private final Runnable callback; - private ScheduledFuture<?> scheduled; // If null, the lease has expired. - - private static final ThreadFactory threadFactory = - new DaemonThreadFactory("JMX LeaseManager %d"); - private final ScheduledExecutorService executor - = Executors.newScheduledThreadPool(1, threadFactory); - - private static final ClassLogger logger = - new ClassLogger("javax.management.event", "LeaseManager"); - -}
--- a/jdk/src/share/classes/com/sun/jmx/event/LeaseRenewer.java Wed Oct 21 16:28:57 2009 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,143 +0,0 @@ -/* - * Copyright 2007-2008 Sun Microsystems, Inc. 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. Sun designates this - * particular file as subject to the "Classpath" exception as provided - * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, - * CA 95054 USA or visit www.sun.com if you need additional information or - * have any questions. - */ - -package com.sun.jmx.event; - -import com.sun.jmx.remote.util.ClassLogger; -import java.util.concurrent.Callable; -import java.util.concurrent.ScheduledExecutorService; -import java.util.concurrent.ScheduledFuture; -import java.util.concurrent.TimeUnit; - -/** - * - * @author sjiang - */ -public class LeaseRenewer { - public LeaseRenewer(ScheduledExecutorService scheduler, Callable<Long> doRenew) { - if (logger.traceOn()) { - logger.trace("LeaseRenewer", "New LeaseRenewer."); - } - - if (doRenew == null) { - throw new NullPointerException("Null job to call server."); - } - - this.doRenew = doRenew; - nextRenewTime = System.currentTimeMillis(); - - this.scheduler = scheduler; - future = this.scheduler.schedule(myRenew, 0, TimeUnit.MILLISECONDS); - } - - public void close() { - if (logger.traceOn()) { - logger.trace("close", "Close the lease."); - } - - synchronized(lock) { - if (closed) { - return; - } else { - closed = true; - } - } - - try { - future.cancel(false); // not interrupt if running - } catch (Exception e) { - // OK - if (logger.debugOn()) { - logger.debug("close", "Failed to cancel the leasing job.", e); - } - } - } - - public boolean closed() { - synchronized(lock) { - return closed; - } - } - - // ------------------------------ - // private - // ------------------------------ - private final Runnable myRenew = new Runnable() { - public void run() { - synchronized(lock) { - if (closed()) { - return; - } - } - - long next = nextRenewTime - System.currentTimeMillis(); - if (next < MIN_MILLIS) { - try { - if (logger.traceOn()) { - logger.trace("myRenew-run", ""); - } - next = doRenew.call().longValue(); - - } catch (Exception e) { - logger.fine("myRenew-run", "Failed to renew lease", e); - close(); - } - - if (next > 0 && next < Long.MAX_VALUE) { - next = next/2; - next = (next < MIN_MILLIS) ? MIN_MILLIS : next; - } else { - close(); - } - } - - nextRenewTime = System.currentTimeMillis() + next; - - if (logger.traceOn()) { - logger.trace("myRenew-run", "Next leasing: "+next); - } - - synchronized(lock) { - if (!closed) { - future = scheduler.schedule(this, next, TimeUnit.MILLISECONDS); - } - } - } - }; - - private final Callable<Long> doRenew; - private ScheduledFuture<?> future; - private boolean closed = false; - private long nextRenewTime; - - private final int[] lock = new int[0]; - - private final ScheduledExecutorService scheduler; - - private static final long MIN_MILLIS = 50; - - private static final ClassLogger logger = - new ClassLogger("javax.management.event", "LeaseRenewer"); -}
--- a/jdk/src/share/classes/com/sun/jmx/event/ReceiverBuffer.java Wed Oct 21 16:28:57 2009 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,97 +0,0 @@ -/* - * Copyright 2007-2008 Sun Microsystems, Inc. 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. Sun designates this - * particular file as subject to the "Classpath" exception as provided - * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, - * CA 95054 USA or visit www.sun.com if you need additional information or - * have any questions. - */ - -package com.sun.jmx.event; - -import com.sun.jmx.remote.util.ClassLogger; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import javax.management.remote.NotificationResult; -import javax.management.remote.TargetedNotification; - - -public class ReceiverBuffer { - public void addNotifs(NotificationResult nr) { - if (nr == null) { - return; - } - - TargetedNotification[] tns = nr.getTargetedNotifications(); - - if (logger.traceOn()) { - logger.trace("addNotifs", "" + tns.length); - } - - long impliedStart = nr.getEarliestSequenceNumber(); - final long missed = impliedStart - start; - start = nr.getNextSequenceNumber(); - - if (missed > 0) { - if (logger.traceOn()) { - logger.trace("addNotifs", - "lost: "+missed); - } - - lost += missed; - } - - Collections.addAll(notifList, nr.getTargetedNotifications()); - } - - public TargetedNotification[] removeNotifs() { - if (logger.traceOn()) { - logger.trace("removeNotifs", String.valueOf(notifList.size())); - } - - if (notifList.size() == 0) { - return null; - } - - TargetedNotification[] ret = notifList.toArray( - new TargetedNotification[]{}); - notifList.clear(); - - return ret; - } - - public int size() { - return notifList.size(); - } - - public int removeLost() { - int ret = lost; - lost = 0; - return ret; - } - - private List<TargetedNotification> notifList - = new ArrayList<TargetedNotification>(); - private long start = 0; - private int lost = 0; - - private static final ClassLogger logger = - new ClassLogger("javax.management.event", "ReceiverBuffer"); -}
--- a/jdk/src/share/classes/com/sun/jmx/event/RepeatedSingletonJob.java Wed Oct 21 16:28:57 2009 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,119 +0,0 @@ -/* - * Copyright 2007-2008 Sun Microsystems, Inc. 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. Sun designates this - * particular file as subject to the "Classpath" exception as provided - * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, - * CA 95054 USA or visit www.sun.com if you need additional information or - * have any questions. - */ - -package com.sun.jmx.event; - -import com.sun.jmx.remote.util.ClassLogger; -import java.util.concurrent.Executor; -import java.util.concurrent.RejectedExecutionException; - -/** - * <p>A task that is repeatedly run by an Executor. The task will be - * repeated as long as the {@link #isSuspended()} method returns true. Once - * that method returns false, the task is no longer executed until someone - * calls {@link #resume()}.</p> - * @author sjiang - */ -public abstract class RepeatedSingletonJob implements Runnable { - public RepeatedSingletonJob(Executor executor) { - if (executor == null) { - throw new NullPointerException("Null executor!"); - } - - this.executor = executor; - } - - public boolean isWorking() { - return working; - } - - public void resume() { - - synchronized(this) { - if (!working) { - if (logger.traceOn()) { - logger.trace("resume", ""); - } - working = true; - execute(); - } - } - } - - public abstract void task(); - public abstract boolean isSuspended(); - - public void run() { - if (logger.traceOn()) { - logger.trace("run", "execute the task"); - } - try { - task(); - } catch (Exception e) { - // A correct task() implementation should not throw exceptions. - // It may cause isSuspended() to start returning true, though. - logger.trace("run", "failed to execute the task", e); - } - - synchronized(this) { - if (!isSuspended()) { - execute(); - } else { - if (logger.traceOn()) { - logger.trace("run", "suspend the task"); - } - working = false; - } - } - - } - - private void execute() { - try { - executor.execute(this); - } catch (RejectedExecutionException e) { - logger.warning( - "execute", - "Executor threw exception (" + this.getClass().getName() + ")", - e); - throw new RejectedExecutionException( - "Executor.execute threw exception -" + - "should not be possible", e); - // User-supplied Executor should not be configured in a way that - // might cause this exception, for example if it is shared between - // several client objects and doesn't have capacity for one job - // from each one. CR 6732037 will add text to the spec explaining - // the problem. The rethrown exception will propagate either out - // of resume() to user code, or out of run() to the Executor - // (which will probably ignore it). - } - } - - private boolean working = false; - private final Executor executor; - - private static final ClassLogger logger = - new ClassLogger("javax.management.event", "RepeatedSingletonJob"); -}
--- a/jdk/src/share/classes/com/sun/jmx/interceptor/DefaultMBeanServerInterceptor.java Wed Oct 21 16:28:57 2009 +0200 +++ b/jdk/src/share/classes/com/sun/jmx/interceptor/DefaultMBeanServerInterceptor.java Wed Oct 21 17:33:18 2009 +0200 @@ -30,16 +30,15 @@ import static com.sun.jmx.defaults.JmxProperties.MBEANSERVER_LOGGER; import com.sun.jmx.mbeanserver.DynamicMBean2; import com.sun.jmx.mbeanserver.Introspector; -import com.sun.jmx.mbeanserver.MBeanInjector; import com.sun.jmx.mbeanserver.MBeanInstantiator; import com.sun.jmx.mbeanserver.ModifiableClassLoaderRepository; import com.sun.jmx.mbeanserver.NamedObject; -import com.sun.jmx.mbeanserver.NotifySupport; import com.sun.jmx.mbeanserver.Repository; import com.sun.jmx.mbeanserver.Repository.RegistrationContext; import com.sun.jmx.mbeanserver.Util; import com.sun.jmx.remote.util.EnvHelp; +import java.io.ObjectInputStream; import java.lang.ref.WeakReference; import java.security.AccessControlContext; import java.security.AccessController; @@ -48,10 +47,7 @@ import java.security.ProtectionDomain; import java.util.ArrayList; import java.util.HashSet; -import java.util.Iterator; -import java.util.LinkedList; import java.util.List; -import java.util.Queue; import java.util.Set; import java.util.WeakHashMap; import java.util.logging.Level; @@ -61,7 +57,6 @@ import javax.management.AttributeList; import javax.management.AttributeNotFoundException; import javax.management.DynamicMBean; -import javax.management.DynamicWrapperMBean; import javax.management.InstanceAlreadyExistsException; import javax.management.InstanceNotFoundException; import javax.management.IntrospectionException; @@ -70,7 +65,6 @@ import javax.management.ListenerNotFoundException; import javax.management.MBeanException; import javax.management.MBeanInfo; -import javax.management.MBeanNotificationInfo; import javax.management.MBeanPermission; import javax.management.MBeanRegistration; import javax.management.MBeanRegistrationException; @@ -81,19 +75,19 @@ import javax.management.NotCompliantMBeanException; import javax.management.Notification; import javax.management.NotificationBroadcaster; -import javax.management.NotificationBroadcasterSupport; import javax.management.NotificationEmitter; import javax.management.NotificationFilter; import javax.management.NotificationListener; import javax.management.ObjectInstance; import javax.management.ObjectName; +import javax.management.OperationsException; import javax.management.QueryEval; import javax.management.QueryExp; import javax.management.ReflectionException; import javax.management.RuntimeErrorException; import javax.management.RuntimeMBeanException; import javax.management.RuntimeOperationsException; -import javax.management.namespace.JMXNamespace; +import javax.management.loading.ClassLoaderRepository; /** * This is the default class for MBean manipulation on the agent side. It @@ -116,8 +110,7 @@ * * @since 1.5 */ -public class DefaultMBeanServerInterceptor - extends MBeanServerInterceptorSupport { +public class DefaultMBeanServerInterceptor implements MBeanServerInterceptor { /** The MBeanInstantiator object used by the * DefaultMBeanServerInterceptor */ @@ -142,14 +135,9 @@ new WeakHashMap<ListenerWrapper, WeakReference<ListenerWrapper>>(); - private final NamespaceDispatchInterceptor dispatcher; - /** The default domain of the object names */ private final String domain; - /** The mbeanServerName */ - private final String mbeanServerName; - /** The sequence number identifying the notifications sent */ // Now sequence number is handled by MBeanServerDelegate. // private int sequenceNumber=0; @@ -168,13 +156,11 @@ * @param instantiator The MBeanInstantiator that will be used to * instantiate MBeans and take care of class loading issues. * @param repository The repository to use for this MBeanServer. - * @param dispatcher The dispatcher used by this MBeanServer */ public DefaultMBeanServerInterceptor(MBeanServer outer, MBeanServerDelegate delegate, MBeanInstantiator instantiator, - Repository repository, - NamespaceDispatchInterceptor dispatcher) { + Repository repository) { if (outer == null) throw new IllegalArgumentException("outer MBeanServer cannot be null"); if (delegate == null) throw new @@ -189,8 +175,6 @@ this.instantiator = instantiator; this.repository = repository; this.domain = repository.getDefaultDomain(); - this.dispatcher = dispatcher; - this.mbeanServerName = Util.getMBeanServerSecurityName(delegate); } public ObjectInstance createMBean(String className, ObjectName name) @@ -269,8 +253,8 @@ name = nonDefaultDomain(name); } - checkMBeanPermission(mbeanServerName,className, null, null, "instantiate"); - checkMBeanPermission(mbeanServerName,className, null, name, "registerMBean"); + checkMBeanPermission(className, null, null, "instantiate"); + checkMBeanPermission(className, null, name, "registerMBean"); /* Load the appropriate class. */ if (withDefaultLoaderRepository) { @@ -334,7 +318,7 @@ final String infoClassName = getNewMBeanClassName(object); - checkMBeanPermission(mbeanServerName,infoClassName, null, name, "registerMBean"); + checkMBeanPermission(infoClassName, null, name, "registerMBean"); checkMBeanTrustPermission(theClass); return registerObject(infoClassName, object, name); @@ -443,8 +427,7 @@ DynamicMBean instance = getMBean(name); // may throw InstanceNotFoundException - checkMBeanPermission(mbeanServerName, instance, null, name, - "unregisterMBean"); + checkMBeanPermission(instance, null, name, "unregisterMBean"); if (instance instanceof MBeanRegistration) preDeregisterInvoke((MBeanRegistration) instance); @@ -478,8 +461,7 @@ name = nonDefaultDomain(name); DynamicMBean instance = getMBean(name); - checkMBeanPermission(mbeanServerName, - instance, null, name, "getObjectInstance"); + checkMBeanPermission(instance, null, name, "getObjectInstance"); final String className = getClassName(instance); @@ -491,7 +473,7 @@ if (sm != null) { // Check if the caller has the right to invoke 'queryMBeans' // - checkMBeanPermission(mbeanServerName,(String) null, null, null, "queryMBeans"); + checkMBeanPermission((String) null, null, null, "queryMBeans"); // Perform query without "query". // @@ -504,7 +486,7 @@ new HashSet<ObjectInstance>(list.size()); for (ObjectInstance oi : list) { try { - checkMBeanPermission(mbeanServerName,oi.getClassName(), null, + checkMBeanPermission(oi.getClassName(), null, oi.getObjectName(), "queryMBeans"); allowedList.add(oi); } catch (SecurityException e) { @@ -537,7 +519,7 @@ if (sm != null) { // Check if the caller has the right to invoke 'queryNames' // - checkMBeanPermission(mbeanServerName,(String) null, null, null, "queryNames"); + checkMBeanPermission((String) null, null, null, "queryNames"); // Perform query without "query". // @@ -550,7 +532,7 @@ new HashSet<ObjectInstance>(list.size()); for (ObjectInstance oi : list) { try { - checkMBeanPermission(mbeanServerName, oi.getClassName(), null, + checkMBeanPermission(oi.getClassName(), null, oi.getObjectName(), "queryNames"); allowedList.add(oi); } catch (SecurityException e) { @@ -602,7 +584,7 @@ if (sm != null) { // Check if the caller has the right to invoke 'getDomains' // - checkMBeanPermission(mbeanServerName, (String) null, null, null, "getDomains"); + checkMBeanPermission((String) null, null, null, "getDomains"); // Return domains // @@ -614,8 +596,8 @@ List<String> result = new ArrayList<String>(domains.length); for (int i = 0; i < domains.length; i++) { try { - ObjectName dom = ObjectName.valueOf(domains[i] + ":x=x"); - checkMBeanPermission(mbeanServerName, (String) null, null, dom, "getDomains"); + ObjectName dom = Util.newObjectName(domains[i] + ":x=x"); + checkMBeanPermission((String) null, null, dom, "getDomains"); result.add(domains[i]); } catch (SecurityException e) { // OK: Do not add this domain to the list @@ -659,8 +641,7 @@ } final DynamicMBean instance = getMBean(name); - checkMBeanPermission(mbeanServerName, instance, attribute, - name, "getAttribute"); + checkMBeanPermission(instance, attribute, name, "getAttribute"); try { return instance.getAttribute(attribute); @@ -705,7 +686,7 @@ // Check if the caller has the right to invoke 'getAttribute' // - checkMBeanPermission(mbeanServerName, classname, null, name, "getAttribute"); + checkMBeanPermission(classname, null, name, "getAttribute"); // Check if the caller has the right to invoke 'getAttribute' // on each specific attribute @@ -714,8 +695,7 @@ new ArrayList<String>(attributes.length); for (String attr : attributes) { try { - checkMBeanPermission(mbeanServerName, classname, attr, - name, "getAttribute"); + checkMBeanPermission(classname, attr, name, "getAttribute"); allowedList.add(attr); } catch (SecurityException e) { // OK: Do not add this attribute to the list @@ -760,8 +740,7 @@ } DynamicMBean instance = getMBean(name); - checkMBeanPermission(mbeanServerName, instance, attribute.getName(), - name, "setAttribute"); + checkMBeanPermission(instance, attribute.getName(), name, "setAttribute"); try { instance.setAttribute(attribute); @@ -803,7 +782,7 @@ // Check if the caller has the right to invoke 'setAttribute' // - checkMBeanPermission(mbeanServerName, classname, null, name, "setAttribute"); + checkMBeanPermission(classname, null, name, "setAttribute"); // Check if the caller has the right to invoke 'setAttribute' // on each specific attribute @@ -811,7 +790,7 @@ allowedAttributes = new AttributeList(attributes.size()); for (Attribute attribute : attributes.asList()) { try { - checkMBeanPermission(mbeanServerName, classname, attribute.getName(), + checkMBeanPermission(classname, attribute.getName(), name, "setAttribute"); allowedAttributes.add(attribute); } catch (SecurityException e) { @@ -835,8 +814,7 @@ name = nonDefaultDomain(name); DynamicMBean instance = getMBean(name); - checkMBeanPermission(mbeanServerName, instance, operationName, - name, "invoke"); + checkMBeanPermission(instance, operationName, name, "invoke"); try { return instance.invoke(operationName, params, signature); } catch (Throwable t) { @@ -919,12 +897,6 @@ DynamicMBean mbean = Introspector.makeDynamicMBean(object); - //Access the ObjectName template value only if the provided name is null - if(name == null) { - name = Introspector.templateToObjectName(mbean.getMBeanInfo(). - getDescriptor(), mbean); - } - return registerDynamicMBean(classname, mbean, name); } @@ -953,8 +925,6 @@ ResourceContext context = null; try { - mbean = injectResources(mbean, server, logicalName); - if (mbean instanceof DynamicMBean2) { try { ((DynamicMBean2) mbean).preRegister2(server, logicalName); @@ -973,8 +943,7 @@ ObjectName.getInstance(nonDefaultDomain(logicalName)); } - checkMBeanPermission(mbeanServerName, classname, null, logicalName, - "registerMBean"); + checkMBeanPermission(classname, null, logicalName, "registerMBean"); if (logicalName == null) { final RuntimeException wrapped = @@ -988,10 +957,9 @@ // Register the MBean with the repository. // Returns the resource context that was used. // The returned context does nothing for regular MBeans. - // For ClassLoader MBeans and JMXNamespace (and JMXDomain) - // MBeans - the context makes it possible to register these + // For ClassLoader MBeans the context makes it possible to register these // objects with the appropriate framework artifacts, such as - // the CLR or the dispatcher, from within the repository lock. + // the CLR, from within the repository lock. // In case of success, we also need to call context.done() at the // end of this method. // @@ -1045,27 +1013,6 @@ else return name; } - private static DynamicMBean injectResources( - DynamicMBean mbean, MBeanServer mbs, ObjectName name) - throws MBeanRegistrationException { - try { - Object resource = getResource(mbean); - MBeanInjector.inject(resource, mbs, name); - if (MBeanInjector.injectsSendNotification(resource)) { - MBeanNotificationInfo[] mbnis = - mbean.getMBeanInfo().getNotifications(); - NotificationBroadcasterSupport nbs = - new NotificationBroadcasterSupport(mbnis); - MBeanInjector.injectSendNotification(resource, nbs); - mbean = NotifySupport.wrap(mbean, nbs); - } - return mbean; - } catch (Throwable t) { - throwMBeanRegistrationException(t, "injecting @Resources"); - return null; // not reached - } - } - private static void postRegister( ObjectName logicalName, DynamicMBean mbean, boolean registrationDone, boolean registerFailed) { @@ -1151,19 +1098,12 @@ } private static Object getResource(DynamicMBean mbean) { - if (mbean instanceof DynamicWrapperMBean) - return ((DynamicWrapperMBean) mbean).getWrappedObject(); + if (mbean instanceof DynamicMBean2) + return ((DynamicMBean2) mbean).getResource(); else return mbean; } - private static ClassLoader getResourceLoader(DynamicMBean mbean) { - if (mbean instanceof DynamicWrapperMBean) - return ((DynamicWrapperMBean) mbean).getWrappedClassLoader(); - else - return mbean.getClass().getClassLoader(); - } - private ObjectName nonDefaultDomain(ObjectName name) { if (name == null || name.getDomain().length() > 0) return name; @@ -1177,7 +1117,7 @@ if one is supplied where it shouldn't be). */ final String completeName = domain + name; - return ObjectName.valueOf(completeName); + return Util.newObjectName(completeName); } public String getDefaultDomain() { @@ -1243,8 +1183,7 @@ } DynamicMBean instance = getMBean(name); - checkMBeanPermission(mbeanServerName, instance, null, - name, "addNotificationListener"); + checkMBeanPermission(instance, null, name, "addNotificationListener"); NotificationBroadcaster broadcaster = getNotificationBroadcaster(name, instance, @@ -1381,8 +1320,7 @@ } DynamicMBean instance = getMBean(name); - checkMBeanPermission(mbeanServerName, instance, null, name, - "removeNotificationListener"); + checkMBeanPermission(instance, null, name, "removeNotificationListener"); /* We could simplify the code by assigning broadcaster after assigning listenerWrapper, but that would change the error @@ -1415,8 +1353,8 @@ Class<T> reqClass) { if (reqClass.isInstance(instance)) return reqClass.cast(instance); - if (instance instanceof DynamicWrapperMBean) - instance = ((DynamicWrapperMBean) instance).getWrappedObject(); + if (instance instanceof DynamicMBean2) + instance = ((DynamicMBean2) instance).getResource(); if (reqClass.isInstance(instance)) return reqClass.cast(instance); final RuntimeException exc = @@ -1452,7 +1390,7 @@ throw new JMRuntimeException("MBean " + name + "has no MBeanInfo"); - checkMBeanPermission(mbeanServerName, mbi.getClassName(), null, name, "getMBeanInfo"); + checkMBeanPermission(mbi.getClassName(), null, name, "getMBeanInfo"); return mbi; } @@ -1461,8 +1399,7 @@ throws InstanceNotFoundException { final DynamicMBean instance = getMBean(name); - checkMBeanPermission(mbeanServerName, - instance, null, name, "isInstanceOf"); + checkMBeanPermission(instance, null, name, "isInstanceOf"); try { Object resource = getResource(instance); @@ -1474,20 +1411,12 @@ if (resourceClassName.equals(className)) return true; - final ClassLoader cl = getResourceLoader(instance); + final ClassLoader cl = resource.getClass().getClassLoader(); final Class<?> classNameClass = Class.forName(className, false, cl); if (classNameClass.isInstance(resource)) return true; - // Ensure that isInstanceOf(NotificationEmitter) is true when - // the MBean is a NotificationEmitter by virtue of a @Resource - // annotation specifying a SendNotification resource. - // This is a hack. - if (instance instanceof NotificationBroadcaster && - classNameClass.isAssignableFrom(NotificationEmitter.class)) - return true; - final Class<?> resourceClass = Class.forName(resourceClassName, false, cl); return classNameClass.isAssignableFrom(resourceClass); } catch (Exception x) { @@ -1513,9 +1442,8 @@ throws InstanceNotFoundException { DynamicMBean instance = getMBean(mbeanName); - checkMBeanPermission(mbeanServerName, instance, null, mbeanName, - "getClassLoaderFor"); - return getResourceLoader(instance); + checkMBeanPermission(instance, null, mbeanName, "getClassLoaderFor"); + return getResource(instance).getClass().getClassLoader(); } /** @@ -1529,13 +1457,12 @@ throws InstanceNotFoundException { if (loaderName == null) { - checkMBeanPermission(mbeanServerName, (String) null, null, null, "getClassLoader"); + checkMBeanPermission((String) null, null, null, "getClassLoader"); return server.getClass().getClassLoader(); } DynamicMBean instance = getMBean(loaderName); - checkMBeanPermission(mbeanServerName, instance, null, loaderName, - "getClassLoader"); + checkMBeanPermission(instance, null, loaderName, "getClassLoader"); Object resource = getResource(instance); @@ -1757,6 +1684,49 @@ } } + public Object instantiate(String className) throws ReflectionException, + MBeanException { + throw new UnsupportedOperationException("Not supported yet."); + } + + public Object instantiate(String className, ObjectName loaderName) throws ReflectionException, + MBeanException, + InstanceNotFoundException { + throw new UnsupportedOperationException("Not supported yet."); + } + + public Object instantiate(String className, Object[] params, + String[] signature) throws ReflectionException, MBeanException { + throw new UnsupportedOperationException("Not supported yet."); + } + + public Object instantiate(String className, ObjectName loaderName, + Object[] params, String[] signature) throws ReflectionException, + MBeanException, + InstanceNotFoundException { + throw new UnsupportedOperationException("Not supported yet."); + } + + public ObjectInputStream deserialize(ObjectName name, byte[] data) throws InstanceNotFoundException, + OperationsException { + throw new UnsupportedOperationException("Not supported yet."); + } + + public ObjectInputStream deserialize(String className, byte[] data) throws OperationsException, + ReflectionException { + throw new UnsupportedOperationException("Not supported yet."); + } + + public ObjectInputStream deserialize(String className, ObjectName loaderName, + byte[] data) throws InstanceNotFoundException, OperationsException, + ReflectionException { + throw new UnsupportedOperationException("Not supported yet."); + } + + public ClassLoaderRepository getClassLoaderRepository() { + throw new UnsupportedOperationException("Not supported yet."); + } + private static class ListenerWrapper implements NotificationListener { ListenerWrapper(NotificationListener l, ObjectName name, Object mbean) { @@ -1834,30 +1804,26 @@ return mbean.getMBeanInfo().getClassName(); } - private static void checkMBeanPermission(String mbeanServerName, - DynamicMBean mbean, + private static void checkMBeanPermission(DynamicMBean mbean, String member, ObjectName objectName, String actions) { SecurityManager sm = System.getSecurityManager(); if (sm != null) { - checkMBeanPermission(mbeanServerName, - safeGetClassName(mbean), + checkMBeanPermission(safeGetClassName(mbean), member, objectName, actions); } } - private static void checkMBeanPermission(String mbeanServerName, - String classname, + private static void checkMBeanPermission(String classname, String member, ObjectName objectName, String actions) { SecurityManager sm = System.getSecurityManager(); if (sm != null) { - Permission perm = new MBeanPermission(mbeanServerName, - classname, + Permission perm = new MBeanPermission(classname, member, objectName, actions); @@ -1923,12 +1889,6 @@ throws InstanceAlreadyExistsException, MBeanRegistrationException { - // this will throw an exception if the pair (resource, logicalName) - // violates namespace conventions - for instance, if logicalName - // ends with // but resource is not a JMXNamespace. - // - checkResourceObjectNameConstraints(resource, logicalName); - // Creates a registration context, if needed. // final ResourceContext context = @@ -1996,56 +1956,6 @@ /** - * Checks that the ObjectName is legal with regards to the - * type of the MBean resource. - * If the MBean name is domain:type=JMXDomain, the - * MBean must be a JMXDomain. - * If the MBean name is namespace//:type=JMXNamespace, the - * MBean must be a JMXNamespace. - * If the MBean is a JMXDomain, its name - * must be domain:type=JMXDomain. - * If the MBean is a JMXNamespace, its name - * must be namespace//:type=JMXNamespace. - */ - private void checkResourceObjectNameConstraints(Object resource, - ObjectName logicalName) - throws MBeanRegistrationException { - try { - dispatcher.checkLocallyRegistrable(resource, logicalName); - } catch (Throwable x) { - DefaultMBeanServerInterceptor.throwMBeanRegistrationException(x, "validating ObjectName"); - } - } - - /** - * Registers a JMXNamespace with the dispatcher. - * This method is called by the ResourceContext from within the - * repository lock. - * @param namespace The JMXNamespace - * @param logicalName The JMXNamespaceMBean ObjectName - * @param postQueue A queue that will be processed after postRegister. - */ - private void addJMXNamespace(JMXNamespace namespace, - final ObjectName logicalName, - final Queue<Runnable> postQueue) { - dispatcher.addInterceptorFor(logicalName, namespace, postQueue); - } - - /** - * Unregisters a JMXNamespace from the dispatcher. - * This method is called by the ResourceContext from within the - * repository lock. - * @param namespace The JMXNamespace - * @param logicalName The JMXNamespaceMBean ObjectName - * @param postQueue A queue that will be processed after postDeregister. - */ - private void removeJMXNamespace(JMXNamespace namespace, - final ObjectName logicalName, - final Queue<Runnable> postQueue) { - dispatcher.removeInterceptorFor(logicalName, namespace, postQueue); - } - - /** * Registers a ClassLoader with the CLR. * This method is called by the ResourceContext from within the * repository lock. @@ -2100,51 +2010,6 @@ /** - * Creates a ResourceContext for a JMXNamespace MBean. - * The resource context makes it possible to add the JMXNamespace to - * (ResourceContext.registering) or resp. remove the JMXNamespace from - * (ResourceContext.unregistered) the NamespaceDispatchInterceptor - * when the associated MBean is added to or resp. removed from the - * repository. - * Note: JMXDomains are special sub classes of JMXNamespaces and - * are also handled by this object. - * - * @param namespace The JMXNamespace MBean being registered or - * unregistered. - * @param logicalName The name of the JMXNamespace MBean. - * @return a ResourceContext that takes in charge the addition or removal - * of the namespace to or from the NamespaceDispatchInterceptor. - */ - private ResourceContext createJMXNamespaceContext( - final JMXNamespace namespace, - final ObjectName logicalName) { - final Queue<Runnable> doneTaskQueue = new LinkedList<Runnable>(); - return new ResourceContext() { - - public void registering() { - addJMXNamespace(namespace, logicalName, doneTaskQueue); - } - - public void unregistered() { - removeJMXNamespace(namespace, logicalName, - doneTaskQueue); - } - - public void done() { - for (Runnable r : doneTaskQueue) { - try { - r.run(); - } catch (RuntimeException x) { - MBEANSERVER_LOGGER.log(Level.FINE, - "Failed to process post queue for "+ - logicalName, x); - } - } - } - }; - } - - /** * Creates a ResourceContext for a ClassLoader MBean. * The resource context makes it possible to add the ClassLoader to * (ResourceContext.registering) or resp. remove the ClassLoader from @@ -2180,8 +2045,7 @@ * Creates a ResourceContext for the given resource. * If the resource does not need a ResourceContext, returns * ResourceContext.NONE. - * At this time, only JMXNamespaces and ClassLoaders need a - * ResourceContext. + * At this time, only ClassLoaders need a ResourceContext. * * @param resource The resource being registered or unregistered. * @param logicalName The name of the associated MBean. @@ -2189,10 +2053,6 @@ */ private ResourceContext makeResourceContextFor(Object resource, ObjectName logicalName) { - if (resource instanceof JMXNamespace) { - return createJMXNamespaceContext((JMXNamespace) resource, - logicalName); - } if (resource instanceof ClassLoader) { return createClassLoaderContext((ClassLoader) resource, logicalName);
--- a/jdk/src/share/classes/com/sun/jmx/interceptor/DispatchInterceptor.java Wed Oct 21 16:28:57 2009 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,551 +0,0 @@ -/* - * Copyright 2008 Sun Microsystems, Inc. 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. Sun designates this - * particular file as subject to the "Classpath" exception as provided - * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, - * CA 95054 USA or visit www.sun.com if you need additional information or - * have any questions. - */ - -package com.sun.jmx.interceptor; - - -import java.util.Collections; -import java.util.HashMap; -import java.util.Map; -import java.util.Queue; -import java.util.Set; - -import javax.management.Attribute; -import javax.management.AttributeList; -import javax.management.AttributeNotFoundException; -import javax.management.InstanceAlreadyExistsException; -import javax.management.InstanceNotFoundException; -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.QueryExp; -import javax.management.ReflectionException; -import javax.management.namespace.JMXNamespace; - -/** - * A dispatcher that dispatches to MBeanServers. - * <p><b> - * This API is a Sun internal API and is subject to changes without notice. - * </b></p> - * @since 1.7 - */ -// -// This is the base class for implementing dispatchers. We have two concrete -// dispatcher implementations: -// -// * A NamespaceDispatchInterceptor, which dispatch calls to existing -// namespace interceptors -// * A DomainDispatchInterceptor, which dispatch calls to existing domain -// interceptors. -// -// With the JMX Namespaces feature, the JMX MBeanServer is now structured -// as follows: -// -// The JMX MBeanServer delegates to a NamespaceDispatchInterceptor, -// which either dispatches to a namespace, or delegates to the -// DomainDispatchInterceptor (if the object name contained no namespace). -// The DomainDispatchInterceptor in turn either dispatches to a domain (if -// there is a JMXDomain for that domain) or delegates to the -// DefaultMBeanServerInterceptor (if there is no JMXDomain for that -// domain). This makes the following picture: -// -// JMX MBeanServer (outer shell) -// | -// | -// NamespaceDispatchInterceptor -// / \ -// no namespace in object name? \ -// / \ -// / dispatch to namespace -// DomainDispatchInterceptor -// / \ -// no JMXDomain for domain? \ -// / \ -// / dispatch to domain -// DefaultMBeanServerInterceptor -// / -// invoke locally registered MBean -// -// The logic for maintaining a map of interceptors -// and dispatching to impacted interceptor, is implemented in this -// base class, which both NamespaceDispatchInterceptor and -// DomainDispatchInterceptor extend. -// -public abstract class DispatchInterceptor - <T extends MBeanServer, N extends JMXNamespace> - extends MBeanServerInterceptorSupport { - - /** - * This is an abstraction which allows us to handle queryNames - * and queryMBeans with the same algorithm. There are some subclasses - * where we need to override both queryNames & queryMBeans to apply - * the same transformation (usually aggregation of results when - * several namespaces/domains are impacted) to both algorithms. - * Usually the only thing that varies between the algorithm of - * queryNames & the algorithm of queryMBean is the type of objects - * in the returned Set. By using a QueryInvoker we can implement the - * transformation only once and apply it to both queryNames & - * queryMBeans. - * @see QueryInterceptor below, and its subclass in - * {@link DomainDispatcher}. - **/ - static abstract class QueryInvoker<T> { - abstract Set<T> query(MBeanServer mbs, - ObjectName pattern, QueryExp query); - } - - /** - * Used to perform queryNames. A QueryInvoker that invokes - * queryNames on an MBeanServer. - **/ - final static QueryInvoker<ObjectName> queryNamesInvoker = - new QueryInvoker<ObjectName>() { - Set<ObjectName> query(MBeanServer mbs, - ObjectName pattern, QueryExp query) { - return mbs.queryNames(pattern,query); - } - }; - - /** - * Used to perform queryMBeans. A QueryInvoker that invokes - * queryMBeans on an MBeanServer. - **/ - final static QueryInvoker<ObjectInstance> queryMBeansInvoker = - new QueryInvoker<ObjectInstance>() { - Set<ObjectInstance> query(MBeanServer mbs, - ObjectName pattern, QueryExp query) { - return mbs.queryMBeans(pattern,query); - } - }; - - /** - * We use this class to intercept queries. - * There's a special case for JMXNamespace MBeans, because - * "namespace//*:*" matches both "namespace//domain:k=v" and - * "namespace//:type=JMXNamespace". - * Therefore, queries may need to be forwarded to more than - * on interceptor and the results aggregated... - */ - static class QueryInterceptor { - final MBeanServer wrapped; - QueryInterceptor(MBeanServer mbs) { - wrapped = mbs; - } - <X> Set<X> query(ObjectName pattern, QueryExp query, - QueryInvoker<X> invoker, MBeanServer server) { - return invoker.query(server, pattern, query); - } - - public Set<ObjectName> queryNames(ObjectName pattern, QueryExp query) { - return query(pattern,query,queryNamesInvoker,wrapped); - } - - public Set<ObjectInstance> queryMBeans(ObjectName pattern, - QueryExp query) { - return query(pattern,query,queryMBeansInvoker,wrapped); - } - } - - // We don't need a ConcurrentHashMap here because getkeys() returns - // an array of keys. Therefore there's no risk to have a - // ConcurrentModificationException. We must however take into - // account the fact that there can be no interceptor for - // some of the returned keys if the map is being modified by - // another thread, or by a callback within the same thread... - // See getKeys() in this class and query() in DomainDispatcher. - // - private final Map<String,T> handlerMap = - Collections.synchronizedMap( - new HashMap<String,T>()); - - // The key at which an interceptor for accessing the named MBean can be - // found in the handlerMap. Note: there doesn't need to be an interceptor - // for that key in the Map. - // - abstract String getHandlerKey(ObjectName name); - - // Returns an interceptor for that name, or null if there's no interceptor - // for that name. - abstract MBeanServer getInterceptorOrNullFor(ObjectName name); - - // Returns a QueryInterceptor for that pattern. - abstract QueryInterceptor getInterceptorForQuery(ObjectName pattern); - - // Returns the ObjectName of the JMXNamespace (or JMXDomain) for that - // key (a namespace or a domain name). - abstract ObjectName getHandlerNameFor(String key); - - // Creates an interceptor for the given key, name, JMXNamespace (or - // JMXDomain). Note: this will be either a NamespaceInterceptor - // wrapping a JMXNamespace, if this object is an instance of - // NamespaceDispatchInterceptor, or a DomainInterceptor wrapping a - // JMXDomain, if this object is an instance of DomainDispatchInterceptor. - abstract T createInterceptorFor(String key, ObjectName name, - N jmxNamespace, Queue<Runnable> postRegisterQueue); - // - // The next interceptor in the chain. - // - // For the NamespaceDispatchInterceptor, this the DomainDispatchInterceptor. - // For the DomainDispatchInterceptor, this is the - // DefaultMBeanServerInterceptor. - // - // The logic of when to invoke the next interceptor in the chain depends - // on the logic of the concrete dispatcher class. - // - // For instance, the NamespaceDispatchInterceptor invokes the next - // interceptor when the object name doesn't contain any namespace. - // - // On the other hand, the DomainDispatchInterceptor invokes the - // next interceptor when there's no interceptor for the accessed domain. - // - abstract MBeanServer getNextInterceptor(); - - // hook for cleanup in subclasses. - void interceptorReleased(T interceptor, - Queue<Runnable> postDeregisterQueue) { - // hook - } - - // Hook for subclasses. - MBeanServer getInterceptorForCreate(ObjectName name) - throws MBeanRegistrationException { - final MBeanServer ns = getInterceptorOrNullFor(name); - if (ns == null) // name cannot be null here. - throw new MBeanRegistrationException( - new IllegalArgumentException("No such MBean handler: " + - getHandlerKey(name) + " for " +name)); - return ns; - } - - // Hook for subclasses. - MBeanServer getInterceptorForInstance(ObjectName name) - throws InstanceNotFoundException { - final MBeanServer ns = getInterceptorOrNullFor(name); - if (ns == null) // name cannot be null here. - throw new InstanceNotFoundException(String.valueOf(name)); - return ns; - } - - // sanity checks - void validateHandlerNameFor(String key, ObjectName name) { - if (key == null || key.equals("")) - throw new IllegalArgumentException("invalid key for "+name+": "+key); - final ObjectName handlerName = getHandlerNameFor(key); - if (!name.equals(handlerName)) - throw new IllegalArgumentException("bad handler name: "+name+ - ". Should be: "+handlerName); - } - - // Called by the DefaultMBeanServerInterceptor when an instance - // of JMXNamespace (or a subclass of it) is registered as an MBean. - // This method is usually invoked from within the repository lock, - // hence the necessity of the postRegisterQueue. - public void addInterceptorFor(ObjectName name, N jmxNamespace, - Queue<Runnable> postRegisterQueue) { - final String key = getHandlerKey(name); - validateHandlerNameFor(key,name); - synchronized (handlerMap) { - final T exists = - handlerMap.get(key); - if (exists != null) - throw new IllegalArgumentException(key+ - ": handler already exists"); - - final T ns = createInterceptorFor(key,name,jmxNamespace, - postRegisterQueue); - handlerMap.put(key,ns); - } - } - - // Called by the DefaultMBeanServerInterceptor when an instance - // of JMXNamespace (or a subclass of it) is deregistered. - // This method is usually invoked from within the repository lock, - // hence the necessity of the postDeregisterQueue. - public void removeInterceptorFor(ObjectName name, N jmxNamespace, - Queue<Runnable> postDeregisterQueue) { - final String key = getHandlerKey(name); - final T ns; - synchronized(handlerMap) { - ns = handlerMap.remove(key); - } - interceptorReleased(ns,postDeregisterQueue); - } - - // Get the interceptor for that key. - T getInterceptor(String key) { - synchronized (handlerMap) { - return handlerMap.get(key); - } - } - - // We return an array of keys, which makes it possible to make - // concurrent modifications of the handlerMap, provided that - // the code which loops over the keys is prepared to handle null - // interceptors. - // See declaration of handlerMap above, and see also query() in - // DomainDispatcher - // - public String[] getKeys() { - synchronized (handlerMap) { - final int size = handlerMap.size(); - return handlerMap.keySet().toArray(new String[size]); - } - } - - // From MBeanServer - public final ObjectInstance createMBean(String className, ObjectName name) - throws ReflectionException, InstanceAlreadyExistsException, - MBeanRegistrationException, MBeanException, - NotCompliantMBeanException { - return getInterceptorForCreate(name).createMBean(className,name); - } - - // From MBeanServer - public final ObjectInstance createMBean(String className, ObjectName name, - ObjectName loaderName) - throws ReflectionException, InstanceAlreadyExistsException, - MBeanRegistrationException, MBeanException, - NotCompliantMBeanException, InstanceNotFoundException{ - return getInterceptorForCreate(name).createMBean(className,name,loaderName); - } - - // From MBeanServer - public final ObjectInstance createMBean(String className, ObjectName name, - Object params[], String signature[]) - throws ReflectionException, InstanceAlreadyExistsException, - MBeanRegistrationException, MBeanException, - NotCompliantMBeanException{ - return getInterceptorForCreate(name). - createMBean(className,name,params,signature); - } - - // From MBeanServer - public final ObjectInstance createMBean(String className, ObjectName name, - ObjectName loaderName, Object params[], - String signature[]) - throws ReflectionException, InstanceAlreadyExistsException, - MBeanRegistrationException, MBeanException, - NotCompliantMBeanException, InstanceNotFoundException{ - return getInterceptorForCreate(name).createMBean(className,name,loaderName, - params,signature); - } - - // From MBeanServer - public final ObjectInstance registerMBean(Object object, ObjectName name) - throws InstanceAlreadyExistsException, MBeanRegistrationException, - NotCompliantMBeanException { - return getInterceptorForCreate(name).registerMBean(object,name); - } - - // From MBeanServer - public final void unregisterMBean(ObjectName name) - throws InstanceNotFoundException, MBeanRegistrationException { - getInterceptorForInstance(name).unregisterMBean(name); - } - - // From MBeanServer - public final ObjectInstance getObjectInstance(ObjectName name) - throws InstanceNotFoundException { - return getInterceptorForInstance(name).getObjectInstance(name); - } - - // From MBeanServer - public final Set<ObjectInstance> queryMBeans(ObjectName name, - QueryExp query) { - final QueryInterceptor queryInvoker = - getInterceptorForQuery(name); - if (queryInvoker == null) return Collections.emptySet(); - else return queryInvoker.queryMBeans(name,query); - } - - // From MBeanServer - public final Set<ObjectName> queryNames(ObjectName name, QueryExp query) { - final QueryInterceptor queryInvoker = - getInterceptorForQuery(name); - if (queryInvoker == null) return Collections.emptySet(); - else return queryInvoker.queryNames(name,query); - } - - // From MBeanServer - public final boolean isRegistered(ObjectName name) { - final MBeanServer mbs = getInterceptorOrNullFor(name); - if (mbs == null) return false; - else return mbs.isRegistered(name); - } - - // From MBeanServer - public Integer getMBeanCount() { - return getNextInterceptor().getMBeanCount(); - } - - // From MBeanServer - public final Object getAttribute(ObjectName name, String attribute) - throws MBeanException, AttributeNotFoundException, - InstanceNotFoundException, ReflectionException { - return getInterceptorForInstance(name).getAttribute(name,attribute); - } - - // From MBeanServer - public final AttributeList getAttributes(ObjectName name, - String[] attributes) - throws InstanceNotFoundException, ReflectionException { - return getInterceptorForInstance(name).getAttributes(name,attributes); - } - - // From MBeanServer - public final void setAttribute(ObjectName name, Attribute attribute) - throws InstanceNotFoundException, AttributeNotFoundException, - InvalidAttributeValueException, MBeanException, - ReflectionException { - getInterceptorForInstance(name).setAttribute(name,attribute); - } - - // From MBeanServer - public final AttributeList setAttributes(ObjectName name, - AttributeList attributes) - throws InstanceNotFoundException, ReflectionException { - return getInterceptorForInstance(name).setAttributes(name,attributes); - } - - // From MBeanServer - public final Object invoke(ObjectName name, String operationName, - Object params[], String signature[]) - throws InstanceNotFoundException, MBeanException, - ReflectionException { - return getInterceptorForInstance(name).invoke(name,operationName,params, - signature); - } - - // From MBeanServer - public String getDefaultDomain() { - return getNextInterceptor().getDefaultDomain(); - } - - /** - * Returns the list of domains in which any MBean is currently - * registered. - */ - public abstract String[] getDomains(); - - // From MBeanServer - public final void addNotificationListener(ObjectName name, - NotificationListener listener, - NotificationFilter filter, - Object handback) - throws InstanceNotFoundException { - getInterceptorForInstance(name). - addNotificationListener(name,listener,filter, - handback); - } - - - // From MBeanServer - public final void addNotificationListener(ObjectName name, - ObjectName listener, - NotificationFilter filter, - Object handback) - throws InstanceNotFoundException { - getInterceptorForInstance(name). - addNotificationListener(name,listener,filter, - handback); - } - - // From MBeanServer - public final void removeNotificationListener(ObjectName name, - ObjectName listener) - throws InstanceNotFoundException, ListenerNotFoundException { - getInterceptorForInstance(name). - removeNotificationListener(name,listener); - } - - // From MBeanServer - public final void removeNotificationListener(ObjectName name, - ObjectName listener, - NotificationFilter filter, - Object handback) - throws InstanceNotFoundException, ListenerNotFoundException { - getInterceptorForInstance(name). - removeNotificationListener(name,listener,filter, - handback); - } - - - // From MBeanServer - public final void removeNotificationListener(ObjectName name, - NotificationListener listener) - throws InstanceNotFoundException, ListenerNotFoundException { - getInterceptorForInstance(name). - removeNotificationListener(name,listener); - } - - // From MBeanServer - public final void removeNotificationListener(ObjectName name, - NotificationListener listener, - NotificationFilter filter, - Object handback) - throws InstanceNotFoundException, ListenerNotFoundException { - getInterceptorForInstance(name). - removeNotificationListener(name,listener,filter, - handback); - } - - // From MBeanServer - public final MBeanInfo getMBeanInfo(ObjectName name) - throws InstanceNotFoundException, IntrospectionException, - ReflectionException { - return getInterceptorForInstance(name).getMBeanInfo(name); - } - - - // From MBeanServer - public final boolean isInstanceOf(ObjectName name, String className) - throws InstanceNotFoundException { - return getInterceptorForInstance(name).isInstanceOf(name,className); - } - - // From MBeanServer - public final ClassLoader getClassLoaderFor(ObjectName mbeanName) - throws InstanceNotFoundException { - return getInterceptorForInstance(mbeanName). - getClassLoaderFor(mbeanName); - } - - // From MBeanServer - public final ClassLoader getClassLoader(ObjectName loaderName) - throws InstanceNotFoundException { - return getInterceptorForInstance(loaderName). - getClassLoader(loaderName); - } - -}
--- a/jdk/src/share/classes/com/sun/jmx/interceptor/DomainDispatchInterceptor.java Wed Oct 21 16:28:57 2009 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,350 +0,0 @@ -/* - * Copyright 2008 Sun Microsystems, Inc. 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. Sun designates this - * particular file as subject to the "Classpath" exception as provided - * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, - * CA 95054 USA or visit www.sun.com if you need additional information or - * have any questions. - */ - -package com.sun.jmx.interceptor; - -import com.sun.jmx.defaults.JmxProperties; -import com.sun.jmx.mbeanserver.MBeanInstantiator; -import com.sun.jmx.mbeanserver.Repository; -import com.sun.jmx.mbeanserver.Util; -import com.sun.jmx.namespace.DomainInterceptor; -import java.util.Queue; -import java.util.Set; - -import java.util.logging.Level; -import java.util.logging.Logger; - -import javax.management.MBeanServer; -import javax.management.MBeanServerDelegate; -import javax.management.ObjectName; -import javax.management.QueryExp; -import javax.management.namespace.JMXDomain; -import static javax.management.namespace.JMXNamespaces.NAMESPACE_SEPARATOR; - -/** - * A dispatcher that dispatch incoming MBeanServer requests to - * DomainInterceptors. - * <p><b> - * This API is a Sun internal API and is subject to changes without notice. - * </b></p> - * @since 1.7 - */ -// -// See comments in DispatchInterceptor. -// -class DomainDispatchInterceptor - extends DispatchInterceptor<DomainInterceptor, JMXDomain> { - - /** - * A logger for this class. - **/ - private static final Logger LOG = JmxProperties.NAMESPACE_LOGGER; - - private static final ObjectName ALL_DOMAINS = - JMXDomain.getDomainObjectName("*"); - - - /** - * A QueryInterceptor that perform & aggregates queries spanning several - * domains. - */ - final static class AggregatingQueryInterceptor extends QueryInterceptor { - - private final DomainDispatchInterceptor parent; - AggregatingQueryInterceptor(DomainDispatchInterceptor dispatcher) { - super(dispatcher.nextInterceptor); - parent = dispatcher; - } - - /** - * Perform queryNames or queryMBeans, depending on which QueryInvoker - * is passed as argument. This is closures without closures. - **/ - @Override - <T> Set<T> query(ObjectName pattern, QueryExp query, - QueryInvoker<T> invoker, MBeanServer localNamespace) { - final Set<T> local = invoker.query(localNamespace, pattern, query); - - // Add all matching MBeans from local namespace. - final Set<T> res = Util.cloneSet(local); - - if (pattern == null) pattern = ObjectName.WILDCARD; - final boolean all = pattern.getDomain().equals("*"); - - final String domain = pattern.getDomain(); - - // If there's no domain pattern, just include the pattern's domain. - // Otherwiae, loop over all virtual domains (parent.getKeys()). - final String[] keys = - (pattern.isDomainPattern() ? - parent.getKeys() : new String[]{domain}); - - // Add all matching MBeans from each virtual domain - // - for (String key : keys) { - // Only invoke those virtual domain which are selected - // by the domain pattern - // - if (!all && !Util.isDomainSelected(key, domain)) - continue; - - try { - final MBeanServer mbs = parent.getInterceptor(key); - - // mbs can be null if the interceptor was removed - // concurrently... - // See handlerMap and getKeys() in DispatchInterceptor - // - if (mbs == null) continue; - - // If the domain is selected, we can replace the pattern - // by the actual domain. This is safer if we want to avoid - // a domain (which could be backed up by an MBeanServer) to - // return names from outside the domain. - // So instead of asking the domain handler for "foo" to - // return all names which match "?o*:type=Bla,*" we're - // going to ask it to return all names which match - // "foo:type=Bla,*" - // - final ObjectName subPattern = pattern.withDomain(key); - res.addAll(invoker.query(mbs, subPattern, query)); - } catch (Exception x) { - LOG.finest("Ignoring exception " + - "when attempting to query namespace "+key+": "+x); - continue; - } - } - return res; - } - } - - private final DefaultMBeanServerInterceptor nextInterceptor; - private final String mbeanServerName; - private final MBeanServerDelegate delegate; - - /** - * Creates a DomainDispatchInterceptor with the specified - * repository instance. - * - * @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. - * @param instantiator The MBeanInstantiator that will be used to - * instantiate MBeans and take care of class loading issues. - * @param repository The repository to use for this MBeanServer - */ - public DomainDispatchInterceptor(MBeanServer outer, - MBeanServerDelegate delegate, - MBeanInstantiator instantiator, - Repository repository, - NamespaceDispatchInterceptor namespaces) { - nextInterceptor = new DefaultMBeanServerInterceptor(outer, - delegate, instantiator,repository,namespaces); - mbeanServerName = Util.getMBeanServerSecurityName(delegate); - this.delegate = delegate; - } - - final boolean isLocalHandlerNameFor(String domain, - ObjectName handlerName) { - if (domain == null) return true; - return handlerName.getDomain().equals(domain) && - JMXDomain.TYPE_ASSIGNMENT.equals( - handlerName.getKeyPropertyListString()); - } - - @Override - void validateHandlerNameFor(String key, ObjectName name) { - super.validateHandlerNameFor(key,name); - final String[] domains = nextInterceptor.getDomains(); - for (int i=0;i<domains.length;i++) { - if (domains[i].equals(key)) - throw new IllegalArgumentException("domain "+key+ - " is not empty"); - } - } - - @Override - final MBeanServer getInterceptorOrNullFor(ObjectName name) { - - if (name == null) return nextInterceptor; - - final String domain = name.getDomain(); - if (domain.endsWith(NAMESPACE_SEPARATOR)) - return nextInterceptor; // This can be a namespace handler. - if (domain.contains(NAMESPACE_SEPARATOR)) - return null; // shouldn't reach here. - if (isLocalHandlerNameFor(domain,name)) { - // This is the name of a JMXDomain MBean. Return nextInterceptor. - LOG.finer("dispatching to local namespace"); - return nextInterceptor; - } - - final DomainInterceptor ns = getInterceptor(domain); - if (ns == null) { - // no JMXDomain found for that domain - return nextInterceptor. - if (LOG.isLoggable(Level.FINER)) { - LOG.finer("dispatching to local namespace: " + domain); - } - return getNextInterceptor(); - } - - if (LOG.isLoggable(Level.FINER)) { - LOG.finer("dispatching to domain: " + domain); - } - return ns; - } - - // This method returns true if the given pattern must be evaluated against - // several interceptors. This happens when either: - // - // a) the pattern can select several domains (it's null, or it's a - // domain pattern) - // or b) it's not a domain pattern, but it might select the name of a - // JMXDomain MBean in charge of that domain. Since the JMXDomain - // MBean is located in the nextInterceptor, the pattern might need - // to be evaluated on two interceptors. - // - // 1. When this method returns false, the query is evaluated on a single - // interceptor: - // The interceptor for pattern.getDomain(), if there is one, - // or the next interceptor, if there is none. - // - // 2. When this method returns true, we loop over all the domain - // interceptors: - // in the list, and if the domain pattern matches the interceptor domain - // we evaluate the query on that interceptor and aggregate the results. - // Eventually we also evaluate the pattern against the next interceptor. - // - // See getInterceptorForQuery below. - // - private boolean multipleQuery(ObjectName pattern) { - // case a) above - if (pattern == null) return true; - if (pattern.isDomainPattern()) return true; - - // case b) above. - // - // This is a bit of a hack. If there's any chance that a JMXDomain - // MBean name is selected by the given pattern then we must include - // the local namespace in our search. - // - // Returning true will have this effect. see 2. above. - // - if (pattern.apply(ALL_DOMAINS.withDomain(pattern.getDomain()))) - return true; - - return false; - } - - @Override - final QueryInterceptor getInterceptorForQuery(ObjectName pattern) { - - // Check if we need to aggregate. - if (multipleQuery(pattern)) - return new AggregatingQueryInterceptor(this); - - // We don't need to aggregate: do the "simple" thing... - final String domain = pattern.getDomain(); - - // Do we have a virtual domain? - final DomainInterceptor ns = getInterceptor(domain); - if (ns != null) { - if (LOG.isLoggable(Level.FINER)) - LOG.finer("dispatching to domain: " + domain); - return new QueryInterceptor(ns); - } - - // We don't have a virtual domain. Send to local domains. - if (LOG.isLoggable(Level.FINER)) - LOG.finer("dispatching to local namespace: " + domain); - return new QueryInterceptor(nextInterceptor); - } - - @Override - final ObjectName getHandlerNameFor(String key) { - return JMXDomain.getDomainObjectName(key); - } - - @Override - final public String getHandlerKey(ObjectName name) { - return name.getDomain(); - } - - @Override - final DomainInterceptor createInterceptorFor(String key, - ObjectName name, JMXDomain handler, - Queue<Runnable> postRegisterQueue) { - final DomainInterceptor ns = - new DomainInterceptor(mbeanServerName,handler,key); - ns.addPostRegisterTask(postRegisterQueue, delegate); - if (LOG.isLoggable(Level.FINER)) { - LOG.finer("DomainInterceptor created: "+ns); - } - return ns; - } - - @Override - final void interceptorReleased(DomainInterceptor interceptor, - Queue<Runnable> postDeregisterQueue) { - interceptor.addPostDeregisterTask(postDeregisterQueue, delegate); - } - - @Override - final DefaultMBeanServerInterceptor getNextInterceptor() { - return nextInterceptor; - } - - /** - * Returns the list of domains in which any MBean is currently - * registered. - */ - @Override - public String[] getDomains() { - // A JMXDomain is registered in its own domain. - // Therefore, nextInterceptor.getDomains() contains all domains. - // In addition, nextInterceptor will perform the necessary - // MBeanPermission checks for getDomains(). - // - return nextInterceptor.getDomains(); - } - - /** - * Returns the number of MBeans registered in the MBean server. - */ - @Override - public Integer getMBeanCount() { - int count = getNextInterceptor().getMBeanCount(); - final String[] keys = getKeys(); - for (String key:keys) { - final MBeanServer mbs = getInterceptor(key); - if (mbs == null) continue; - count += mbs.getMBeanCount(); - } - return count; - } -}
--- a/jdk/src/share/classes/com/sun/jmx/interceptor/MBeanServerInterceptorSupport.java Wed Oct 21 16:28:57 2009 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,127 +0,0 @@ -/* - * Copyright 2008 Sun Microsystems, Inc. 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. Sun designates this - * particular file as subject to the "Classpath" exception as provided - * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, - * CA 95054 USA or visit www.sun.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.ObjectName; -import javax.management.OperationsException; -import javax.management.ReflectionException; -import javax.management.loading.ClassLoaderRepository; - -/** - * An abstract class for MBeanServerInterceptorSupport. - * Some methods in MBeanServerInterceptor should never be called. - * This base class provides an implementation of these methods that simply - * throw an {@link UnsupportedOperationException}. - * <p><b> - * This API is a Sun internal API and is subject to changes without notice. - * </b></p> - * @since 1.7 - */ -public abstract class MBeanServerInterceptorSupport - implements MBeanServerInterceptor { - /** - * This method should never be called. - * Throws UnsupportedOperationException. - */ - public Object instantiate(String className) - throws ReflectionException, MBeanException { - throw new UnsupportedOperationException("Not applicable."); - } - - /** - * This method should never be called. - * Throws UnsupportedOperationException. - */ - public Object instantiate(String className, ObjectName loaderName) - throws ReflectionException, MBeanException, - InstanceNotFoundException { - throw new UnsupportedOperationException("Not applicable."); - } - - /** - * This method should never be called. - * Throws UnsupportedOperationException. - */ - public Object instantiate(String className, Object[] params, - String[] signature) throws ReflectionException, MBeanException { - throw new UnsupportedOperationException("Not applicable."); - } - - /** - * This method should never be called. - * Throws UnsupportedOperationException. - */ - public Object instantiate(String className, ObjectName loaderName, - Object[] params, String[] signature) - throws ReflectionException, MBeanException, - InstanceNotFoundException { - throw new UnsupportedOperationException("Not applicable."); - } - - /** - * This method should never be called. - * Throws UnsupportedOperationException. - */ - @Deprecated - public ObjectInputStream deserialize(ObjectName name, byte[] data) - throws InstanceNotFoundException, OperationsException { - throw new UnsupportedOperationException("Not applicable."); - } - - /** - * This method should never be called. - * Throws UnsupportedOperationException. - */ - @Deprecated - public ObjectInputStream deserialize(String className, byte[] data) - throws OperationsException, ReflectionException { - throw new UnsupportedOperationException("Not applicable."); - } - - /** - * This method should never be called. - * Throws UnsupportedOperationException. - */ - @Deprecated - public ObjectInputStream deserialize(String className, - ObjectName loaderName, byte[] data) - throws InstanceNotFoundException, OperationsException, - ReflectionException { - throw new UnsupportedOperationException("Not applicable."); - } - - /** - * This method should never be called. - * Throws UnsupportedOperationException. - */ - public ClassLoaderRepository getClassLoaderRepository() { - throw new UnsupportedOperationException("Not applicable."); - } - -}
--- a/jdk/src/share/classes/com/sun/jmx/interceptor/NamespaceDispatchInterceptor.java Wed Oct 21 16:28:57 2009 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,297 +0,0 @@ -/* - * Copyright 2008 Sun Microsystems, Inc. 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. Sun designates this - * particular file as subject to the "Classpath" exception as provided - * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, - * CA 95054 USA or visit www.sun.com if you need additional information or - * have any questions. - */ - -package com.sun.jmx.interceptor; - -import com.sun.jmx.defaults.JmxProperties; -import com.sun.jmx.mbeanserver.MBeanInstantiator; -import com.sun.jmx.mbeanserver.Repository; -import com.sun.jmx.mbeanserver.Util; -import com.sun.jmx.namespace.NamespaceInterceptor; - -import java.util.Queue; -import java.util.logging.Level; -import java.util.logging.Logger; - -import javax.management.MBeanServer; -import javax.management.MBeanServerDelegate; -import javax.management.ObjectName; -import javax.management.RuntimeOperationsException; -import javax.management.namespace.JMXDomain; -import javax.management.namespace.JMXNamespace; -import static javax.management.namespace.JMXNamespaces.NAMESPACE_SEPARATOR; - -/** - * A dispatcher that dispatches to NamespaceInterceptors. - * <p><b> - * This API is a Sun internal API and is subject to changes without notice. - * </b></p> - * @since 1.7 - */ -public class NamespaceDispatchInterceptor - extends DispatchInterceptor<NamespaceInterceptor, JMXNamespace> { - - /** - * A logger for this class. - **/ - private static final Logger LOG = JmxProperties.NAMESPACE_LOGGER; - - private static final int NAMESPACE_SEPARATOR_LENGTH = - NAMESPACE_SEPARATOR.length(); - private static final ObjectName X3 = ObjectName.valueOf("x:x=x"); - - private final DomainDispatchInterceptor nextInterceptor; - private final String serverName; - - /** - * Creates a NamespaceDispatchInterceptor with the specified - * repository instance. - * <p>Do not forget to call <code>initialize(outer,delegate)</code> - * before using this object. - * - * @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. - * @param instantiator The MBeanInstantiator that will be used to - * instantiate MBeans and take care of class loading issues. - * @param repository The repository to use for this MBeanServer - */ - public NamespaceDispatchInterceptor(MBeanServer outer, - MBeanServerDelegate delegate, - MBeanInstantiator instantiator, - Repository repository) { - nextInterceptor = new DomainDispatchInterceptor(outer,delegate, - instantiator,repository,this); - serverName = Util.getMBeanServerSecurityName(delegate); - } - - /** - * Get first name space in ObjectName path. Ignore leading namespace - * separators. Includes the trailing //. - * - * Examples: - * <pre> - * For ObjectName: Returns: - * foo//bar//baz:x=x -> "foo//" - * foo//:type=JMXNamespace -> "foo//" - * foo//:x=x -> "foo//" - * foo////:x=x -> "foo//" - * //foo//bar//baz:x=x -> "//" - * ////foo//bar//baz:x=x -> "//" - * //:x=x -> "//" - * foo:x=x -> "" - * (null) -> "" - * :x=x -> "" - * - * </pre> - **/ - static String getFirstNamespaceWithSlash(ObjectName name) { - if (name == null) return ""; - final String domain = name.getDomain(); - if (domain.equals("")) return ""; - - // go to next separator - final int end = domain.indexOf(NAMESPACE_SEPARATOR); - if (end == -1) return ""; // no namespace - - // This is the first element in the namespace path. - final String namespace = - domain.substring(0,end+NAMESPACE_SEPARATOR_LENGTH); - - return namespace; - } - - /** - * Called by the DefaultMBeanServerInterceptor, just before adding an - * MBean to the repository. - * - * @param resource the MBean to be registered. - * @param logicalName the name of the MBean to be registered. - */ - final void checkLocallyRegistrable(Object resource, - ObjectName logicalName) { - if (!(resource instanceof JMXNamespace) && - logicalName.getDomain().contains(NAMESPACE_SEPARATOR)) - throw new IllegalArgumentException(String.valueOf(logicalName)+ - ": Invalid ObjectName for an instance of " + - resource.getClass().getName()); - } - - // Removes the trailing //. namespaceWithSlash should be either - // "" or a namespace path ending with //. - // - private final String getKeyFor(String namespaceWithSlash) { - final int end = namespaceWithSlash.length() - - NAMESPACE_SEPARATOR_LENGTH; - if (end <= 0) return ""; - final String key = namespaceWithSlash.substring(0,end); - return key; - } - - @Override - final MBeanServer getInterceptorOrNullFor(ObjectName name) { - final String namespace = getFirstNamespaceWithSlash(name); - - // Leading separators should trigger instance not found exception. - // returning null here has this effect. - // - if (namespace.equals(NAMESPACE_SEPARATOR)) { - LOG.finer("ObjectName starts with: "+namespace); - return null; - } - - // namespace="" means that there was no namespace path in the - // ObjectName. => delegate to the next interceptor (local MBS) - // name.getDomain()=namespace means that we have an ObjectName of - // the form blah//:x=x. This is either a JMXNamespace or a non - // existent MBean. => delegate to the next interceptor (local MBS) - if (namespace.equals("") || name.getDomain().equals(namespace)) { - LOG.finer("dispatching to local name space"); - return nextInterceptor; - } - - // There was a namespace path in the ObjectName. Returns the - // interceptor that handles it, or null if there is no such - // interceptor. - final String key = getKeyFor(namespace); - final NamespaceInterceptor ns = getInterceptor(key); - if (LOG.isLoggable(Level.FINER)) { - if (ns != null) { - LOG.finer("dispatching to name space: " + key); - } else { - LOG.finer("no handler for: " + key); - } - } - return ns; - } - - @Override - final QueryInterceptor getInterceptorForQuery(ObjectName pattern) { - final String namespace = getFirstNamespaceWithSlash(pattern); - - // Leading separators should trigger instance not found exception. - // returning null here has this effect. - // - if (namespace.equals(NAMESPACE_SEPARATOR)) { - LOG.finer("ObjectName starts with: "+namespace); - return null; - } - - // namespace="" means that there was no namespace path in the - // ObjectName. => delegate to the next interceptor (local MBS) - // name.getDomain()=namespace means that we have an ObjectName of - // the form blah//:x=x. This is either a JMXNamespace or a non - // existent MBean. => delegate to the next interceptor (local MBS) - if (namespace.equals("") || pattern.getDomain().equals(namespace)) { - LOG.finer("dispatching to local name space"); - return new QueryInterceptor(nextInterceptor); - } - - // This is a 'hack' to check whether the first namespace is a pattern. - // We wan to throw RTOE wrapping IAE in that case - if (X3.withDomain(namespace).isDomainPattern()) { - throw new RuntimeOperationsException( - new IllegalArgumentException("Pattern not allowed in namespace path")); - } - - // There was a namespace path in the ObjectName. Returns the - // interceptor that handles it, or null if there is no such - // interceptor. - // - final String key = getKeyFor(namespace); - final NamespaceInterceptor ns = getInterceptor(key); - if (LOG.isLoggable(Level.FINER)) { - if (ns != null) { - LOG.finer("dispatching to name space: " + key); - } else { - LOG.finer("no handler for: " + key); - } - } - if (ns == null) return null; - return new QueryInterceptor(ns); - } - - @Override - final ObjectName getHandlerNameFor(String key) { - return ObjectName.valueOf(key+NAMESPACE_SEPARATOR, - "type", JMXNamespace.TYPE); - } - - @Override - final public String getHandlerKey(ObjectName name) { - final String namespace = getFirstNamespaceWithSlash(name); - // namespace is either "" or a namespace ending with // - return getKeyFor(namespace); - } - - @Override - final NamespaceInterceptor createInterceptorFor(String key, - ObjectName name, JMXNamespace handler, - Queue<Runnable> postRegisterQueue) { - final NamespaceInterceptor ns = - new NamespaceInterceptor(serverName,handler,key); - if (LOG.isLoggable(Level.FINER)) { - LOG.finer("NamespaceInterceptor created: "+ns); - } - return ns; - } - - @Override - final DomainDispatchInterceptor getNextInterceptor() { - return nextInterceptor; - } - - /** - * Returns the list of domains in which any MBean is currently - * registered. - */ - @Override - public String[] getDomains() { - return nextInterceptor.getDomains(); - } - - @Override - public void addInterceptorFor(ObjectName name, JMXNamespace handler, - Queue<Runnable> postRegisterQueue) { - if (handler instanceof JMXDomain) - nextInterceptor.addInterceptorFor(name, - (JMXDomain)handler,postRegisterQueue); - else super.addInterceptorFor(name,handler,postRegisterQueue); - } - - @Override - public void removeInterceptorFor(ObjectName name, JMXNamespace handler, - Queue<Runnable> postDeregisterQueue) { - if (handler instanceof JMXDomain) - nextInterceptor.removeInterceptorFor(name,(JMXDomain)handler, - postDeregisterQueue); - else super.removeInterceptorFor(name,handler,postDeregisterQueue); - } - - -}
--- a/jdk/src/share/classes/com/sun/jmx/interceptor/SingleMBeanForwarder.java Wed Oct 21 16:28:57 2009 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,442 +0,0 @@ -/* - * Copyright 2008 Sun Microsystems, Inc. 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. Sun designates this - * particular file as subject to the "Classpath" exception as provided - * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, - * CA 95054 USA or visit www.sun.com if you need additional information or - * have any questions. - */ - -package com.sun.jmx.interceptor; - -import com.sun.jmx.mbeanserver.Util; -import java.util.Arrays; -import java.util.Collections; -import java.util.Set; -import java.util.TreeSet; -import javax.management.Attribute; -import javax.management.AttributeList; -import javax.management.AttributeNotFoundException; -import javax.management.DynamicMBean; -import javax.management.InstanceAlreadyExistsException; -import javax.management.InstanceNotFoundException; -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.NotificationEmitter; -import javax.management.NotificationFilter; -import javax.management.NotificationListener; -import javax.management.ObjectInstance; -import javax.management.ObjectName; -import javax.management.QueryExp; -import javax.management.ReflectionException; -import javax.management.namespace.JMXNamespaces; -import javax.management.namespace.MBeanServerSupport; -import javax.management.remote.IdentityMBeanServerForwarder; - -/** - * <p>An {@link MBeanServerForwarder} that simulates the existence of a - * given MBean. Requests for that MBean, call it X, are intercepted by the - * forwarder, and requests for any other MBean are forwarded to the next - * forwarder in the chain. Requests such as queryNames which can span both the - * X and other MBeans are handled by merging the results for X with the results - * from the next forwarder, unless the "visible" parameter is false, in which - * case X is invisible to such requests.</p> - */ -public class SingleMBeanForwarder extends IdentityMBeanServerForwarder { - - private final ObjectName mbeanName; - private final boolean visible; - private DynamicMBean mbean; - - private MBeanServer mbeanMBS = new MBeanServerSupport() { - - @Override - public DynamicMBean getDynamicMBeanFor(ObjectName name) - throws InstanceNotFoundException { - if (mbeanName.equals(name)) { - return mbean; - } else { - throw new InstanceNotFoundException(name.toString()); - } - } - - @Override - protected Set<ObjectName> getNames() { - return Collections.singleton(mbeanName); - } - - @Override - public NotificationEmitter getNotificationEmitterFor( - ObjectName name) { - if (mbean instanceof NotificationEmitter) - return (NotificationEmitter) mbean; - return null; - } - - // This will only be called if mbeanName has an empty domain. - // In that case a getAttribute (e.g.) of that name will have the - // domain replaced by MBeanServerSupport with the default domain, - // so we must be sure that the default domain is empty too. - @Override - public String getDefaultDomain() { - return mbeanName.getDomain(); - } - }; - - public SingleMBeanForwarder( - ObjectName mbeanName, DynamicMBean mbean, boolean visible) { - this.mbeanName = mbeanName; - this.visible = visible; - setSingleMBean(mbean); - } - - protected void setSingleMBean(DynamicMBean mbean) { - this.mbean = mbean; - } - - @Override - public void addNotificationListener(ObjectName name, ObjectName listener, - NotificationFilter filter, - Object handback) - throws InstanceNotFoundException { - if (mbeanName.equals(name)) - mbeanMBS.addNotificationListener(name, listener, filter, handback); - else - super.addNotificationListener(name, listener, filter, handback); - } - - @Override - public void addNotificationListener(ObjectName name, - NotificationListener listener, - NotificationFilter filter, - Object handback) - throws InstanceNotFoundException { - if (mbeanName.equals(name)) - mbeanMBS.addNotificationListener(name, listener, filter, handback); - else - super.addNotificationListener(name, listener, filter, handback); - } - - @Override - public ObjectInstance createMBean(String className, ObjectName name, - ObjectName loaderName, Object[] params, - String[] signature) - throws ReflectionException, - InstanceAlreadyExistsException, - MBeanRegistrationException, - MBeanException, - NotCompliantMBeanException, - InstanceNotFoundException { - if (mbeanName.equals(name)) - throw new InstanceAlreadyExistsException(mbeanName.toString()); - else - return super.createMBean(className, name, loaderName, params, signature); - } - - @Override - public ObjectInstance createMBean(String className, ObjectName name, - Object[] params, String[] signature) - throws ReflectionException, InstanceAlreadyExistsException, - MBeanRegistrationException, MBeanException, - NotCompliantMBeanException { - if (mbeanName.equals(name)) - throw new InstanceAlreadyExistsException(mbeanName.toString()); - return super.createMBean(className, name, params, signature); - } - - @Override - public ObjectInstance createMBean(String className, ObjectName name, - ObjectName loaderName) - throws ReflectionException, - InstanceAlreadyExistsException, - MBeanRegistrationException, - MBeanException, - NotCompliantMBeanException, - InstanceNotFoundException { - if (mbeanName.equals(name)) - throw new InstanceAlreadyExistsException(mbeanName.toString()); - return super.createMBean(className, name, loaderName); - } - - @Override - public ObjectInstance createMBean(String className, ObjectName name) - throws ReflectionException, - InstanceAlreadyExistsException, - MBeanRegistrationException, - MBeanException, - NotCompliantMBeanException { - if (mbeanName.equals(name)) - throw new InstanceAlreadyExistsException(mbeanName.toString()); - return super.createMBean(className, name); - } - - @Override - public Object getAttribute(ObjectName name, String attribute) - throws MBeanException, - AttributeNotFoundException, - InstanceNotFoundException, - ReflectionException { - if (mbeanName.equals(name)) - return mbeanMBS.getAttribute(name, attribute); - else - return super.getAttribute(name, attribute); - } - - @Override - public AttributeList getAttributes(ObjectName name, String[] attributes) - throws InstanceNotFoundException, ReflectionException { - if (mbeanName.equals(name)) - return mbeanMBS.getAttributes(name, attributes); - else - return super.getAttributes(name, attributes); - } - - @Override - public ClassLoader getClassLoader(ObjectName loaderName) - throws InstanceNotFoundException { - if (mbeanName.equals(loaderName)) - return mbeanMBS.getClassLoader(loaderName); - else - return super.getClassLoader(loaderName); - } - - @Override - public ClassLoader getClassLoaderFor(ObjectName name) - throws InstanceNotFoundException { - if (mbeanName.equals(name)) - return mbeanMBS.getClassLoaderFor(name); - else - return super.getClassLoaderFor(name); - } - - @Override - public String[] getDomains() { - String[] domains = super.getDomains(); - if (!visible) - return domains; - TreeSet<String> domainSet = new TreeSet<String>(Arrays.asList(domains)); - domainSet.add(mbeanName.getDomain()); - return domainSet.toArray(new String[domainSet.size()]); - } - - @Override - public Integer getMBeanCount() { - Integer count = super.getMBeanCount(); - if (visible && !super.isRegistered(mbeanName)) - count++; - return count; - } - - @Override - public MBeanInfo getMBeanInfo(ObjectName name) - throws InstanceNotFoundException, - IntrospectionException, - ReflectionException { - if (mbeanName.equals(name)) - return mbeanMBS.getMBeanInfo(name); - else - return super.getMBeanInfo(name); - } - - @Override - public ObjectInstance getObjectInstance(ObjectName name) - throws InstanceNotFoundException { - if (mbeanName.equals(name)) - return mbeanMBS.getObjectInstance(name); - else - return super.getObjectInstance(name); - } - - @Override - public Object invoke(ObjectName name, String operationName, Object[] params, - String[] signature) - throws InstanceNotFoundException, - MBeanException, - ReflectionException { - if (mbeanName.equals(name)) - return mbeanMBS.invoke(name, operationName, params, signature); - else - return super.invoke(name, operationName, params, signature); - } - - @Override - public boolean isInstanceOf(ObjectName name, String className) - throws InstanceNotFoundException { - if (mbeanName.equals(name)) - return mbeanMBS.isInstanceOf(name, className); - else - return super.isInstanceOf(name, className); - } - - @Override - public boolean isRegistered(ObjectName name) { - if (mbeanName.equals(name)) - return true; - else - return super.isRegistered(name); - } - - /** - * This is a ugly hack. Although jmx.context//*:* matches jmx.context//:* - * queryNames(jmx.context//*:*,null) must not return jmx.context//:* - * @param pattern the pattern to match against. must not be null. - * @return true if mbeanName can be included, false if it must not. - */ - private boolean applies(ObjectName pattern) { - // we know pattern is not null. - if (!visible || !pattern.apply(mbeanName)) - return false; - - final String dompat = pattern.getDomain(); - if (!dompat.contains(JMXNamespaces.NAMESPACE_SEPARATOR)) - return true; // We already checked that patterns apply. - - if (mbeanName.getDomain().endsWith(JMXNamespaces.NAMESPACE_SEPARATOR)) { - // only matches if pattern ends with // - return dompat.endsWith(JMXNamespaces.NAMESPACE_SEPARATOR); - } - - // should not come here, unless mbeanName contains a // in the - // middle of its domain, which would be weird. - // let query on mbeanMBS proceed and take care of that. - // - return true; - } - - @Override - public Set<ObjectInstance> queryMBeans(ObjectName name, QueryExp query) { - Set<ObjectInstance> names = super.queryMBeans(name, query); - if (visible) { - if (name == null || applies(name) ) { - // Don't assume mbs.queryNames returns a writable set. - names = Util.cloneSet(names); - names.addAll(mbeanMBS.queryMBeans(name, query)); - } - } - return names; - } - - @Override - public Set<ObjectName> queryNames(ObjectName name, QueryExp query) { - Set<ObjectName> names = super.queryNames(name, query); - if (visible) { - if (name == null || applies(name)) { - // Don't assume mbs.queryNames returns a writable set. - names = Util.cloneSet(names); - names.addAll(mbeanMBS.queryNames(name, query)); - } - } - return names; - } - - - @Override - public ObjectInstance registerMBean(Object object, ObjectName name) - throws InstanceAlreadyExistsException, - MBeanRegistrationException, - NotCompliantMBeanException { - if (mbeanName.equals(name)) - throw new InstanceAlreadyExistsException(mbeanName.toString()); - else - return super.registerMBean(object, name); - } - - @Override - public void removeNotificationListener(ObjectName name, - NotificationListener listener, - NotificationFilter filter, - Object handback) - throws InstanceNotFoundException, - ListenerNotFoundException { - if (mbeanName.equals(name)) - mbeanMBS.removeNotificationListener(name, listener, filter, handback); - else - super.removeNotificationListener(name, listener, filter, handback); - } - - @Override - public void removeNotificationListener(ObjectName name, - NotificationListener listener) - throws InstanceNotFoundException, ListenerNotFoundException { - if (mbeanName.equals(name)) - mbeanMBS.removeNotificationListener(name, listener); - else - super.removeNotificationListener(name, listener); - } - - @Override - public void removeNotificationListener(ObjectName name, ObjectName listener, - NotificationFilter filter, - Object handback) - throws InstanceNotFoundException, - ListenerNotFoundException { - if (mbeanName.equals(name)) - mbeanMBS.removeNotificationListener(name, listener, filter, handback); - else - super.removeNotificationListener(name, listener, filter, handback); - } - - @Override - public void removeNotificationListener(ObjectName name, ObjectName listener) - throws InstanceNotFoundException, ListenerNotFoundException { - if (mbeanName.equals(name)) - mbeanMBS.removeNotificationListener(name, listener); - else - super.removeNotificationListener(name, listener); - } - - @Override - public void setAttribute(ObjectName name, Attribute attribute) - throws InstanceNotFoundException, - AttributeNotFoundException, - InvalidAttributeValueException, - MBeanException, - ReflectionException { - if (mbeanName.equals(name)) - mbeanMBS.setAttribute(name, attribute); - else - super.setAttribute(name, attribute); - } - - @Override - public AttributeList setAttributes(ObjectName name, - AttributeList attributes) - throws InstanceNotFoundException, ReflectionException { - if (mbeanName.equals(name)) - return mbeanMBS.setAttributes(name, attributes); - else - return super.setAttributes(name, attributes); - } - - @Override - public void unregisterMBean(ObjectName name) - throws InstanceNotFoundException, - MBeanRegistrationException { - if (mbeanName.equals(name)) - mbeanMBS.unregisterMBean(name); - else - super.unregisterMBean(name); - } -}
--- a/jdk/src/share/classes/com/sun/jmx/mbeanserver/ConvertingMethod.java Wed Oct 21 16:28:57 2009 +0200 +++ b/jdk/src/share/classes/com/sun/jmx/mbeanserver/ConvertingMethod.java Wed Oct 21 17:33:18 2009 +0200 @@ -31,15 +31,13 @@ import javax.management.Descriptor; import javax.management.MBeanException; -import javax.management.openmbean.MXBeanMapping; -import javax.management.openmbean.MXBeanMappingFactory; import javax.management.openmbean.OpenDataException; import javax.management.openmbean.OpenType; final class ConvertingMethod { - static ConvertingMethod from(Method m, MXBeanMappingFactory mappingFactory) { + static ConvertingMethod from(Method m) { try { - return new ConvertingMethod(m, mappingFactory); + return new ConvertingMethod(m); } catch (OpenDataException ode) { final String msg = "Method " + m.getDeclaringClass().getName() + "." + m.getName() + " has parameter or return type that " + @@ -53,7 +51,7 @@ } Descriptor getDescriptor() { - return Introspector.descriptorForElement(method, false); + return Introspector.descriptorForElement(method); } Type getGenericReturnType() { @@ -206,9 +204,9 @@ return method.getDeclaringClass() + "." + method.getName(); } - private ConvertingMethod(Method m, MXBeanMappingFactory mappingFactory) - throws OpenDataException { + private ConvertingMethod(Method m) throws OpenDataException { this.method = m; + MXBeanMappingFactory mappingFactory = MXBeanMappingFactory.DEFAULT; returnMapping = mappingFactory.mappingForType(m.getGenericReturnType(), mappingFactory); Type[] params = m.getGenericParameterTypes();
--- a/jdk/src/share/classes/com/sun/jmx/mbeanserver/DefaultMXBeanMappingFactory.java Wed Oct 21 16:28:57 2009 +0200 +++ b/jdk/src/share/classes/com/sun/jmx/mbeanserver/DefaultMXBeanMappingFactory.java Wed Oct 21 17:33:18 2009 +0200 @@ -28,8 +28,6 @@ import static com.sun.jmx.mbeanserver.Util.*; import static com.sun.jmx.mbeanserver.MXBeanIntrospector.typeName; -import javax.management.openmbean.MXBeanMappingClass; - import static javax.management.openmbean.SimpleType.*; import com.sun.jmx.remote.util.EnvHelp; @@ -69,8 +67,6 @@ import javax.management.openmbean.CompositeDataSupport; import javax.management.openmbean.CompositeDataView; import javax.management.openmbean.CompositeType; -import javax.management.openmbean.MXBeanMapping; -import javax.management.openmbean.MXBeanMappingFactory; import javax.management.openmbean.OpenDataException; import javax.management.openmbean.OpenType; import javax.management.openmbean.SimpleType; @@ -165,34 +161,29 @@ private static final class Mappings extends WeakHashMap<Type, WeakReference<MXBeanMapping>> {} - private static final Map<MXBeanMappingFactory, Mappings> factoryMappings = - new WeakHashMap<MXBeanMappingFactory, Mappings>(); - - private static final Map<Type, MXBeanMapping> permanentMappings = newMap(); + private static final Mappings mappings = new Mappings(); - private static synchronized MXBeanMapping getMapping( - Type type, MXBeanMappingFactory factory) { - Mappings mappings = factoryMappings.get(factory); - if (mappings == null) { - mappings = new Mappings(); - factoryMappings.put(factory, mappings); - } + /** Following List simply serves to keep a reference to predefined + MXBeanMappings so they don't get garbage collected. */ + private static final List<MXBeanMapping> permanentMappings = newList(); + + private static synchronized MXBeanMapping getMapping(Type type) { WeakReference<MXBeanMapping> wr = mappings.get(type); return (wr == null) ? null : wr.get(); } - private static synchronized void putMapping( - Type type, MXBeanMapping mapping, MXBeanMappingFactory factory) { - Mappings mappings = factoryMappings.get(factory); - if (mappings == null) { - mappings = new Mappings(); - factoryMappings.put(factory, mappings); - } + private static synchronized void putMapping(Type type, MXBeanMapping mapping) { WeakReference<MXBeanMapping> wr = new WeakReference<MXBeanMapping>(mapping); mappings.put(type, wr); } + private static synchronized void putPermanentMapping( + Type type, MXBeanMapping mapping) { + putMapping(type, mapping); + permanentMappings.add(mapping); + } + static { /* Set up the mappings for Java types that map to SimpleType. */ @@ -213,7 +204,7 @@ throw new Error(e); } final MXBeanMapping mapping = new IdentityMapping(c, t); - permanentMappings.put(c, mapping); + putPermanentMapping(c, mapping); if (c.getName().startsWith("java.lang.")) { try { @@ -221,7 +212,7 @@ final Class<?> primitiveType = (Class<?>) typeField.get(null); final MXBeanMapping primitiveMapping = new IdentityMapping(primitiveType, t); - permanentMappings.put(primitiveType, primitiveMapping); + putPermanentMapping(primitiveType, primitiveMapping); if (primitiveType != void.class) { final Class<?> primitiveArrayType = Array.newInstance(primitiveType, 0).getClass(); @@ -230,8 +221,8 @@ final MXBeanMapping primitiveArrayMapping = new IdentityMapping(primitiveArrayType, primitiveArrayOpenType); - permanentMappings.put(primitiveArrayType, - primitiveArrayMapping); + putPermanentMapping(primitiveArrayType, + primitiveArrayMapping); } } catch (NoSuchFieldException e) { // OK: must not be a primitive wrapper @@ -255,7 +246,7 @@ MXBeanMapping mapping; - mapping = getMapping(objType, null); + mapping = getMapping(objType); if (mapping != null) return mapping; @@ -268,7 +259,7 @@ inProgress.remove(objType); } - putMapping(objType, mapping, factory); + putMapping(objType, mapping); return mapping; } @@ -278,14 +269,6 @@ /* It's not yet worth formalizing these tests by having for example an array of factory classes, each of which says whether it recognizes the Type (Chain of Responsibility pattern). */ - MXBeanMapping mapping = permanentMappings.get(objType); - if (mapping != null) - return mapping; - Class<?> erasure = erasure(objType); - MXBeanMappingClass mappingClass = - erasure.getAnnotation(MXBeanMappingClass.class); - if (mappingClass != null) - return makeAnnotationMapping(mappingClass, objType, factory); if (objType instanceof GenericArrayType) { Type componentType = ((GenericArrayType) objType).getGenericComponentType(); @@ -313,51 +296,6 @@ throw new OpenDataException("Cannot map type: " + objType); } - private static MXBeanMapping - makeAnnotationMapping(MXBeanMappingClass mappingClass, - Type objType, - MXBeanMappingFactory factory) - throws OpenDataException { - Class<? extends MXBeanMapping> c = mappingClass.value(); - Constructor<? extends MXBeanMapping> cons; - try { - cons = c.getConstructor(Type.class); - } catch (NoSuchMethodException e) { - final String msg = - "Annotation @" + MXBeanMappingClass.class.getName() + - " must name a class with a public constructor that has a " + - "single " + Type.class.getName() + " argument"; - OpenDataException ode = new OpenDataException(msg); - ode.initCause(e); - throw ode; - } - try { - return cons.newInstance(objType); - } catch (Exception e) { - final String msg = - "Could not construct a " + c.getName() + " for @" + - MXBeanMappingClass.class.getName(); - OpenDataException ode = new OpenDataException(msg); - ode.initCause(e); - throw ode; - } - } - - private static Class<?> erasure(Type t) { - if (t instanceof Class<?>) - return (Class<?>) t; - if (t instanceof ParameterizedType) - return erasure(((ParameterizedType) t).getRawType()); - /* Other cases: GenericArrayType, TypeVariable, WildcardType. - * Returning the erasure of GenericArrayType is not necessary because - * anyway we will be recursing on the element type, and we'll erase - * then. Returning the erasure of the other two would mean returning - * the type bound (e.g. Foo in <T extends Foo> or <? extends Foo>) - * and since we don't treat this as Foo elsewhere we shouldn't here. - */ - return Object.class; - } - private static <T extends Enum<T>> MXBeanMapping makeEnumMapping(Class<?> enumClass, Class<T> fake) { return new EnumMapping<T>(Util.<Class<T>>cast(enumClass));
--- a/jdk/src/share/classes/com/sun/jmx/mbeanserver/DynamicMBean2.java Wed Oct 21 16:28:57 2009 +0200 +++ b/jdk/src/share/classes/com/sun/jmx/mbeanserver/DynamicMBean2.java Wed Oct 21 17:33:18 2009 +0200 @@ -1,5 +1,5 @@ /* - * Copyright 2005-2008 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2005 Sun Microsystems, Inc. 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 @@ -25,7 +25,7 @@ package com.sun.jmx.mbeanserver; -import javax.management.DynamicWrapperMBean; +import javax.management.DynamicMBean; import javax.management.MBeanServer; import javax.management.ObjectName; @@ -35,7 +35,17 @@ * * @since 1.6 */ -public interface DynamicMBean2 extends DynamicWrapperMBean { +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().
--- a/jdk/src/share/classes/com/sun/jmx/mbeanserver/Introspector.java Wed Oct 21 16:28:57 2009 +0200 +++ b/jdk/src/share/classes/com/sun/jmx/mbeanserver/Introspector.java Wed Oct 21 17:33:18 2009 +0200 @@ -25,14 +25,9 @@ package com.sun.jmx.mbeanserver; -import com.sun.jmx.remote.util.EnvHelp; -import java.beans.BeanInfo; -import java.beans.PropertyDescriptor; import java.lang.annotation.Annotation; import java.lang.reflect.AnnotatedElement; -import java.lang.reflect.Array; import java.lang.reflect.Constructor; -import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.lang.reflect.Proxy; @@ -40,39 +35,21 @@ import java.util.Arrays; import java.util.HashMap; import java.util.Map; -import java.util.logging.Level; -import javax.management.AttributeNotFoundException; -import javax.management.Description; import javax.management.Descriptor; -import javax.management.DescriptorFields; import javax.management.DescriptorKey; import javax.management.DynamicMBean; import javax.management.ImmutableDescriptor; -import javax.management.MBean; import javax.management.MBeanInfo; -import javax.management.MXBean; import javax.management.NotCompliantMBeanException; -import javax.management.openmbean.CompositeData; -import javax.management.openmbean.MXBeanMappingFactory; -import static com.sun.jmx.defaults.JmxProperties.MBEANSERVER_LOGGER; -import com.sun.jmx.mbeanserver.Util; import com.sun.jmx.remote.util.EnvHelp; import java.beans.BeanInfo; import java.beans.PropertyDescriptor; import java.lang.reflect.Array; import java.lang.reflect.InvocationTargetException; -import java.util.LinkedHashSet; -import java.util.Set; -import java.util.regex.Matcher; -import java.util.regex.Pattern; import javax.management.AttributeNotFoundException; -import javax.management.JMX; -import javax.management.ObjectName; -import javax.management.ObjectNameTemplate; import javax.management.openmbean.CompositeData; -import javax.management.openmbean.MXBeanMappingFactory; /** * This class contains the methods for performing all the tests needed to verify @@ -82,13 +59,7 @@ */ public class Introspector { - /** - * Pattern used to extract Attribute Names from ObjectNameTemplate Annotation - * For example, in the following example, the Name attribute value is - * retrieved : ":type=MyType, name={Name}" - */ - private static Pattern OBJECT_NAME_PATTERN_TEMPLATE = - Pattern.compile("(\\{[^\\}]+\\})|(=\"\\{[^\\}]+\\}\")"); + /* * ------------------------------------------ * PRIVATE CONSTRUCTORS @@ -164,10 +135,6 @@ public static void checkCompliance(Class<?> mbeanClass) throws NotCompliantMBeanException { - - // Check that @Resource is used correctly (if it used). - MBeanInjector.validate(mbeanClass); - // Is DynamicMBean? // if (DynamicMBean.class.isAssignableFrom(mbeanClass)) @@ -190,36 +157,16 @@ } catch (NotCompliantMBeanException e) { mxbeanException = e; } - // Is @MBean or @MXBean class? - // In fact we find @MBean or @MXBean as a hacky variant of - // getStandardMBeanInterface or getMXBeanInterface. If we get here - // then nothing worked. final String msg = "MBean class " + mbeanClass.getName() + " does not implement " + - "DynamicMBean; does not follow the Standard MBean conventions (" + - mbeanException.toString() + "); does not follow the MXBean conventions (" + - mxbeanException.toString() + "); and does not have or inherit the @" + - MBean.class.getSimpleName() + " or @" + MXBean.class.getSimpleName() + - " annotation"; + "DynamicMBean, and neither follows the Standard MBean conventions (" + + mbeanException.toString() + ") nor the MXBean conventions (" + + mxbeanException.toString() + ")"; throw new NotCompliantMBeanException(msg); } - /** - * <p>Make a DynamicMBean out of the existing MBean object. The object - * may already be a DynamicMBean, or it may be a Standard MBean or - * MXBean, possibly defined using {@code @MBean} or {@code @MXBean}.</p> - * @param mbean the object to convert to a DynamicMBean. - * @param <T> a type parameter defined for implementation convenience - * (which would have to be removed if this method were part of the public - * API). - * @return the converted DynamicMBean. - * @throws NotCompliantMBeanException if {@code mbean} is not a compliant - * MBean object, including the case where it is null. - */ public static <T> DynamicMBean makeDynamicMBean(T mbean) - throws NotCompliantMBeanException { - if (mbean == null) - throw new NotCompliantMBeanException("Null MBean object"); + throws NotCompliantMBeanException { if (mbean instanceof DynamicMBean) return (DynamicMBean) mbean; final Class<?> mbeanClass = mbean.getClass(); @@ -240,18 +187,8 @@ // to be an MBean or an MXBean. We will call checkCompliance() // to generate the appropriate exception. } - if (c != null) { - MXBeanMappingFactory factory; - try { - factory = MXBeanMappingFactory.forInterface(c); - } catch (IllegalArgumentException e) { - NotCompliantMBeanException ncmbe = - new NotCompliantMBeanException(e.getMessage()); - ncmbe.initCause(e); - throw ncmbe; - } - return new MXBeanSupport(mbean, c, factory); - } + if (c != null) + return new MXBeanSupport(mbean, c); checkCompliance(mbeanClass); throw new NotCompliantMBeanException("Not compliant"); // not reached } @@ -280,10 +217,9 @@ return testCompliance(baseClass, null); } - public static void testComplianceMXBeanInterface(Class<?> interfaceClass, - MXBeanMappingFactory factory) + public static void testComplianceMXBeanInterface(Class<?> interfaceClass) throws NotCompliantMBeanException { - MXBeanIntrospector.getInstance(factory).getAnalyzer(interfaceClass); + MXBeanIntrospector.getInstance().getAnalyzer(interfaceClass); } /** @@ -352,8 +288,6 @@ */ public static <T> Class<? super T> getStandardMBeanInterface(Class<T> baseClass) throws NotCompliantMBeanException { - if (baseClass.isAnnotationPresent(MBean.class)) - return baseClass; Class<? super T> current = baseClass; Class<? super T> mbeanInterface = null; while (current != null) { @@ -384,8 +318,6 @@ */ public static <T> Class<? super T> getMXBeanInterface(Class<T> baseClass) throws NotCompliantMBeanException { - if (hasMXBeanAnnotation(baseClass)) - return baseClass; try { return MXBeanSupport.findMXBeanInterface(baseClass); } catch (Exception e) { @@ -393,61 +325,12 @@ } } - public static <T> Class<? super T> getStandardOrMXBeanInterface( - Class<T> baseClass, boolean mxbean) - throws NotCompliantMBeanException { - if (mxbean) - return getMXBeanInterface(baseClass); - else - return getStandardMBeanInterface(baseClass); - } - - public static ObjectName templateToObjectName(Descriptor descriptor, - DynamicMBean mbean) - throws NotCompliantMBeanException { - String template = (String) - descriptor.getFieldValue(JMX.OBJECT_NAME_TEMPLATE); - if(template == null) return null; - try { - Matcher m = OBJECT_NAME_PATTERN_TEMPLATE.matcher(template); - while (m.find()){ - String grp = m.group(); - System.out.println("GROUP " + grp); - String attributeName = null; - boolean quote = false; - if(grp.startsWith("=\"{")) { - attributeName = grp.substring(3, grp.length() - 2); - quote = true; - } else - attributeName = grp.substring(1, grp.length() - 1); - - Object attributeValue = mbean.getAttribute(attributeName); - String validValue = quote ? - "=" + ObjectName.quote(attributeValue.toString()) : - attributeValue.toString(); - template = template.replace(grp, validValue); - } - return new ObjectName(template); - }catch(Exception ex) { - NotCompliantMBeanException ncex = new - NotCompliantMBeanException(ObjectNameTemplate.class. - getSimpleName() + " annotation value [" + template + "] " + - "is invalid. " + ex); - ncex.initCause(ex); - throw ncex; - } - } - /* * ------------------------------------------ * PRIVATE METHODS * ------------------------------------------ */ - static boolean hasMXBeanAnnotation(Class<?> c) { - MXBean m = c.getAnnotation(MXBean.class); - return (m != null && m.value()); - } /** * Try to find the MBean interface corresponding to the class aName @@ -469,77 +352,11 @@ return null; } - public static String descriptionForElement(AnnotatedElement elmt) { - if (elmt == null) - return null; - Description d = elmt.getAnnotation(Description.class); - if (d == null) - return null; - return d.value(); - } - - public static String descriptionForParameter( - Annotation[] parameterAnnotations) { - for (Annotation a : parameterAnnotations) { - if (a instanceof Description) - return ((Description) a).value(); - } - return null; - } - - public static String nameForParameter( - Annotation[] parameterAnnotations) { - for (Annotation a : parameterAnnotations) { - Class<? extends Annotation> ac = a.annotationType(); - // You'd really have to go out of your way to have more than - // one @Name annotation, so we don't check for that. - if (ac.getSimpleName().equals("Name")) { - try { - Method value = ac.getMethod("value"); - if (value.getReturnType() == String.class && - value.getParameterTypes().length == 0) { - return (String) value.invoke(a); - } - } catch (Exception e) { - MBEANSERVER_LOGGER.log( - Level.WARNING, - "Unexpected exception getting @" + ac.getName(), - e); - } - } - } - return null; - } - - public static Descriptor descriptorForElement(final AnnotatedElement elmt, - boolean isSetter) { + public static Descriptor descriptorForElement(final AnnotatedElement elmt) { if (elmt == null) return ImmutableDescriptor.EMPTY_DESCRIPTOR; final Annotation[] annots = elmt.getAnnotations(); - Descriptor descr = descriptorForAnnotations(annots); - String[] exceptions = {}; - if(elmt instanceof Method) - exceptions = getAllExceptions(((Method) elmt).getExceptionTypes()); - else - if(elmt instanceof Constructor<?>) - exceptions = getAllExceptions(((Constructor<?>) elmt). - getExceptionTypes()); - - if(exceptions.length > 0 ) { - String fieldName = isSetter ? JMX.SET_EXCEPTIONS_FIELD : - JMX.EXCEPTIONS_FIELD; - - String[] fieldNames = {fieldName}; - Object[] fieldValues = {exceptions}; - descr = ImmutableDescriptor.union(descr, - new ImmutableDescriptor(fieldNames, fieldValues)); - } - - return descr; - } - - public static Descriptor descriptorForAnnotation(Annotation annot) { - return descriptorForAnnotations(new Annotation[] {annot}); + return descriptorForAnnotations(annots); } public static Descriptor descriptorForAnnotations(Annotation[] annots) { @@ -547,9 +364,36 @@ return ImmutableDescriptor.EMPTY_DESCRIPTOR; Map<String, Object> descriptorMap = new HashMap<String, Object>(); for (Annotation a : annots) { - if (a instanceof DescriptorFields) - addDescriptorFieldsToMap(descriptorMap, (DescriptorFields) a); - addAnnotationFieldsToMap(descriptorMap, a); + Class<? extends Annotation> c = a.annotationType(); + Method[] elements = c.getMethods(); + for (Method element : elements) { + DescriptorKey key = element.getAnnotation(DescriptorKey.class); + if (key != null) { + String name = key.value(); + Object value; + try { + value = element.invoke(a); + } 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()) @@ -559,76 +403,6 @@ } /** - * Array of thrown excepions. - * @param exceptions can be null; - * @return An Array of Exception class names. Size is 0 if method is null. - */ - private static String[] getAllExceptions(Class<?>[] exceptions) { - Set<String> set = new LinkedHashSet<String>(); - for(Class<?>ex : exceptions) - set.add(ex.getName()); - - String[] arr = new String[set.size()]; - return set.toArray(arr); - } - - private static void addDescriptorFieldsToMap( - Map<String, Object> descriptorMap, DescriptorFields df) { - for (String field : df.value()) { - int eq = field.indexOf('='); - if (eq < 0) { - throw new IllegalArgumentException( - "@DescriptorFields string must contain '=': " + - field); - } - String name = field.substring(0, eq); - String value = field.substring(eq + 1); - addToMap(descriptorMap, name, value); - } - } - - private static void addAnnotationFieldsToMap( - Map<String, Object> descriptorMap, Annotation a) { - Class<? extends Annotation> c = a.annotationType(); - Method[] elements = c.getMethods(); - for (Method element : elements) { - DescriptorKey key = element.getAnnotation(DescriptorKey.class); - if (key != null) { - String name = key.value(); - Object value; - try { - value = element.invoke(a); - } 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); - } - if (!key.omitIfDefault() || - !equals(value, element.getDefaultValue())) { - value = annotationToField(value); - addToMap(descriptorMap, name, value); - } - } - } - } - - private static void addToMap( - Map<String, Object> descriptorMap, String name, Object 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); - } - } - - /** * Throws a NotCompliantMBeanException or a SecurityException. * @param notCompliant the class which was under examination * @param cause the raeson why NotCompliantMBeanException should
--- a/jdk/src/share/classes/com/sun/jmx/mbeanserver/JmxMBeanServer.java Wed Oct 21 16:28:57 2009 +0200 +++ b/jdk/src/share/classes/com/sun/jmx/mbeanserver/JmxMBeanServer.java Wed Oct 21 17:33:18 2009 +0200 @@ -25,14 +25,14 @@ package com.sun.jmx.mbeanserver; +import com.sun.jmx.interceptor.DefaultMBeanServerInterceptor; +import com.sun.jmx.interceptor.MBeanServerInterceptor; import static com.sun.jmx.defaults.JmxProperties.MBEANSERVER_LOGGER; -import com.sun.jmx.interceptor.NamespaceDispatchInterceptor; import java.io.ObjectInputStream; import java.security.AccessController; import java.security.Permission; import java.security.PrivilegedExceptionAction; -import java.util.Iterator; import java.util.List; import java.util.Set; import java.util.logging.Level; @@ -108,8 +108,6 @@ /** The MBeanServerDelegate object representing the MBean Server */ private final MBeanServerDelegate mBeanServerDelegateObject; - private final String mbeanServerName; - /** * <b>Package:</b> Creates an MBeanServer with the * specified default domain name, outer interface, and delegate. @@ -241,10 +239,9 @@ final Repository repository = new Repository(domain); this.mbsInterceptor = - new NamespaceDispatchInterceptor(outer, delegate, instantiator, + new DefaultMBeanServerInterceptor(outer, delegate, instantiator, repository); this.interceptorsEnabled = interceptors; - this.mbeanServerName = Util.getMBeanServerSecurityName(delegate); initialize(); } @@ -940,8 +937,7 @@ throws ReflectionException, MBeanException { /* Permission check */ - checkMBeanPermission(mbeanServerName, className, null, null, - "instantiate"); + checkMBeanPermission(className, null, null, "instantiate"); return instantiator.instantiate(className); } @@ -978,8 +974,7 @@ InstanceNotFoundException { /* Permission check */ - checkMBeanPermission(mbeanServerName, className, null, - null, "instantiate"); + checkMBeanPermission(className, null, null, "instantiate"); ClassLoader myLoader = outerShell.getClass().getClassLoader(); return instantiator.instantiate(className, loaderName, myLoader); @@ -1017,8 +1012,7 @@ throws ReflectionException, MBeanException { /* Permission check */ - checkMBeanPermission(mbeanServerName, className, null, null, - "instantiate"); + checkMBeanPermission(className, null, null, "instantiate"); ClassLoader myLoader = outerShell.getClass().getClassLoader(); return instantiator.instantiate(className, params, signature, @@ -1061,8 +1055,7 @@ InstanceNotFoundException { /* Permission check */ - checkMBeanPermission(mbeanServerName, className, null, - null, "instantiate"); + checkMBeanPermission(className, null, null, "instantiate"); ClassLoader myLoader = outerShell.getClass().getClassLoader(); return instantiator.instantiate(className,loaderName,params,signature, @@ -1333,8 +1326,7 @@ **/ public ClassLoaderRepository getClassLoaderRepository() { /* Permission check */ - checkMBeanPermission(mbeanServerName, null, null, - null, "getClassLoaderRepository"); + checkMBeanPermission(null, null, null, "getClassLoaderRepository"); return secureClr; } @@ -1487,16 +1479,14 @@ // SECURITY CHECKS //---------------- - private static void checkMBeanPermission(String serverName, - String classname, + 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(serverName, - classname, + Permission perm = new MBeanPermission(classname, member, objectName, actions);
--- a/jdk/src/share/classes/com/sun/jmx/mbeanserver/MBeanAnalyzer.java Wed Oct 21 16:28:57 2009 +0200 +++ b/jdk/src/share/classes/com/sun/jmx/mbeanserver/MBeanAnalyzer.java Wed Oct 21 17:33:18 2009 +0200 @@ -33,10 +33,6 @@ import java.util.List; import java.util.Map; import java.util.Set; -import javax.management.MBean; -import javax.management.MXBean; -import javax.management.ManagedAttribute; -import javax.management.ManagedOperation; import javax.management.NotCompliantMBeanException; /** @@ -55,15 +51,15 @@ */ class MBeanAnalyzer<M> { - static interface MBeanVisitor<M, X extends Exception> { + static interface MBeanVisitor<M> { public void visitAttribute(String attributeName, M getter, - M setter) throws X; + M setter); public void visitOperation(String operationName, - M operation) throws X; + M operation); } - <X extends Exception> void visit(MBeanVisitor<M, X> visitor) throws X { + void visit(MBeanVisitor<M> visitor) { // visit attributes for (Map.Entry<String, AttrMethods<M>> entry : attrMap.entrySet()) { String name = entry.getKey(); @@ -108,7 +104,10 @@ private MBeanAnalyzer(Class<?> mbeanType, MBeanIntrospector<M> introspector) throws NotCompliantMBeanException { - introspector.checkCompliance(mbeanType); + if (!mbeanType.isInterface()) { + throw new NotCompliantMBeanException("Not an interface: " + + mbeanType.getName()); + } try { initMaps(mbeanType, introspector); @@ -129,26 +128,18 @@ for (Method m : methods) { final String name = m.getName(); final int nParams = m.getParameterTypes().length; - final boolean managedOp = m.isAnnotationPresent(ManagedOperation.class); - final boolean managedAttr = m.isAnnotationPresent(ManagedAttribute.class); - if (managedOp && managedAttr) { - throw new NotCompliantMBeanException("Method " + name + - " has both @ManagedOperation and @ManagedAttribute"); - } final M cm = introspector.mFrom(m); String attrName = ""; - if (!managedOp) { - if (name.startsWith("get")) - attrName = name.substring(3); - else if (name.startsWith("is") - && m.getReturnType() == boolean.class) - attrName = name.substring(2); - } + 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 && !managedOp) { + && m.getReturnType() != void.class) { // It's a getter // Check we don't have both isX and getX AttrMethods<M> am = attrMap.get(attrName); @@ -165,7 +156,7 @@ attrMap.put(attrName, am); } else if (name.startsWith("set") && name.length() > 3 && nParams == 1 && - m.getReturnType() == void.class && !managedOp) { + m.getReturnType() == void.class) { // It's a setter attrName = name.substring(3); AttrMethods<M> am = attrMap.get(attrName); @@ -178,9 +169,6 @@ } am.setter = cm; attrMap.put(attrName, am); - } else if (managedAttr) { - throw new NotCompliantMBeanException("Method " + name + - " has @ManagedAttribute but is not a valid getter or setter"); } else { // It's an operation List<M> cms = opMap.get(name);
--- a/jdk/src/share/classes/com/sun/jmx/mbeanserver/MBeanInjector.java Wed Oct 21 16:28:57 2009 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,295 +0,0 @@ -/* - * Copyright 2007-2008 Sun Microsystems, Inc. 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. Sun designates this - * particular file as subject to the "Classpath" exception as provided - * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, - * CA 95054 USA or visit www.sun.com if you need additional information or - * have any questions. - */ - -package com.sun.jmx.mbeanserver; - -import java.lang.ref.WeakReference; -import java.security.PrivilegedAction; -import java.util.Map; -import java.util.WeakHashMap; -import javax.annotation.Resource; -import javax.management.MBeanServer; -import javax.management.NotCompliantMBeanException; -import javax.management.ObjectName; - -import static com.sun.jmx.mbeanserver.Util.newMap; -import java.lang.reflect.AccessibleObject; -import java.lang.reflect.Field; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.lang.reflect.Modifier; -import java.security.AccessController; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import javax.management.SendNotification; - -public class MBeanInjector { - // There are no instances of this class - private MBeanInjector() { - } - - private static Class<?>[] injectedClasses = { - MBeanServer.class, ObjectName.class, SendNotification.class, - }; - - public static void inject(Object mbean, MBeanServer mbs, ObjectName name) - throws Exception { - ClassInjector injector = injectorForClass(mbean.getClass()); - injector.inject(mbean, MBeanServer.class, mbs); - injector.inject(mbean, ObjectName.class, name); - } - - public static boolean injectsSendNotification(Object mbean) - throws NotCompliantMBeanException { - ClassInjector injector = injectorForClass(mbean.getClass()); - return injector.injects(SendNotification.class); - } - - public static void injectSendNotification(Object mbean, SendNotification sn) - throws Exception { - ClassInjector injector = injectorForClass(mbean.getClass()); - injector.inject(mbean, SendNotification.class, sn); - } - - public static void validate(Class<?> c) throws NotCompliantMBeanException { - injectorForClass(c); - } - - private static class ClassInjector { - private Map<Class<?>, List<Field>> fields; - private Map<Class<?>, List<Method>> methods; - - ClassInjector(Class<?> c) throws NotCompliantMBeanException { - fields = newMap(); - methods = newMap(); - - Class<?> sup = c.getSuperclass(); - ClassInjector supInjector; - if (sup == null) { - supInjector = null; - } else { - supInjector = injectorForClass(sup); - fields.putAll(supInjector.fields); - methods.putAll(supInjector.methods); - } - - addMembers(c); - eliminateOverriddenMethods(); - - // If we haven't added any new fields or methods to what we - // inherited, then we can share the parent's maps. - if (supInjector != null) { - if (fields.equals(supInjector.fields)) - fields = supInjector.fields; - if (methods.equals(supInjector.methods)) - methods = supInjector.methods; - } - } - - boolean injects(Class<?> c) { - return (fields.get(c) != null || methods.get(c) != null); - } - - <T> void inject(Object instance, Class<T> type, T resource) - throws Exception { - List<Field> fs = fields.get(type); - if (fs != null) { - for (Field f : fs) - f.set(instance, resource); - } - List<Method> ms = methods.get(type); - if (ms != null) { - for (Method m : ms) { - try { - m.invoke(instance, resource); - } catch (InvocationTargetException e) { - Throwable cause = e.getCause(); - if (cause instanceof Error) - throw (Error) cause; - else - throw (Exception) cause; - } - } - } - } - - private void eliminateOverriddenMethods() { - /* Covariant overriding is unlikely, but it is possible that the - * parent has a @Resource method that we override with another - * @Resource method. We don't want to invoke both methods, - * because polymorphism means we would actually invoke the same - * method twice. - */ - for (Map.Entry<Class<?>, List<Method>> entry : methods.entrySet()) { - List<Method> list = entry.getValue(); - list = MBeanAnalyzer.eliminateCovariantMethods(list); - entry.setValue(list); - } - } - - /* - * Find Fields or Methods within the given Class that we can inject - * resource references into. Suppose we want to know if a Field can get - * a reference to an ObjectName. We'll accept fields like this: - * - * @Resource - * private transient ObjectName name; - * - * or like this: - * - * @Resource(type = ObjectName.class) - * private transient Object name; - * - * but not like this: - * - * @Resource - * private transient Object name; - * - * (Plain @Resource is equivalent to @Resource(type = Object.class).) - * - * We don't want to inject into everything that might possibly accept - * an ObjectName reference, because examples like the last one above - * could also accept an MBeanServer reference or any other sort of - * reference. - * - * So we accept a Field if it has a @Resource annotation and either - * (a) its type is exactly ObjectName and its @Resource type is - * compatible with ObjectName (e.g. it is Object); or - * (b) its type is compatible with ObjectName and its @Resource type - * is exactly ObjectName. Fields that meet these criteria will not - * meet the same criteria with respect to other types such as MBeanServer. - * - * The same logic applies mutatis mutandis to Methods such as this: - * - * @Resource - * private void setObjectName1(ObjectName name) - * @Resource(type = Object.class) - * private void setObjectName2(Object name) - */ - private void addMembers(final Class<?> c) - throws NotCompliantMBeanException { - AccessibleObject[][] memberArrays = - AccessController.doPrivileged( - new PrivilegedAction<AccessibleObject[][]>() { - public AccessibleObject[][] run() { - return new AccessibleObject[][] { - c.getDeclaredFields(), c.getDeclaredMethods() - }; - } - }); - for (AccessibleObject[] members : memberArrays) { - for (final AccessibleObject member : members) { - Resource res = member.getAnnotation(Resource.class); - if (res == null) - continue; - - final Field field; - final Method method; - final Class<?> memberType; - final int modifiers; - if (member instanceof Field) { - field = (Field) member; - memberType = field.getType(); - modifiers = field.getModifiers(); - method = null; - } else { - field = null; - method = (Method) member; - Class<?>[] paramTypes = method.getParameterTypes(); - if (paramTypes.length != 1) { - throw new NotCompliantMBeanException( - "@Resource method must have exactly 1 " + - "parameter: " + method); - } - if (method.getReturnType() != void.class) { - throw new NotCompliantMBeanException( - "@Resource method must return void: " + - method); - } - memberType = paramTypes[0]; - modifiers = method.getModifiers(); - } - - if (Modifier.isStatic(modifiers)) { - throw new NotCompliantMBeanException( - "@Resource method or field cannot be static: " + - member); - } - - for (Class<?> injectedClass : injectedClasses) { - Class<?>[] types = {memberType, res.type()}; - boolean accept = false; - for (int i = 0; i < 2; i++) { - if (types[i] == injectedClass && - types[1 - i].isAssignableFrom(injectedClass)) { - accept = true; - break; - } - } - if (accept) { - AccessController.doPrivileged(new PrivilegedAction<Void>() { - public Void run() { - member.setAccessible(true); - return null; - } - }); - addToMap(fields, injectedClass, field); - addToMap(methods, injectedClass, method); - } - } - } - } - } - - private static <K, V> void addToMap(Map<K, List<V>> map, K key, V value) { - if (value == null) - return; - List<V> list = map.get(key); - if (list == null) - list = Collections.singletonList(value); - else { - if (list.size() == 1) - list = new ArrayList<V>(list); - list.add(value); - } - map.put(key, list); - } - } - - private static synchronized ClassInjector injectorForClass(Class<?> c) - throws NotCompliantMBeanException { - WeakReference<ClassInjector> wr = injectorMap.get(c); - ClassInjector ci = (wr == null) ? null : wr.get(); - if (ci == null) { - ci = new ClassInjector(c); - injectorMap.put(c, new WeakReference<ClassInjector>(ci)); - } - return ci; - } - - private static Map<Class<?>, WeakReference<ClassInjector>> injectorMap = - new WeakHashMap<Class<?>, WeakReference<ClassInjector>>(); -}
--- a/jdk/src/share/classes/com/sun/jmx/mbeanserver/MBeanInstantiator.java Wed Oct 21 16:28:57 2009 +0200 +++ b/jdk/src/share/classes/com/sun/jmx/mbeanserver/MBeanInstantiator.java Wed Oct 21 17:33:18 2009 +0200 @@ -614,15 +614,6 @@ } /** - * Returns the class of a primitive type. - * @param name The type for which we the associated class. - * @return the class, or null if name is not primitive. - */ - public static Class<?> primitiveType(String name) { - return primitiveClasses.get(name); - } - - /** * Load a class with the specified loader, or with this object * class loader if the specified loader is null. **/
--- a/jdk/src/share/classes/com/sun/jmx/mbeanserver/MBeanIntrospector.java Wed Oct 21 16:28:57 2009 +0200 +++ b/jdk/src/share/classes/com/sun/jmx/mbeanserver/MBeanIntrospector.java Wed Oct 21 17:33:18 2009 +0200 @@ -36,28 +36,20 @@ import java.lang.reflect.Type; import java.util.Arrays; import java.util.List; -import java.util.Map; import java.util.WeakHashMap; -import javax.management.Description; import javax.management.Descriptor; import javax.management.ImmutableDescriptor; import javax.management.IntrospectionException; import javax.management.InvalidAttributeValueException; -import javax.management.MBean; 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.MXBean; -import javax.management.ManagedAttribute; -import javax.management.ManagedOperation; import javax.management.NotCompliantMBeanException; import javax.management.NotificationBroadcaster; -import javax.management.NotificationInfo; -import javax.management.NotificationInfos; import javax.management.ReflectionException; /** @@ -79,7 +71,7 @@ * ancestor with ConvertingMethod. But that would mean an extra object * for every Method in every Standard MBean interface. */ -public abstract class MBeanIntrospector<M> { +abstract class MBeanIntrospector<M> { static final class PerInterfaceMap<M> extends WeakHashMap<Class<?>, WeakReference<PerInterface<M>>> {} @@ -159,27 +151,7 @@ * may be null. */ abstract MBeanAttributeInfo getMBeanAttributeInfo(String attributeName, - M getter, M setter) throws IntrospectionException; - - final String getAttributeDescription( - String attributeName, String defaultDescription, - Method getter, Method setter) throws IntrospectionException { - String g = Introspector.descriptionForElement(getter); - String s = Introspector.descriptionForElement(setter); - if (g == null) { - if (s == null) - return defaultDescription; - else - return s; - } else if (s == null || g.equals(s)) { - return g; - } else { - throw new IntrospectionException( - "Inconsistent @Description on getter and setter for " + - "attribute " + attributeName); - } - } - + M getter, M setter); /** * Construct an MBeanOperationInfo for the given operation based on * the M it was derived from. @@ -201,36 +173,10 @@ abstract Descriptor getMBeanDescriptor(Class<?> resourceClass); /** - * Get any additional Descriptor entries for this introspector instance. - * If there is a non-default MXBeanMappingFactory, it will appear in - * this Descriptor. - * @return Additional Descriptor entries, or an empty Descriptor if none. - */ - Descriptor getSpecificMBeanDescriptor() { - return ImmutableDescriptor.EMPTY_DESCRIPTOR; - } - - void checkCompliance(Class<?> mbeanType) throws NotCompliantMBeanException { - if (!mbeanType.isInterface() && - !mbeanType.isAnnotationPresent(MBean.class) && - !Introspector.hasMXBeanAnnotation(mbeanType)) { - throw new NotCompliantMBeanException("Not an interface and " + - "does not have @" + MBean.class.getSimpleName() + - " or @" + MXBean.class.getSimpleName() + " annotation: " + - mbeanType.getName()); - } - } - - /** * Get the methods to be analyzed to build the MBean interface. */ List<Method> getMethods(final Class<?> mbeanType) throws Exception { - if (mbeanType.isInterface()) - return Arrays.asList(mbeanType.getMethods()); - - final List<Method> methods = newList(); - getAnnotatedMethods(mbeanType, methods); - return methods; + return Arrays.asList(mbeanType.getMethods()); } final PerInterface<M> getPerInterface(Class<?> mbeanInterface) @@ -265,14 +211,11 @@ * the MBeanInfo's Descriptor. */ private MBeanInfo makeInterfaceMBeanInfo(Class<?> mbeanInterface, - MBeanAnalyzer<M> analyzer) throws IntrospectionException { + MBeanAnalyzer<M> analyzer) { final MBeanInfoMaker maker = new MBeanInfoMaker(); analyzer.visit(maker); - final String defaultDescription = + final String description = "Information on the management interface of the MBean"; - String description = Introspector.descriptionForElement(mbeanInterface); - if (description == null) - description = defaultDescription; return maker.makeMBeanInfo(mbeanInterface, description); } @@ -370,11 +313,11 @@ /** A visitor that constructs the per-interface MBeanInfo. */ private class MBeanInfoMaker - implements MBeanAnalyzer.MBeanVisitor<M, IntrospectionException> { + implements MBeanAnalyzer.MBeanVisitor<M> { public void visitAttribute(String attributeName, M getter, - M setter) throws IntrospectionException { + M setter) { MBeanAttributeInfo mbai = getMBeanAttributeInfo(attributeName, getter, setter); @@ -403,7 +346,7 @@ new ImmutableDescriptor(interfaceClassName); final Descriptor mbeanDescriptor = getBasicMBeanDescriptor(); final Descriptor annotatedDescriptor = - Introspector.descriptorForElement(mbeanInterface, false); + Introspector.descriptorForElement(mbeanInterface); final Descriptor descriptor = DescriptorCache.getInstance().union( classNameDescriptor, @@ -442,32 +385,20 @@ * Return the MBeanInfo for the given resource, based on the given * per-interface data. */ - final MBeanInfo getMBeanInfo(Object resource, PerInterface<M> perInterface) - throws NotCompliantMBeanException { + final MBeanInfo getMBeanInfo(Object resource, PerInterface<M> perInterface) { MBeanInfo mbi = getClassMBeanInfo(resource.getClass(), perInterface); - MBeanNotificationInfo[] notifs; - try { - notifs = findNotifications(resource); - } catch (RuntimeException e) { - NotCompliantMBeanException x = - new NotCompliantMBeanException(e.getMessage()); - x.initCause(e); - throw x; - } - Descriptor d = getSpecificMBeanDescriptor(); - boolean anyNotifs = (notifs != null && notifs.length > 0); - if (!anyNotifs && ImmutableDescriptor.EMPTY_DESCRIPTOR.equals(d)) + MBeanNotificationInfo[] notifs = findNotifications(resource); + if (notifs == null || notifs.length == 0) return mbi; else { - d = ImmutableDescriptor.union(d, mbi.getDescriptor()); return new MBeanInfo(mbi.getClassName(), mbi.getDescription(), mbi.getAttributes(), mbi.getConstructors(), mbi.getOperations(), notifs, - d); + mbi.getDescriptor()); } } @@ -507,145 +438,29 @@ } } - /* - * Add to "methods" every public method that has the @ManagedAttribute - * or @ManagedOperation annotation, in the given class or any of - * its superclasses or superinterfaces. - * - * We always add superclass or superinterface methods first, so that - * the stable sort used by eliminateCovariantMethods will put the - * method from the most-derived class last. This means that we will - * see the version of the @ManagedAttribute (or ...Operation) annotation - * from that method, which might have a different description or whatever. - */ - public static void getAnnotatedMethods(Class<?> c, List<Method> methods) - throws Exception { - Class<?> sup = c.getSuperclass(); - if (sup != null) - getAnnotatedMethods(sup, methods); - Class<?>[] intfs = c.getInterfaces(); - for (Class<?> intf : intfs) - getAnnotatedMethods(intf, methods); - for (Method m : c.getMethods()) { - // We are careful not to add m if it is inherited from a parent - // class or interface, because duplicate methods lead to nasty - // behaviour in eliminateCovariantMethods. - if (m.getDeclaringClass() == c && - (m.isAnnotationPresent(ManagedAttribute.class) || - m.isAnnotationPresent(ManagedOperation.class))) - methods.add(m); - } - } - - /* - * Return the array of MBeanNotificationInfo for the given MBean object. - * If the object implements NotificationBroadcaster and its - * getNotificationInfo() method returns a non-empty array, then that - * is the result. Otherwise, if the object has a @NotificationInfo - * or @NotificationInfos annotation, then its contents form the result. - * Otherwise, the result is null. - */ static MBeanNotificationInfo[] findNotifications(Object moi) { - if (moi instanceof NotificationBroadcaster) { - MBeanNotificationInfo[] mbn = - ((NotificationBroadcaster) moi).getNotificationInfo(); - if (mbn != null && mbn.length > 0) { - 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; - } - } else { - try { - if (!MBeanInjector.injectsSendNotification(moi)) - return null; - } catch (NotCompliantMBeanException e) { - throw new RuntimeException(e); - } + 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 findNotificationsFromAnnotations(moi.getClass()); - } - - public static MBeanNotificationInfo[] findNotificationsFromAnnotations( - Class<?> mbeanClass) { - Class<?> c = getAnnotatedNotificationInfoClass(mbeanClass); - if (c == null) - return null; - NotificationInfo ni = c.getAnnotation(NotificationInfo.class); - NotificationInfos nis = c.getAnnotation(NotificationInfos.class); - List<NotificationInfo> list = newList(); - if (ni != null) - list.add(ni); - if (nis != null) - list.addAll(Arrays.asList(nis.value())); - if (list.isEmpty()) - return null; - List<MBeanNotificationInfo> mbnis = newList(); - for (NotificationInfo x : list) { - // The Descriptor includes any fields explicitly specified by - // x.descriptorFields(), plus any fields from the contained - // @Description annotation. - Descriptor d = new ImmutableDescriptor(x.descriptorFields()); - d = ImmutableDescriptor.union( - d, Introspector.descriptorForAnnotation(x.description())); - MBeanNotificationInfo mbni = new MBeanNotificationInfo( - x.types(), x.notificationClass().getName(), - x.description().value(), d); - mbnis.add(mbni); - } - return mbnis.toArray(new MBeanNotificationInfo[mbnis.size()]); - } - - private static final Map<Class<?>, WeakReference<Class<?>>> - annotatedNotificationInfoClasses = newWeakHashMap(); - - private static Class<?> getAnnotatedNotificationInfoClass(Class<?> baseClass) { - synchronized (annotatedNotificationInfoClasses) { - WeakReference<Class<?>> wr = - annotatedNotificationInfoClasses.get(baseClass); - if (wr != null) - return wr.get(); - Class<?> c = null; - if (baseClass.isAnnotationPresent(NotificationInfo.class) || - baseClass.isAnnotationPresent(NotificationInfos.class)) { - c = baseClass; - } else { - Class<?>[] intfs = baseClass.getInterfaces(); - for (Class<?> intf : intfs) { - Class<?> c1 = getAnnotatedNotificationInfoClass(intf); - if (c1 != null) { - if (c != null) { - throw new IllegalArgumentException( - "Class " + baseClass.getName() + " inherits " + - "@NotificationInfo(s) from both " + - c.getName() + " and " + c1.getName()); - } - c = c1; - } - } - } - // Record the result of the search. If no @NotificationInfo(s) - // were found, c is null, and we store a WeakReference(null). - // This prevents us from having to search again and fail again. - annotatedNotificationInfoClasses.put(baseClass, - new WeakReference<Class<?>>(c)); - return c; - } + 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++) { - String descr = "Public constructor of the MBean"; - Description d = cons[i].getAnnotation(Description.class); - if (d != null) - descr = d.value(); + final String descr = "Public constructor of the MBean"; mbc[i] = new MBeanConstructorInfo(descr, cons[i]); } return mbc;
--- a/jdk/src/share/classes/com/sun/jmx/mbeanserver/MBeanSupport.java Wed Oct 21 16:28:57 2009 +0200 +++ b/jdk/src/share/classes/com/sun/jmx/mbeanserver/MBeanSupport.java Wed Oct 21 17:33:18 2009 +0200 @@ -37,7 +37,7 @@ import javax.management.NotCompliantMBeanException; import javax.management.ObjectName; import javax.management.ReflectionException; -import javax.management.openmbean.MXBeanMappingFactory; +import com.sun.jmx.mbeanserver.MXBeanMappingFactory; /** * Base class for MBeans. There is one instance of this class for @@ -121,8 +121,7 @@ public abstract class MBeanSupport<M> implements DynamicMBean2, MBeanRegistration { - <T> MBeanSupport(T resource, Class<T> mbeanInterfaceType, - MXBeanMappingFactory mappingFactory) + <T> MBeanSupport(T resource, Class<T> mbeanInterfaceType) throws NotCompliantMBeanException { if (mbeanInterfaceType == null) throw new NotCompliantMBeanException("Null MBean interface"); @@ -133,14 +132,13 @@ throw new NotCompliantMBeanException(msg); } this.resource = resource; - MBeanIntrospector<M> introspector = getMBeanIntrospector(mappingFactory); + 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(MXBeanMappingFactory mappingFactory); + abstract MBeanIntrospector<M> getMBeanIntrospector(); /** * Return a cookie for this MBean. This cookie will be passed to @@ -262,14 +260,10 @@ return resource.getClass().getName(); } - public final Object getWrappedObject() { + public final Object getResource() { return resource; } - public final ClassLoader getWrappedClassLoader() { - return resource.getClass().getClassLoader(); - } - public final Class<?> getMBeanInterface() { return perInterface.getMBeanInterface(); }
--- a/jdk/src/share/classes/com/sun/jmx/mbeanserver/MXBeanIntrospector.java Wed Oct 21 16:28:57 2009 +0200 +++ b/jdk/src/share/classes/com/sun/jmx/mbeanserver/MXBeanIntrospector.java Wed Oct 21 17:33:18 2009 +0200 @@ -28,26 +28,18 @@ import com.sun.jmx.mbeanserver.MBeanIntrospector.MBeanInfoMap; import com.sun.jmx.mbeanserver.MBeanIntrospector.PerInterfaceMap; import java.lang.annotation.Annotation; -import java.lang.ref.WeakReference; 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 java.util.Map; -import java.util.WeakHashMap; -import javax.management.Description; import javax.management.Descriptor; import javax.management.ImmutableDescriptor; -import javax.management.IntrospectionException; -import javax.management.JMX; import javax.management.MBeanAttributeInfo; import javax.management.MBeanException; import javax.management.MBeanOperationInfo; import javax.management.MBeanParameterInfo; -import javax.management.ManagedOperation; import javax.management.NotCompliantMBeanException; -import javax.management.openmbean.MXBeanMappingFactory; import javax.management.openmbean.OpenMBeanAttributeInfoSupport; import javax.management.openmbean.OpenMBeanOperationInfoSupport; import javax.management.openmbean.OpenMBeanParameterInfo; @@ -60,36 +52,10 @@ * @since 1.6 */ class MXBeanIntrospector extends MBeanIntrospector<ConvertingMethod> { - /* We keep one MXBeanIntrospector per MXBeanMappingFactory, since the results - * of the introspection depend on the factory. The MXBeanIntrospector - * has a reference back to the factory, so we wrap it in a WeakReference. - * It will be strongly referenced by any MXBeanSupport instances using it; - * if there are none then it is OK to gc it. - */ - private static final - Map<MXBeanMappingFactory, WeakReference<MXBeanIntrospector>> map = - new WeakHashMap<MXBeanMappingFactory, WeakReference<MXBeanIntrospector>>(); + private static final MXBeanIntrospector instance = new MXBeanIntrospector(); - static MXBeanIntrospector getInstance(MXBeanMappingFactory factory) { - if (factory == null) - factory = MXBeanMappingFactory.DEFAULT; - synchronized (map) { - MXBeanIntrospector intro; - WeakReference<MXBeanIntrospector> wr = map.get(factory); - if (wr != null) { - intro = wr.get(); - if (intro != null) - return intro; - } - intro = new MXBeanIntrospector(factory); - wr = new WeakReference<MXBeanIntrospector>(intro); - map.put(factory, wr); - return intro; - } - } - - private MXBeanIntrospector(MXBeanMappingFactory factory) { - this.mappingFactory = factory; + static MXBeanIntrospector getInstance() { + return instance; } @Override @@ -115,7 +81,7 @@ @Override ConvertingMethod mFrom(Method m) { - return ConvertingMethod.from(m, mappingFactory); + return ConvertingMethod.from(m); } @Override @@ -176,17 +142,13 @@ @Override MBeanAttributeInfo getMBeanAttributeInfo(String attributeName, - ConvertingMethod getter, ConvertingMethod setter) - throws IntrospectionException { + 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 = getAttributeDescription( - attributeName, attributeName, - getter == null ? null : getter.getMethod(), - setter == null ? null : setter.getMethod()); + final String description = attributeName; final OpenType<?> openType; final Type originalType; @@ -235,17 +197,13 @@ MBeanOperationInfo getMBeanOperationInfo(String operationName, ConvertingMethod operation) { final Method method = operation.getMethod(); - String description = operationName; + final String description = operationName; /* Ideally this would be an empty string, but - OMBOperationInfo constructor forbids that. */ - Description d = method.getAnnotation(Description.class); - if (d != null) - description = d.value(); + OMBOperationInfo constructor forbids that. Also, we + could consult an annotation to get a useful + description. */ - int impact = MBeanOperationInfo.UNKNOWN; - ManagedOperation annot = method.getAnnotation(ManagedOperation.class); - if (annot != null) - impact = annot.impact().getCode(); + final int impact = MBeanOperationInfo.UNKNOWN; final OpenType<?> returnType = operation.getOpenReturnType(); final Type originalReturnType = operation.getGenericReturnType(); @@ -257,15 +215,8 @@ boolean openParameterTypes = true; Annotation[][] annots = method.getParameterAnnotations(); for (int i = 0; i < paramTypes.length; i++) { - String paramName = Introspector.nameForParameter(annots[i]); - if (paramName == null) - paramName = "p" + i; - - String paramDescription = - Introspector.descriptionForParameter(annots[i]); - if (paramDescription == null) - paramDescription = paramName; - + final String paramName = "p" + i; + final String paramDescription = paramName; final OpenType<?> openType = paramTypes[i]; final Type originalType = originalParamTypes[i]; Descriptor descriptor = @@ -292,7 +243,7 @@ Descriptor descriptor = typeDescriptor(returnType, originalReturnType); descriptor = ImmutableDescriptor.union(descriptor, - Introspector.descriptorForElement(method, false)); + Introspector.descriptorForElement(method)); final MBeanOperationInfo oi; if (openReturnType && openParameterTypes) { /* If the return value and all the parameters can be faithfully @@ -343,17 +294,6 @@ return ImmutableDescriptor.EMPTY_DESCRIPTOR; } - @Override - Descriptor getSpecificMBeanDescriptor() { - if (mappingFactory == MXBeanMappingFactory.DEFAULT) - return ImmutableDescriptor.EMPTY_DESCRIPTOR; - else { - return new ImmutableDescriptor( - JMX.MXBEAN_MAPPING_FACTORY_CLASS_FIELD + "=" + - mappingFactory.getClass().getName()); - } - } - private static Descriptor typeDescriptor(OpenType<?> openType, Type originalType) { return new ImmutableDescriptor( @@ -421,7 +361,5 @@ private final PerInterfaceMap<ConvertingMethod> perInterfaceMap = new PerInterfaceMap<ConvertingMethod>(); - private final MBeanInfoMap mbeanInfoMap = new MBeanInfoMap(); - - private final MXBeanMappingFactory mappingFactory; + private static final MBeanInfoMap mbeanInfoMap = new MBeanInfoMap(); }
--- a/jdk/src/share/classes/com/sun/jmx/mbeanserver/MXBeanLookup.java Wed Oct 21 16:28:57 2009 +0200 +++ b/jdk/src/share/classes/com/sun/jmx/mbeanserver/MXBeanLookup.java Wed Oct 21 17:33:18 2009 +0200 @@ -25,8 +25,6 @@ package com.sun.jmx.mbeanserver; -import com.sun.jmx.remote.util.EnvHelp; -import java.io.InvalidObjectException; import static com.sun.jmx.mbeanserver.Util.*; import java.util.Map; import java.lang.ref.WeakReference; @@ -85,181 +83,87 @@ * * 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. - * - * The above describes the logic for "plain" MXBeanLookup, represented - * by MXBeanLookup.Plain. When namespaces enter the picture, we see - * MXBeanLookup.Prefix. Here, the idea is that the name of the ModuleMXBean - * might be a//m:m=m. In this case, we don't accept a reference to - * an MXBean object, since that would require different namespaces to know - * each others' objects. We only accept proxies. Suppose you have a proxy - * for a//m:m=m, call it moduleProxy, and you call - * moduleProxy.setProduct(productProxy). Then if productProxy is for - * a//p:p=p we should convert this to just p:p=p. If productProxy is for - * a//b//p:p=p we should convert it to b//p:p=p. Conversely, if getProduct - * returns an ObjectName like b//p:p=p then we should convert it into a proxy - * for a//b//p:p=p. */ -public abstract class MXBeanLookup { +public class MXBeanLookup { private MXBeanLookup(MBeanServerConnection mbsc) { this.mbsc = mbsc; } - static MXBeanLookup lookupFor(MBeanServerConnection mbsc, String prefix) { - if (prefix == null) - return Plain.lookupFor(mbsc); - else - return new Prefix(mbsc, prefix); - } - - abstract <T> T objectNameToMXBean(ObjectName name, Class<T> type) - throws InvalidObjectException; - - abstract ObjectName mxbeanToObjectName(Object mxbean) - throws OpenDataException; - - static class Plain extends MXBeanLookup { - Plain(MBeanServerConnection mbsc) { - super(mbsc); - } - - static Plain lookupFor(MBeanServerConnection mbsc) { - synchronized (mbscToLookup) { - WeakReference<Plain> weakLookup = mbscToLookup.get(mbsc); - Plain lookup = (weakLookup == null) ? null : weakLookup.get(); - if (lookup == null) { - lookup = new Plain(mbsc); - mbscToLookup.put(mbsc, new WeakReference<Plain>(lookup)); - } - return lookup; - } - } - - @Override - 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; - } - - @Override - 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"; + 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)); } - 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. - */ - } - - private final WeakIdentityHashMap<Object, ObjectName> - mxbeanToObjectName = WeakIdentityHashMap.make(); - private final Map<ObjectName, WeakReference<Object>> - objectNameToProxy = newMap(); - private static WeakIdentityHashMap<MBeanServerConnection, - WeakReference<Plain>> - mbscToLookup = WeakIdentityHashMap.make(); - } - - private static class Prefix extends MXBeanLookup { - private final String prefix; - - Prefix(MBeanServerConnection mbsc, String prefix) { - super(mbsc); - this.prefix = prefix; - } - - @Override - <T> T objectNameToMXBean(ObjectName name, Class<T> type) - throws InvalidObjectException { - String domain = prefix + name.getDomain(); - try { - name = name.withDomain(domain); - } catch (IllegalArgumentException e) { - throw EnvHelp.initCause( - new InvalidObjectException(e.getMessage()), e); - } - return JMX.newMXBeanProxy(mbsc, name, type); - } - - @Override - ObjectName mxbeanToObjectName(Object mxbean) - throws OpenDataException { - ObjectName name = proxyToObjectName(mxbean); - String domain = name.getDomain(); - if (!domain.startsWith(prefix)) { - throw new OpenDataException( - "Proxy's name does not start with " + - prefix + ": " + name); - } - try { - name = name.withDomain(domain.substring(prefix.length())); - } catch (IllegalArgumentException e) { - throw EnvHelp.initCause( - new OpenDataException(e.getMessage()), e); - } - return name; + return lookup; } } - ObjectName proxyToObjectName(Object proxy) { - InvocationHandler ih = Proxy.getInvocationHandler(proxy); - if (ih instanceof MBeanServerInvocationHandler) { - MBeanServerInvocationHandler mbsih = - (MBeanServerInvocationHandler) ih; - if (mbsih.getMBeanServerConnection().equals(mbsc)) - return mbsih.getObjectName(); + 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"; } - return null; + 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() { @@ -273,5 +177,12 @@ private static final ThreadLocal<MXBeanLookup> currentLookup = new ThreadLocal<MXBeanLookup>(); - final MBeanServerConnection mbsc; + 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(); }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/src/share/classes/com/sun/jmx/mbeanserver/MXBeanMapping.java Wed Oct 21 17:33:18 2009 +0200 @@ -0,0 +1,210 @@ +/* + * Copyright 2007-2008 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.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, null); + } 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 {} +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/src/share/classes/com/sun/jmx/mbeanserver/MXBeanMappingFactory.java Wed Oct 21 17:33:18 2009 +0200 @@ -0,0 +1,124 @@ +/* + * Copyright 2007-2008 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.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; +}
--- a/jdk/src/share/classes/com/sun/jmx/mbeanserver/MXBeanProxy.java Wed Oct 21 16:28:57 2009 +0200 +++ b/jdk/src/share/classes/com/sun/jmx/mbeanserver/MXBeanProxy.java Wed Oct 21 17:33:18 2009 +0200 @@ -32,10 +32,8 @@ import javax.management.Attribute; import javax.management.MBeanServerConnection; -import javax.management.MalformedObjectNameException; import javax.management.NotCompliantMBeanException; import javax.management.ObjectName; -import javax.management.openmbean.MXBeanMappingFactory; /** <p>Helper class for an {@link InvocationHandler} that forwards methods from an @@ -47,7 +45,7 @@ @since 1.6 */ public class MXBeanProxy { - public MXBeanProxy(Class<?> mxbeanInterface, MXBeanMappingFactory factory) { + public MXBeanProxy(Class<?> mxbeanInterface) { if (mxbeanInterface == null) throw new IllegalArgumentException("Null parameter"); @@ -55,7 +53,7 @@ final MBeanAnalyzer<ConvertingMethod> analyzer; try { analyzer = - MXBeanIntrospector.getInstance(factory).getAnalyzer(mxbeanInterface); + MXBeanIntrospector.getInstance().getAnalyzer(mxbeanInterface); } catch (NotCompliantMBeanException e) { throw new IllegalArgumentException(e); } @@ -63,7 +61,7 @@ } private class Visitor - implements MBeanAnalyzer.MBeanVisitor<ConvertingMethod, RuntimeException> { + implements MBeanAnalyzer.MBeanVisitor<ConvertingMethod> { public void visitAttribute(String attributeName, ConvertingMethod getter, ConvertingMethod setter) { @@ -161,8 +159,7 @@ Handler handler = handlerMap.get(method); ConvertingMethod cm = handler.getConvertingMethod(); - String prefix = extractPrefix(name); - MXBeanLookup lookup = MXBeanLookup.lookupFor(mbsc, prefix); + MXBeanLookup lookup = MXBeanLookup.lookupFor(mbsc); MXBeanLookup oldLookup = MXBeanLookup.getLookup(); try { MXBeanLookup.setLookup(lookup); @@ -174,17 +171,5 @@ } } - private static String extractPrefix(ObjectName name) - throws MalformedObjectNameException { - String domain = name.getDomain(); - int slashslash = domain.lastIndexOf("//"); - if (slashslash > 0 && domain.charAt(slashslash - 1) == '/') - slashslash--; - if (slashslash >= 0) - return domain.substring(0, slashslash + 2); - else - return null; - } - private final Map<Method, Handler> handlerMap = newMap(); }
--- a/jdk/src/share/classes/com/sun/jmx/mbeanserver/MXBeanSupport.java Wed Oct 21 16:28:57 2009 +0200 +++ b/jdk/src/share/classes/com/sun/jmx/mbeanserver/MXBeanSupport.java Wed Oct 21 17:33:18 2009 +0200 @@ -35,7 +35,6 @@ import javax.management.MBeanServer; import javax.management.NotCompliantMBeanException; import javax.management.ObjectName; -import javax.management.openmbean.MXBeanMappingFactory; /** * Base class for MXBeans. @@ -62,16 +61,14 @@ 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, - MXBeanMappingFactory mappingFactory) + public <T> MXBeanSupport(T resource, Class<T> mxbeanInterface) throws NotCompliantMBeanException { - super(resource, mxbeanInterface, mappingFactory); + super(resource, mxbeanInterface); } @Override - MBeanIntrospector<ConvertingMethod> - getMBeanIntrospector(MXBeanMappingFactory mappingFactory) { - return MXBeanIntrospector.getInstance(mappingFactory); + MBeanIntrospector<ConvertingMethod> getMBeanIntrospector() { + return MXBeanIntrospector.getInstance(); } @Override @@ -159,8 +156,8 @@ // eventually we could have some logic to supply a default name synchronized (lock) { - this.mxbeanLookup = MXBeanLookup.Plain.lookupFor(server); - this.mxbeanLookup.addReference(name, getWrappedObject()); + this.mxbeanLookup = MXBeanLookup.lookupFor(server); + this.mxbeanLookup.addReference(name, getResource()); this.objectName = name; } } @@ -169,19 +166,13 @@ public void unregister() { synchronized (lock) { if (mxbeanLookup != null) { - if (mxbeanLookup.removeReference(objectName, getWrappedObject())) + if (mxbeanLookup.removeReference(objectName, getResource())) objectName = null; } - // XXX: need to revisit the whole register/unregister logic in - // the face of wrapping. The mxbeanLookup!=null test is a hack. - // If you wrap an MXBean in a MyWrapperMBean and register it, - // the lookup table should contain the wrapped object. But that - // implies that MyWrapperMBean calls register, which today it - // can't within the public API. } } private final Object lock = new Object(); // for mxbeanLookup and objectName - private MXBeanLookup.Plain mxbeanLookup; + private MXBeanLookup mxbeanLookup; private ObjectName objectName; }
--- a/jdk/src/share/classes/com/sun/jmx/mbeanserver/NotificationMBeanSupport.java Wed Oct 21 16:28:57 2009 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,82 +0,0 @@ -/* - * Copyright 2007-2008 Sun Microsystems, Inc. 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. Sun designates this - * particular file as subject to the "Classpath" exception as provided - * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, - * CA 95054 USA or visit www.sun.com if you need additional information or - * have any questions. - */ - -package com.sun.jmx.mbeanserver; - -import java.lang.reflect.Method; -import java.util.ArrayList; -import java.util.List; -import javax.management.NotCompliantMBeanException; -import javax.management.Notification; -import javax.management.openmbean.MXBeanMappingFactory; - -/** - * <p>A variant of {@code StandardMBeanSupport} where the only - * methods included are public getters. This is used by - * {@code QueryNotificationFilter} to pretend that a Notification is - * an MBean so it can have a query evaluated on it. Standard queries - * never set attributes or invoke methods but custom queries could and - * we don't want to allow that. Also we don't want to fail if a - * Notification happens to have inconsistent types in a pair of getX and - * setX methods, and we want to include the Object.getClass() method. - */ -public class NotificationMBeanSupport extends StandardMBeanSupport { - public <T extends Notification> NotificationMBeanSupport(T n) - throws NotCompliantMBeanException { - super(n, Util.<Class<T>>cast(n.getClass())); - } - - @Override - MBeanIntrospector<Method> getMBeanIntrospector(MXBeanMappingFactory ignored) { - return introspector; - } - - private static class Introspector extends StandardMBeanIntrospector { - @Override - void checkCompliance(Class<?> mbeanType) {} - - @Override - List<Method> getMethods(final Class<?> mbeanType) - throws Exception { - List<Method> methods = new ArrayList<Method>(); - for (Method m : mbeanType.getMethods()) { - String name = m.getName(); - Class<?> ret = m.getReturnType(); - if (m.getParameterTypes().length == 0) { - if ((name.startsWith("is") && name.length() > 2 && - ret == boolean.class) || - (name.startsWith("get") && name.length() > 3 && - ret != void.class)) { - methods.add(m); - } - } - } - return methods; - } - - } - private static final MBeanIntrospector<Method> introspector = - new Introspector(); -}
--- a/jdk/src/share/classes/com/sun/jmx/mbeanserver/NotifySupport.java Wed Oct 21 16:28:57 2009 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,186 +0,0 @@ -/* - * Copyright 2007-2008 Sun Microsystems, Inc. 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. Sun designates this - * particular file as subject to the "Classpath" exception as provided - * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, - * CA 95054 USA or visit www.sun.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.DynamicMBean; -import javax.management.DynamicWrapperMBean; -import javax.management.InvalidAttributeValueException; -import javax.management.ListenerNotFoundException; -import javax.management.MBeanException; -import javax.management.MBeanInfo; -import javax.management.MBeanNotificationInfo; -import javax.management.MBeanRegistration; -import javax.management.MBeanServer; -import javax.management.NotificationBroadcasterSupport; -import javax.management.NotificationEmitter; -import javax.management.NotificationFilter; -import javax.management.NotificationListener; -import javax.management.ObjectName; -import javax.management.ReflectionException; - -/** - * Create wrappers for DynamicMBean that implement NotificationEmitter - * and SendNotification. - */ -public class NotifySupport - implements DynamicMBean2, NotificationEmitter, MBeanRegistration { - - private final DynamicMBean mbean; - private final NotificationBroadcasterSupport nbs; - - public static DynamicMBean wrap( - DynamicMBean mbean, NotificationBroadcasterSupport nbs) { - return new NotifySupport(mbean, nbs); - } - - private NotifySupport(DynamicMBean mbean, NotificationBroadcasterSupport nbs) { - this.mbean = mbean; - this.nbs = nbs; - } - - public static NotificationBroadcasterSupport getNB(DynamicMBean mbean) { - if (mbean instanceof NotifySupport) - return ((NotifySupport) mbean).nbs; - else - return null; - } - - public String getClassName() { - if (mbean instanceof DynamicMBean2) - return ((DynamicMBean2) mbean).getClassName(); - Object w = mbean; - if (w instanceof DynamicWrapperMBean) - w = ((DynamicWrapperMBean) w).getWrappedObject(); - return w.getClass().getName(); - } - - public void preRegister2(MBeanServer mbs, ObjectName name) throws Exception { - if (mbean instanceof DynamicMBean2) - ((DynamicMBean2) mbean).preRegister2(mbs, name); - } - - public void registerFailed() { - if (mbean instanceof DynamicMBean2) - ((DynamicMBean2) mbean).registerFailed(); - } - - public Object getWrappedObject() { - if (mbean instanceof DynamicWrapperMBean) - return ((DynamicWrapperMBean) mbean).getWrappedObject(); - else - return mbean; - } - - public ClassLoader getWrappedClassLoader() { - if (mbean instanceof DynamicWrapperMBean) - return ((DynamicWrapperMBean) mbean).getWrappedClassLoader(); - else - return mbean.getClass().getClassLoader(); - } - - public Object getAttribute(String attribute) throws AttributeNotFoundException, - MBeanException, - ReflectionException { - return mbean.getAttribute(attribute); - } - - public void setAttribute(Attribute attribute) throws AttributeNotFoundException, - InvalidAttributeValueException, - MBeanException, - ReflectionException { - mbean.setAttribute(attribute); - } - - public AttributeList setAttributes(AttributeList attributes) { - return mbean.setAttributes(attributes); - } - - public Object invoke(String actionName, Object[] params, String[] signature) - throws MBeanException, ReflectionException { - return mbean.invoke(actionName, params, signature); - } - - public MBeanInfo getMBeanInfo() { - return mbean.getMBeanInfo(); - } - - public AttributeList getAttributes(String[] attributes) { - return mbean.getAttributes(attributes); - } - - public void removeNotificationListener(NotificationListener listener, - NotificationFilter filter, - Object handback) throws ListenerNotFoundException { - nbs.removeNotificationListener(listener, filter, handback); - } - - public void removeNotificationListener(NotificationListener listener) - throws ListenerNotFoundException { - nbs.removeNotificationListener(listener); - } - - public MBeanNotificationInfo[] getNotificationInfo() { - return nbs.getNotificationInfo(); - } - - public void addNotificationListener(NotificationListener listener, - NotificationFilter filter, - Object handback) { - nbs.addNotificationListener(listener, filter, handback); - } - - public ObjectName preRegister(MBeanServer server, ObjectName name) throws Exception { - if (mbr() != null) - return mbr().preRegister(server, name); - else - return name; - } - - public void postRegister(Boolean registrationDone) { - if (mbr() != null) - mbr().postRegister(registrationDone); - } - - public void preDeregister() throws Exception { - if (mbr() != null) - mbr().preDeregister(); - } - - public void postDeregister() { - if (mbr() != null) - mbr().postDeregister(); - } - - private MBeanRegistration mbr() { - if (mbean instanceof MBeanRegistration) - return (MBeanRegistration) mbean; - else - return null; - } -}
--- a/jdk/src/share/classes/com/sun/jmx/mbeanserver/PerInterface.java Wed Oct 21 16:28:57 2009 +0200 +++ b/jdk/src/share/classes/com/sun/jmx/mbeanserver/PerInterface.java Wed Oct 21 17:33:18 2009 +0200 @@ -1,5 +1,5 @@ /* - * Copyright 2005-2008 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2005-2006 Sun Microsystems, Inc. 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 @@ -231,7 +231,7 @@ /** * Visitor that sets up the method maps (operations, getters, setters). */ - private class InitMaps implements MBeanAnalyzer.MBeanVisitor<M, RuntimeException> { + private class InitMaps implements MBeanAnalyzer.MBeanVisitor<M> { public void visitAttribute(String attributeName, M getter, M setter) {
--- a/jdk/src/share/classes/com/sun/jmx/mbeanserver/PerThreadGroupPool.java Wed Oct 21 16:28:57 2009 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,71 +0,0 @@ -/* - * Copyright 1999-2008 Sun Microsystems, Inc. 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. Sun designates this - * particular file as subject to the "Classpath" exception as provided - * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, - * CA 95054 USA or visit www.sun.com if you need additional information or - * have any questions. - */ - -package com.sun.jmx.mbeanserver; - -import java.lang.ref.WeakReference; -import java.util.concurrent.ThreadPoolExecutor; - -/** - * <p>A factory for ThreadPoolExecutor objects that allows the same object to - * be shared by all users of the factory that are in the same ThreadGroup.</p> - */ -// We return a ThreadPoolExecutor rather than the more general ExecutorService -// because we need to be able to call allowCoreThreadTimeout so that threads in -// the pool will eventually be destroyed when the pool is no longer in use. -// Otherwise these threads would keep the ThreadGroup alive forever. -public class PerThreadGroupPool<T extends ThreadPoolExecutor> { - private final WeakIdentityHashMap<ThreadGroup, WeakReference<T>> map = - WeakIdentityHashMap.make(); - - public static interface Create<T extends ThreadPoolExecutor> { - public T createThreadPool(ThreadGroup group); - } - - private PerThreadGroupPool() {} - - public static <T extends ThreadPoolExecutor> PerThreadGroupPool<T> make() { - return new PerThreadGroupPool<T>(); - } - - public synchronized T getThreadPoolExecutor(Create<T> create) { - // Find out if there's already an existing executor for the calling - // thread and reuse it. Otherwise, create a new one and store it in - // the executors map. If there is a SecurityManager, the group of - // System.getSecurityManager() is used, else the group of the calling - // thread. - SecurityManager s = System.getSecurityManager(); - ThreadGroup group = (s != null) ? s.getThreadGroup() : - Thread.currentThread().getThreadGroup(); - WeakReference<T> wr = map.get(group); - T executor = (wr == null) ? null : wr.get(); - if (executor == null) { - executor = create.createThreadPool(group); - executor.allowCoreThreadTimeOut(true); - map.put(group, new WeakReference<T>(executor)); - } - return executor; - } -}
--- a/jdk/src/share/classes/com/sun/jmx/mbeanserver/Repository.java Wed Oct 21 16:28:57 2009 +0200 +++ b/jdk/src/share/classes/com/sun/jmx/mbeanserver/Repository.java Wed Oct 21 17:33:18 2009 +0200 @@ -396,7 +396,7 @@ // Set domain to default if domain is empty and not already set if (dom.length() == 0) - name = ObjectName.valueOf(domain + name.toString()); + name = Util.newObjectName(domain + name.toString()); // Do we have default domain ? if (dom == domain) { // ES: OK (dom & domain are interned) @@ -573,7 +573,7 @@ // Pattern matching in the domain name (*, ?) final String dom2Match = name.getDomain(); for (String dom : domainTb.keySet()) { - if (Util.wildpathmatch(dom, dom2Match)) { + if (Util.wildmatch(dom, dom2Match)) { final Map<String,NamedObject> moiTb = domainTb.get(dom); if (allNames) result.addAll(moiTb.values());
--- a/jdk/src/share/classes/com/sun/jmx/mbeanserver/StandardMBeanIntrospector.java Wed Oct 21 16:28:57 2009 +0200 +++ b/jdk/src/share/classes/com/sun/jmx/mbeanserver/StandardMBeanIntrospector.java Wed Oct 21 17:33:18 2009 +0200 @@ -1,5 +1,5 @@ /* - * Copyright 2005-2008 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2005 Sun Microsystems, Inc. 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 @@ -35,7 +35,6 @@ import javax.management.MBeanAttributeInfo; import javax.management.MBeanException; import javax.management.MBeanOperationInfo; -import javax.management.ManagedOperation; import javax.management.NotCompliantMBeanException; import javax.management.NotificationBroadcaster; import javax.management.NotificationBroadcasterSupport; @@ -119,32 +118,22 @@ @Override MBeanAttributeInfo getMBeanAttributeInfo(String attributeName, - Method getter, Method setter) throws IntrospectionException { + Method getter, Method setter) { - String description = getAttributeDescription( - attributeName, "Attribute exposed for management", - getter, setter); - return new MBeanAttributeInfo(attributeName, description, - getter, 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 defaultDescription = "Operation exposed for management"; - String description = Introspector.descriptionForElement(operation); - if (description == null) - description = defaultDescription; - - int impact = MBeanOperationInfo.UNKNOWN; - ManagedOperation annot = operation.getAnnotation(ManagedOperation.class); - if (annot != null) - impact = annot.impact().getCode(); - - MBeanOperationInfo mboi = new MBeanOperationInfo(description, operation); - return new MBeanOperationInfo( - mboi.getName(), mboi.getDescription(), mboi.getSignature(), - mboi.getReturnType(), impact, mboi.getDescriptor()); + final String description = "Operation exposed for management"; + return new MBeanOperationInfo(description, operation); } @Override
--- a/jdk/src/share/classes/com/sun/jmx/mbeanserver/StandardMBeanSupport.java Wed Oct 21 16:28:57 2009 +0200 +++ b/jdk/src/share/classes/com/sun/jmx/mbeanserver/StandardMBeanSupport.java Wed Oct 21 17:33:18 2009 +0200 @@ -31,7 +31,6 @@ import javax.management.MBeanServer; import javax.management.NotCompliantMBeanException; import javax.management.ObjectName; -import javax.management.openmbean.MXBeanMappingFactory; /** * Base class for Standard MBeans. @@ -58,11 +57,11 @@ */ public <T> StandardMBeanSupport(T resource, Class<T> mbeanInterfaceType) throws NotCompliantMBeanException { - super(resource, mbeanInterfaceType, (MXBeanMappingFactory) null); + super(resource, mbeanInterfaceType); } @Override - MBeanIntrospector<Method> getMBeanIntrospector(MXBeanMappingFactory ignored) { + MBeanIntrospector<Method> getMBeanIntrospector() { return StandardMBeanIntrospector.getInstance(); } @@ -84,14 +83,13 @@ @Override public MBeanInfo getMBeanInfo() { MBeanInfo mbi = super.getMBeanInfo(); - Class<?> resourceClass = getWrappedObject().getClass(); - if (!getMBeanInterface().isInterface() || - StandardMBeanIntrospector.isDefinitelyImmutableInfo(resourceClass)) + 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(getWrappedObject()), + MBeanIntrospector.findNotifications(getResource()), mbi.getDescriptor()); } }
--- a/jdk/src/share/classes/com/sun/jmx/mbeanserver/Util.java Wed Oct 21 16:28:57 2009 +0200 +++ b/jdk/src/share/classes/com/sun/jmx/mbeanserver/Util.java Wed Oct 21 17:33:18 2009 +0200 @@ -25,8 +25,6 @@ package com.sun.jmx.mbeanserver; -import com.sun.jmx.defaults.JmxProperties; -import java.io.IOException; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; @@ -40,25 +38,18 @@ import java.util.Map; import java.util.Set; import java.util.SortedMap; -import java.util.SortedSet; import java.util.TreeMap; -import java.util.TreeSet; -import java.util.WeakHashMap; -import java.util.logging.Level; -import javax.management.MBeanServer; -import javax.management.MBeanServerDelegate; -import javax.management.MBeanServerFactory; -import javax.management.ObjectInstance; +import javax.management.MalformedObjectNameException; import javax.management.ObjectName; -import javax.management.loading.ClassLoaderRepository; -import static javax.management.namespace.JMXNamespaces.NAMESPACE_SEPARATOR; public class Util { - private final static int NAMESPACE_SEPARATOR_LENGTH = - NAMESPACE_SEPARATOR.length(); - public final static char[] ILLEGAL_MBEANSERVER_NAME_CHARS=";:*?". - toCharArray(); - + 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>(); @@ -89,10 +80,6 @@ return new LinkedHashMap<K, V>(); } - static <K, V> WeakHashMap<K, V> newWeakHashMap() { - return new WeakHashMap<K, V>(); - } - static <E> Set<E> newSet() { return new HashSet<E>(); } @@ -251,451 +238,4 @@ public static boolean wildmatch(String str, String pat) { return wildmatch(str,pat,0,str.length(),0,pat.length()); } - - /** - * Matches a string against a pattern, as a name space path. - * This is a special matching where * and ?? don't match //. - * The string is split in sub-strings separated by //, and the - * pattern is split in sub-patterns separated by //. Each sub-string - * is matched against its corresponding sub-pattern. - * so <elt-1>//<elt2>//...//<elt-n> matches <pat-1>//<pat-2>//...//<pat-q> - * only if n==q and for ( i = 1 => n) elt-i matches pat-i. - * - * In addition, if we encounter a pattern element which is exactly - * **, it can match any number of path-elements - but it must match at - * least one element. - * When we encounter such a meta-wildcard, we remember its position - * and the position in the string path, and we advance both the pattern - * and the string. Later, if we encounter a mismatch in pattern & string, - * we rewind the position in pattern to just after the meta-wildcard, - * and we backtrack the string to i+1 element after the position - * we had when we first encountered the meta-wildcard, i being the - * position when we last backtracked the string. - * - * The backtracking logic is an adaptation of the logic in wildmatch - * above. - * See test/javax/mangement/ObjectName/ApplyWildcardTest.java - * - * Note: this thing is called 'wild' - and that's for a reason ;-) - **/ - public static boolean wildpathmatch(String str, String pat) { - final int strlen = str.length(); - final int patlen = pat.length(); - int stri = 0; - int pati = 0; - - int starstri; // index for backtrack if "**" attempt fails - int starpati; // index for backtrack if "**" attempt fails - - starstri = starpati = -1; - - while (true) { - // System.out.println("pati="+pati+", stri="+stri); - final int strend = str.indexOf(NAMESPACE_SEPARATOR, stri); - final int patend = pat.indexOf(NAMESPACE_SEPARATOR, pati); - - // no // remaining in either string or pattern: simple wildmatch - // until end of string. - if (strend == -1 && patend == -1) { - // System.out.println("last sub pattern, last sub element..."); - // System.out.println("wildmatch("+str.substring(stri,strlen)+ - // ","+pat.substring(pati,patlen)+")"); - return wildmatch(str,pat,stri,strlen,pati,patlen); - } - - // no // remaining in string, but at least one remaining in - // pattern - // => no match - if (strend == -1) { - // System.out.println("pattern has more // than string..."); - return false; - } - - // strend is != -1, but patend might. - // detect wildcard ** - if (patend == pati+2 && pat.charAt(pati)=='*' && - pat.charAt(pati+1)=='*') { - // if we reach here we know that neither strend nor patend are - // equals to -1. - stri = strend + NAMESPACE_SEPARATOR_LENGTH; - pati = patend + NAMESPACE_SEPARATOR_LENGTH; - starpati = pati; // position just after **// in pattern - starstri = stri; // we eat 1 element in string, and remember - // the position for backtracking and eating - // one more element if needed. - // System.out.println("starpati="+pati); - continue; - } - - // This is a bit hacky: * can match // when // is at the end - // of the string, so we include the // delimiter in the pattern - // matching. Either we're in the middle of the path, so including - // // both at the end of the pattern and at the end of the string - // has no effect - match(*//,dfsd//) is equivalent to match(*,dfsd) - // or we're at the end of the pattern path, in which case - // including // at the end of the string will have the desired - // effect (provided that we detect the end of matching correctly, - // see further on). - // - final int endpat = - ((patend > -1)?patend+NAMESPACE_SEPARATOR_LENGTH:patlen); - final int endstr = - ((strend > -1)?strend+NAMESPACE_SEPARATOR_LENGTH:strlen); - - // if we reach the end of the pattern, or if elt-i & pat-i - // don't match, we have a mismatch. - - // Note: we know that strend != -1, therefore patend==-1 - // indicates a mismatch unless pattern can match - // a // at the end, and strend+2=strlen. - // System.out.println("wildmatch("+str.substring(stri,endstr)+","+ - // pat.substring(pati,endpat)+")"); - if (!wildmatch(str,pat,stri,endstr,pati,endpat)) { - - // System.out.println("nomatch"); - // if we have a mismatch and didn't encounter any meta-wildcard, - // we return false. String & pattern don't match. - if (starpati < 0) return false; - - // If we reach here, we had a meta-wildcard. - // We need to backtrack to the wildcard, and make it eat an - // additional string element. - // - stri = str.indexOf(NAMESPACE_SEPARATOR, starstri); - // System.out.println("eating one additional element? "+stri); - - // If there's no more elements to eat, string and pattern - // don't match => return false. - if (stri == -1) return false; - - // Backtrack to where we were when we last matched against - // the meta-wildcard, make it eat an additional path element, - // remember the new positions, and continue from there... - // - stri = stri + NAMESPACE_SEPARATOR_LENGTH; - starstri = stri; - pati = starpati; - // System.out.println("skiping to stri="+stri); - continue; - } - - // Here we know that strend > -1 but we can have patend == -1. - // - // So if we reach here, we know pat-i+//? has matched - // elt-i+// - // - // If patend==-1, we know that there was no delimiter - // at the end of the pattern, that we are at the last pattern, - // and therefore that pat-i has matched elt-i+// - // - // In that case we can consider that we have a match only if - // elt-i is also the last path element in the string, which is - // equivalent to saying that strend+2==strlen. - // - if (patend == -1 && starpati == -1) - return (strend+NAMESPACE_SEPARATOR_LENGTH==strlen); - - // patend != -1, or starpati > -1 so there remains something - // to match. - - // go to next pair: elt-(i+1) pat-(i+1); - stri = strend + NAMESPACE_SEPARATOR_LENGTH; - pati = (patend==-1)?pati:(patend + NAMESPACE_SEPARATOR_LENGTH); - } - } - - /** - * Returns true if the ObjectName's {@code domain} is selected by the - * given {@code pattern}. - */ - public static boolean isDomainSelected(String domain, String pattern) { - if (domain == null || pattern == null) - throw new IllegalArgumentException("null"); - return Util.wildpathmatch(domain,pattern); - } - - /** - * Filters a set of ObjectName according to a given pattern. - * - * @param pattern the pattern that the returned names must match. - * @param all the set of names to filter. - * @return a set of ObjectName from which non matching names - * have been removed. - */ - public static Set<ObjectName> filterMatchingNames(ObjectName pattern, - Set<ObjectName> all) { - // If no pattern, just return all names - if (pattern == null - || all.isEmpty() - || ObjectName.WILDCARD.equals(pattern)) - return all; - - // If there's a pattern, do the matching. - final Set<ObjectName> res = equivalentEmptySet(all); - for (ObjectName n : all) if (pattern.apply(n)) res.add(n); - return res; - } - - - /** - * Filters a set of ObjectInstance according to a given pattern. - * - * @param pattern the pattern that the returned names must match. - * @param all the set of instances to filter. - * @return a set of ObjectInstance from which non matching instances - * have been removed. - */ - public static Set<ObjectInstance> - filterMatchingInstances(ObjectName pattern, - Set<ObjectInstance> all) { - // If no pattern, just return all names - if (pattern == null - || all.isEmpty() - || ObjectName.WILDCARD.equals(pattern)) - return all; - - // If there's a pattern, do the matching. - final Set<ObjectInstance> res = equivalentEmptySet(all); - for (ObjectInstance n : all) { - if (n == null) continue; - if (pattern.apply(n.getObjectName())) - res.add(n); - } - return res; - } - - /** - * An abstract ClassLoaderRepository that contains a single class loader. - **/ - private final static class SingleClassLoaderRepository - implements ClassLoaderRepository { - private final ClassLoader singleLoader; - - SingleClassLoaderRepository(ClassLoader loader) { - this.singleLoader = loader; - } - - ClassLoader getSingleClassLoader() { - return singleLoader; - } - - private Class<?> loadClass(String className, ClassLoader loader) - throws ClassNotFoundException { - return Class.forName(className, false, loader); - } - - public Class<?> loadClass(String className) - throws ClassNotFoundException { - return loadClass(className, getSingleClassLoader()); - } - - public Class<?> loadClassWithout(ClassLoader exclude, - String className) throws ClassNotFoundException { - final ClassLoader loader = getSingleClassLoader(); - if (exclude != null && exclude.equals(loader)) - throw new ClassNotFoundException(className); - return loadClass(className, loader); - } - - public Class<?> loadClassBefore(ClassLoader stop, String className) - throws ClassNotFoundException { - return loadClassWithout(stop, className); - } - } - - /** - * Returns a ClassLoaderRepository that contains a single class loader. - * @param loader the class loader contained in the returned repository. - * @return a ClassLoaderRepository that contains the single loader. - */ - public static ClassLoaderRepository getSingleClassLoaderRepository( - final ClassLoader loader) { - return new SingleClassLoaderRepository(loader); - } - - /** - * Returns the name of the given MBeanServer that should be put in a - * permission you need. - * This corresponds to the - * {@code *[;mbeanServerName=<mbeanServerName>[;*]]} property - * embedded in the MBeanServerId attribute of the - * server's {@link MBeanServerDelegate}. - * - * @param server The MBean server - * @return the name of the MBeanServer, or "*" if the name couldn't be - * obtained, or {@value MBeanServerFactory#DEFAULT_MBEANSERVER_NAME} - * if there was no name. - */ - public static String getMBeanServerSecurityName(MBeanServer server) { - final String notfound = "*"; - try { - final String mbeanServerId = (String) - server.getAttribute(MBeanServerDelegate.DELEGATE_NAME, - "MBeanServerId"); - final String found = extractMBeanServerName(mbeanServerId); - if (found.length()==0) - return MBeanServerFactory.DEFAULT_MBEANSERVER_NAME; - return found; - } catch (Exception x) { - logshort("Failed to retrieve MBeanServerName for server, " + - "using \"*\"",x); - return notfound; - } - } - - /** - * Returns the name of the MBeanServer embedded in the given - * mbeanServerId. If the given mbeanServerId doesn't contain any name, - * an empty String is returned. - * The MBeanServerId is expected to be of the form: - * {@code *[;mbeanServerName=<mbeanServerName>[;*]]} - * @param mbeanServerId The MBean server ID - * @return the name of the MBeanServer if found, or "" if the name was - * not present in the mbeanServerId. - */ - public static String extractMBeanServerName(String mbeanServerId) { - if (mbeanServerId==null) return ""; - final String beginMarker=";mbeanServerName="; - final String endMarker=";"; - final int found = mbeanServerId.indexOf(beginMarker); - if (found < 0) return ""; - final int start = found + beginMarker.length(); - final int stop = mbeanServerId.indexOf(endMarker, start); - return mbeanServerId.substring(start, - (stop < 0 ? mbeanServerId.length() : stop)); - } - - /** - * Insert the given mbeanServerName into the given mbeanServerId. - * If mbeanServerName is null, empty, or equals to "-", the returned - * mbeanServerId will not contain any mbeanServerName. - * @param mbeanServerId The mbeanServerId in which to insert - * mbeanServerName - * @param mbeanServerName The mbeanServerName - * @return an mbeanServerId containing the given mbeanServerName - * @throws IllegalArgumentException if mbeanServerId already contains - * a different name, or if the given mbeanServerName is not valid. - */ - public static String insertMBeanServerName(String mbeanServerId, - String mbeanServerName) { - final String found = extractMBeanServerName(mbeanServerId); - if (found.length() > 0 && - found.equals(checkServerName(mbeanServerName))) - return mbeanServerId; - if (found.length() > 0 && !isMBeanServerNameUndefined(found)) - throw new IllegalArgumentException( - "MBeanServerName already defined"); - if (isMBeanServerNameUndefined(mbeanServerName)) - return mbeanServerId; - final String beginMarker=";mbeanServerName="; - return mbeanServerId+beginMarker+checkServerName(mbeanServerName); - } - - /** - * Returns true if the given mbeanServerName corresponds to an - * undefined MBeanServerName. - * The mbeanServerName is considered undefined if it is one of: - * {@code null} or {@value MBeanServerFactory#DEFAULT_MBEANSERVER_NAME}. - * @param mbeanServerName The mbeanServerName, as returned by - * {@link #extractMBeanServerName(String)}. - * @return true if the given name corresponds to one of the forms that - * denotes an undefined MBeanServerName. - */ - public static boolean isMBeanServerNameUndefined(String mbeanServerName) { - return mbeanServerName == null || - MBeanServerFactory.DEFAULT_MBEANSERVER_NAME.equals(mbeanServerName); - } - /** - * Check that the provided mbeanServername is syntactically valid. - * @param mbeanServerName An mbeanServerName, or {@code null}. - * @return mbeanServerName, or {@value - * MBeanServerFactory#DEFAULT_MBEANSERVER_NAME} if {@code mbeanServerName} - * is {@code null}. - * @throws IllegalArgumentException if mbeanServerName contains illegal - * characters, or is empty, or is {@code "-"}. - * Illegal characters are {@link #ILLEGAL_MBEANSERVER_NAME_CHARS}. - */ - public static String checkServerName(String mbeanServerName) { - if ("".equals(mbeanServerName)) - throw new IllegalArgumentException( - "\"\" is not a valid MBean server name"); - if ("-".equals(mbeanServerName)) - throw new IllegalArgumentException( - "\"-\" is not a valid MBean server name"); - if (isMBeanServerNameUndefined(mbeanServerName)) - return MBeanServerFactory.DEFAULT_MBEANSERVER_NAME; - for (char c : ILLEGAL_MBEANSERVER_NAME_CHARS) { - if (mbeanServerName.indexOf(c) >= 0) - throw new IllegalArgumentException( - "invalid character in MBeanServer name: "+c); - } - return mbeanServerName; - } - - /** - * Get the MBeanServer name that should be put in a permission you need. - * - * @param delegate The MBeanServerDelegate - * @return The MBeanServer name - or {@value - * MBeanServerFactory#DEFAULT_MBEANSERVER_NAME} if there was no name. - */ - public static String getMBeanServerSecurityName( - MBeanServerDelegate delegate) { - try { - final String serverName = delegate.getMBeanServerName(); - if (isMBeanServerNameUndefined(serverName)) - return MBeanServerFactory.DEFAULT_MBEANSERVER_NAME; - return serverName; - } catch (Exception x) { - logshort("Failed to retrieve MBeanServerName from delegate, " + - "using \"*\"",x); - return "*"; - } - } - - // Log the exception and its causes without logging the stack trace. - // Use with care - it is usually preferable to log the whole stack trace! - // We don't want to log the whole stack trace here: logshort() is - // called in those cases where the exception might not be abnormal. - private static void logshort(String msg, Throwable t) { - if (JmxProperties.MISC_LOGGER.isLoggable(Level.FINE)) { - StringBuilder toprint = new StringBuilder(msg); - do { - toprint.append("\nCaused By: ").append(String.valueOf(t)); - } while ((t=t.getCause())!=null); - JmxProperties.MISC_LOGGER.fine(toprint.toString()); - } - } - - public static <T> Set<T> cloneSet(Set<T> set) { - if (set instanceof SortedSet<?>) { - @SuppressWarnings("unchecked") - SortedSet<T> sset = (SortedSet<T>) set; - set = new TreeSet<T>(sset.comparator()); - set.addAll(sset); - } else - set = new HashSet<T>(set); - return set; - } - - public static <T> Set<T> equivalentEmptySet(Set<T> set) { - if (set instanceof SortedSet<?>) { - @SuppressWarnings("unchecked") - SortedSet<T> sset = (SortedSet<T>) set; - set = new TreeSet<T>(sset.comparator()); - } else - set = new HashSet<T>(); - return set; - } - - // This exception is used when wrapping a class that throws IOException - // in a class that doesn't. - // The typical example for this are JMXNamespaces, when the sub - // MBeanServer can be remote. - // - public static RuntimeException newRuntimeIOException(IOException io) { - final String msg = "Communication failed with underlying resource: "+ - io.getMessage(); - return new RuntimeException(msg,io); - } }
--- a/jdk/src/share/classes/com/sun/jmx/namespace/DomainInterceptor.java Wed Oct 21 16:28:57 2009 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,463 +0,0 @@ -/* - * Copyright 2008 Sun Microsystems, Inc. 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. Sun designates this - * particular file as subject to the "Classpath" exception as provided - * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, - * CA 95054 USA or visit www.sun.com if you need additional information or - * have any questions. - */ - -package com.sun.jmx.namespace; - -import com.sun.jmx.defaults.JmxProperties; -import com.sun.jmx.mbeanserver.Util; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.Queue; -import java.util.Set; -import java.util.logging.Level; -import java.util.logging.Logger; - -import javax.management.Attribute; -import javax.management.AttributeList; -import javax.management.InstanceNotFoundException; -import javax.management.ListenerNotFoundException; -import javax.management.MBeanPermission; -import javax.management.MBeanServerDelegate; -import javax.management.MBeanServerNotification; -import javax.management.Notification; -import javax.management.NotificationFilter; -import javax.management.NotificationListener; -import javax.management.ObjectInstance; -import javax.management.ObjectName; -import javax.management.QueryExp; -import javax.management.namespace.JMXDomain; - -/** - * A DomainInterceptor wraps a JMXDomain. - * <p><b> - * This API is a Sun internal API and is subject to changes without notice. - * </b></p> - * @since 1.7 - */ -public class DomainInterceptor extends HandlerInterceptor<JMXDomain> { - - // TODO: Ideally DomainInterceptor should be replaced by - // something at Repository level. - // The problem there will be that we may need to - // reinstantiate the 'queryPerformedByRepos' boolean - // [or we will need to wrap the repository in - // a 'RepositoryInterceptor'?] - // Also there's no real need for a DomainInterceptor to - // extend RewritingMBeanServerConnection. - - - /** - * A logger for this class. - **/ - private static final Logger LOG = JmxProperties.NAMESPACE_LOGGER; - - private final String domainName; - private volatile ObjectName ALL; - private final String serverName; - private volatile NotificationListener mbsListener; - - private static class PatternNotificationFilter - implements NotificationFilter { - - final ObjectName pattern; - public PatternNotificationFilter(ObjectName pattern) { - this.pattern = pattern==null?ObjectName.WILDCARD:pattern; - } - - public boolean isNotificationEnabled(Notification notification) { - if (!(notification instanceof MBeanServerNotification)) - return false; - final MBeanServerNotification mbsn = - (MBeanServerNotification) notification; - if (pattern.apply(mbsn.getMBeanName())) - return true; - return false; - } - - static final long serialVersionUID = 7409950927025262111L; - } - - /** - * Creates a new instance of NamespaceInterceptor - */ - public DomainInterceptor(String serverName, - JMXDomain handler, - String domainName) { - super(handler); - this.domainName = domainName; - this.serverName = serverName; - ALL = ObjectName.valueOf(domainName+":*"); - } - - @Override - public String toString() { - return this.getClass().getName()+"(parent="+serverName+ - ", domain="+this.domainName+")"; - } - - final void connectDelegate(final MBeanServerDelegate delegate) - throws InstanceNotFoundException { - final NotificationFilter filter = - new PatternNotificationFilter(getPatternFor(null)); - synchronized (this) { - if (mbsListener == null) { - mbsListener = new NotificationListener() { - public void handleNotification(Notification notification, - Object handback) { - if (filter.isNotificationEnabled(notification)) - delegate.sendNotification(notification); - } - }; - } - } - - getHandlerInterceptorMBean(). - addMBeanServerNotificationListener(mbsListener, filter); - } - - final void disconnectDelegate() - throws InstanceNotFoundException, ListenerNotFoundException { - final NotificationListener l; - synchronized (this) { - l = mbsListener; - if (l == null) return; - mbsListener = null; - } - getHandlerInterceptorMBean().removeMBeanServerNotificationListener(l); - } - - public final void addPostRegisterTask(Queue<Runnable> queue, - final MBeanServerDelegate delegate) { - if (queue == null) - throw new IllegalArgumentException("task queue must not be null"); - final Runnable task1 = new Runnable() { - public void run() { - try { - connectDelegate(delegate); - } catch (Exception x) { - throw new UnsupportedOperationException( - "notification forwarding",x); - } - } - }; - queue.add(task1); - } - - public final void addPostDeregisterTask(Queue<Runnable> queue, - final MBeanServerDelegate delegate) { - if (queue == null) - throw new IllegalArgumentException("task queue must not be null"); - final Runnable task1 = new Runnable() { - public void run() { - try { - disconnectDelegate(); - } catch (Exception x) { - throw new UnsupportedOperationException( - "notification forwarding",x); - } - } - }; - queue.add(task1); - } - - // No name conversion for JMXDomains... - // Throws IllegalArgumentException if targetName.getDomain() is not - // in the domain handled. - // - @Override - protected ObjectName toSource(ObjectName targetName) { - if (targetName == null) return null; - if (targetName.isDomainPattern()) return targetName; - final String targetDomain = targetName.getDomain(); - - // TODO: revisit this. RuntimeOperationsException may be better? - // - if (!targetDomain.equals(domainName)) - throw new IllegalArgumentException(targetName.toString()); - return targetName; - } - - // No name conversion for JMXDomains... - @Override - protected ObjectName toTarget(ObjectName sourceName) { - return sourceName; - } - - - - /** - * No rewriting: always return sources - stripping instances for which - * the caller doesn't have permissions. - **/ - @Override - Set<ObjectInstance> processOutputInstances(Set<ObjectInstance> sources) { - if (sources == null || sources.isEmpty() || !checkOn()) - return sources; - final Set<ObjectInstance> res = Util.equivalentEmptySet(sources); - for (ObjectInstance o : sources) { - if (checkQuery(o.getObjectName(), "queryMBeans")) - res.add(o); - } - return res; - } - - - /** - * No rewriting: always return sourceNames - stripping names for which - * the caller doesn't have permissions. - **/ - @Override - Set<ObjectName> processOutputNames(Set<ObjectName> sourceNames) { - if (sourceNames == null || sourceNames.isEmpty() || !checkOn()) - return sourceNames; - final Set<ObjectName> res = Util.equivalentEmptySet(sourceNames); - for (ObjectName o : sourceNames) { - if (checkQuery(o, "queryNames")) - res.add(o); - } - return res; - } - - /** No rewriting: always return source **/ - @Override - ObjectInstance processOutputInstance(ObjectInstance source) { - return source; - } - - @Override - public Set<ObjectName> queryNames(ObjectName name, QueryExp query) { - try { - // We don't trust the wrapped JMXDomain... - final ObjectName pattern = getPatternFor(name); - final Set<ObjectName> res = super.queryNames(pattern,query); - return Util.filterMatchingNames(pattern,res); - } catch (Exception x) { - if (LOG.isLoggable(Level.FINE)) - LOG.fine("Unexpected exception raised in queryNames: "+x); - LOG.log(Level.FINEST,"Unexpected exception raised in queryNames",x); - return Collections.emptySet(); - } - } - - // Compute a new pattern which is a sub pattern of 'name' but only selects - // the MBeans in domain 'domainName' - // When we reach here, it has been verified that 'name' matches our domain - // name (done by DomainDispatchInterceptor) - private ObjectName getPatternFor(final ObjectName name) { - if (name == null) return ALL; - if (name.getDomain().equals(domainName)) return name; - return name.withDomain(domainName); - } - - @Override - public Set<ObjectInstance> queryMBeans(ObjectName name, QueryExp query) { - try { - // We don't trust the wrapped JMXDomain... - final ObjectName pattern = getPatternFor(name); - final Set<ObjectInstance> res = super.queryMBeans(pattern,query); - return Util.filterMatchingInstances(pattern,res); - } catch (Exception x) { - if (LOG.isLoggable(Level.FINE)) - LOG.fine("Unexpected exception raised in queryNames: "+x); - LOG.log(Level.FINEST,"Unexpected exception raised in queryNames",x); - return Collections.emptySet(); - } - } - - @Override - public String getDefaultDomain() { - return domainName; - } - - @Override - public String[] getDomains() { - return new String[] {domainName}; - } - - // We call getMBeanCount() on the namespace rather than on the - // source server in order to avoid counting MBeans which are not - // in the domain. - @Override - public Integer getMBeanCount() { - return getHandlerInterceptorMBean().getMBeanCount(); - } - - private boolean checkOn() { - final SecurityManager sm = System.getSecurityManager(); - return (sm != null); - } - - // - // Implements permission checks. - // - @Override - void check(ObjectName routingName, String member, String action) { - if (!checkOn()) return; - final String act = (action==null)?"-":action; - if("queryMBeans".equals(act) || "queryNames".equals(act)) { - // This is tricky. check with 3 parameters is called - // by queryNames/queryMBeans before performing the query. - // At this point we must check with no class name. - // Therefore we pass a className of "-". - // The filtering will be done later - processOutputNames and - // processOutputInstance will call checkQuery. - // - check(routingName, "-", "-", act); - } else { - // This is also tricky: - // passing null here will cause check to retrieve the classname, - // if needed. - check(routingName, null, member, act); - } - } - - // - // Implements permission checks. - // - @Override - void checkCreate(ObjectName routingName, String className, String action) { - if (!checkOn()) return; - check(routingName,className,"-",action); - } - - // - // Implements permission checks. - // - void check(ObjectName routingName, String className, String member, - String action) { - if (!checkOn()) return; - final MBeanPermission perm; - - final String act = (action==null)?"-":action; - if ("getDomains".equals(act)) { // ES: OK - perm = new MBeanPermission(serverName,"-",member, - routingName,act); - } else { - final String clazz = - (className==null)?getClassName(routingName):className; - perm = new MBeanPermission(serverName,clazz,member, - routingName,act); - } - final SecurityManager sm = System.getSecurityManager(); - if (sm != null) - sm.checkPermission(perm); - } - - String getClassName(ObjectName routingName) { - if (routingName == null || routingName.isPattern()) return "-"; - try { - return getHandlerInterceptorMBean().getSourceServer(). - getObjectInstance(routingName).getClassName(); - } catch (InstanceNotFoundException ex) { - LOG.finest("Can't get class name for "+routingName+ - ", using \"-\". Cause is: "+ex); - return "-"; - } - } - - // - // Implements permission filters for attributes... - // - @Override - AttributeList checkAttributes(ObjectName routingName, - AttributeList attributes, String action) { - if (!checkOn()) return attributes; - final String className = getClassName(routingName); - check(routingName,className,"-",action); - if (attributes == null || attributes.isEmpty()) return attributes; - final AttributeList res = new AttributeList(); - for (Attribute at : attributes.asList()) { - try { - check(routingName,className,at.getName(),action); - res.add(at); - } catch (SecurityException x) { // DLS: OK - continue; - } - } - return res; - } - - // - // Implements permission filters for attributes... - // - @Override - String[] checkAttributes(ObjectName routingName, String[] attributes, - String action) { - if (!checkOn()) return attributes; - final String className = getClassName(routingName); - check(routingName,className,"-",action); - if (attributes == null || attributes.length==0) return attributes; - final List<String> res = new ArrayList<String>(attributes.length); - for (String at : attributes) { - try { - check(routingName,className,at,action); - res.add(at); - } catch (SecurityException x) { // DLS: OK - continue; - } - } - return res.toArray(new String[res.size()]); - } - - // - // Implements permission filters for domains... - // - @Override - String[] checkDomains(String[] domains, String action) { - if (domains == null || domains.length==0 || !checkOn()) - return domains; - int count=0; - for (int i=0;i<domains.length;i++) { - try { - check(ObjectName.valueOf(domains[i]+":x=x"),"-", - "-","getDomains"); - } catch (SecurityException x) { // DLS: OK - count++; - domains[i]=null; - } - } - if (count == 0) return domains; - final String[] res = new String[domains.length-count]; - count = 0; - for (int i=0;i<domains.length;i++) - if (domains[i]!=null) res[count++]=domains[i]; - return res; - } - - // - // Implements permission filters for queries... - // - @Override - boolean checkQuery(ObjectName routingName, String action) { - try { - final String className = getClassName(routingName); - check(routingName,className,"-",action); - return true; - } catch (SecurityException x) { // DLS: OK - return false; - } - } -}
--- a/jdk/src/share/classes/com/sun/jmx/namespace/HandlerInterceptor.java Wed Oct 21 16:28:57 2009 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,734 +0,0 @@ -/* - * Copyright 2008 Sun Microsystems, Inc. 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. Sun designates this - * particular file as subject to the "Classpath" exception as provided - * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, - * CA 95054 USA or visit www.sun.com if you need additional information or - * have any questions. - */ - -package com.sun.jmx.namespace; - - -import com.sun.jmx.defaults.JmxProperties; -import com.sun.jmx.interceptor.MBeanServerInterceptor; - -import com.sun.jmx.mbeanserver.Util; -import java.io.IOException; -import java.io.ObjectInputStream; -import java.util.Set; -import java.util.logging.Level; -import java.util.logging.Logger; - -import javax.management.Attribute; -import javax.management.AttributeList; -import javax.management.AttributeNotFoundException; -import javax.management.InstanceAlreadyExistsException; -import javax.management.InstanceNotFoundException; -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.RuntimeOperationsException; -import javax.management.loading.ClassLoaderRepository; -import javax.management.namespace.JMXNamespace; - -/** - * This interceptor wraps a JMXNamespace, and performs - * {@code ObjectName} rewriting. {@code HandlerInterceptor} are - * created and managed by a {@link NamespaceDispatchInterceptor} or a - * {@link DomainDispatchInterceptor}. - * <p><b> - * This API is a Sun internal API and is subject to changes without notice. - * </b></p> - * @since 1.7 - */ -public abstract class HandlerInterceptor<T extends JMXNamespace> - extends RoutingMBeanServerConnection<MBeanServer> - implements MBeanServerInterceptor { - - /** - * A logger for this class. - **/ - private static final Logger LOG = JmxProperties.NAMESPACE_LOGGER; - - // The wrapped JMXNamespace - private final T handler; - - /** - * Creates a new instance of HandlerInterceptor - */ - public HandlerInterceptor(T handler) { - if (handler == null) throw new IllegalArgumentException("null"); - this.handler = handler; - } - - // - // The {@code source} connection is a connection to the MBeanServer - // that contains the actual MBeans. - // In the case of cascading, that would be a connection to the sub - // agent. Practically, this is JMXNamespace.getSourceServer(); - // - @Override - protected MBeanServer source() { - return handler.getSourceServer(); - } - - // The MBeanServer on which getClassLoader / getClassLoaderFor - // will be called. - // The NamespaceInterceptor overrides this method - so that it - // getClassLoader / getClassLoaderFor don't trigger the loop - // detection mechanism. - // - MBeanServer getServerForLoading() { - return source(); - } - - // The namespace or domain handler - this either a JMXNamespace or a - // a JMXDomain - T getHandlerInterceptorMBean() { - return handler; - } - - // If the underlying JMXNamespace throws an IO, the IO will be - // wrapped in a RuntimeOperationsException. - RuntimeException handleIOException(IOException x,String fromMethodName, - Object... params) { - // Must do something here? - if (LOG.isLoggable(Level.FINEST)) { - LOG.finest("IO Exception in "+fromMethodName+": "+x+ - " - "+" rethrowing as RuntimeOperationsException."); - } - throw new RuntimeOperationsException( - Util.newRuntimeIOException(x)); - } - - // From MBeanServerConnection: catch & handles IOException - @Override - public AttributeList getAttributes(ObjectName name, String[] attributes) - throws InstanceNotFoundException, ReflectionException { - try { - final String[] authorized = - checkAttributes(name,attributes,"getAttribute"); - final AttributeList attrList = - super.getAttributes(name,authorized); - return attrList; - } catch (IOException ex) { - throw handleIOException(ex,"getAttributes",name,attributes); - } - } - - // From MBeanServer - public ClassLoader getClassLoaderFor(ObjectName mbeanName) - throws InstanceNotFoundException { - final ObjectName sourceName = toSourceOrRuntime(mbeanName); - try { - check(mbeanName,null,"getClassLoaderFor"); - return getServerForLoading().getClassLoaderFor(sourceName); - } catch (RuntimeException ex) { - throw makeCompliantRuntimeException(ex); - } - } - - - // From MBeanServer - public ClassLoader getClassLoader(ObjectName loaderName) - throws InstanceNotFoundException { - final ObjectName sourceName = toSourceOrRuntime(loaderName); - try { - check(loaderName,null,"getClassLoader"); - return getServerForLoading().getClassLoader(sourceName); - } catch (RuntimeException ex) { - throw makeCompliantRuntimeException(ex); - } - } - - // From MBeanServer - public ObjectInstance registerMBean(Object object, ObjectName name) - throws InstanceAlreadyExistsException, MBeanRegistrationException, - NotCompliantMBeanException { - final ObjectName sourceName = newSourceMBeanName(name); - try { - checkCreate(name,object.getClass().getName(),"registerMBean"); - return processOutputInstance( - source().registerMBean(object,sourceName)); - } catch (RuntimeException ex) { - throw makeCompliantRuntimeException(ex); - } - } - - // From MBeanServerConnection: catch & handles IOException - @Override - public void removeNotificationListener(ObjectName name, ObjectName listener) - throws InstanceNotFoundException, ListenerNotFoundException { - try { - check(name,null,"removeNotificationListener"); - super.removeNotificationListener(name,listener); - } catch (IOException ex) { - throw handleIOException(ex,"removeNotificationListener",name,listener); - } - } - - // From MBeanServerConnection: catch & handles IOException - @Override - public String getDefaultDomain() { - try { - return super.getDefaultDomain(); - } catch (IOException ex) { - throw handleIOException(ex,"getDefaultDomain"); - } - } - - // From MBeanServerConnection: catch & handles IOException - @Override - public String[] getDomains() { - try { - check(null,null,"getDomains"); - final String[] domains = super.getDomains(); - return checkDomains(domains,"getDomains"); - } catch (IOException ex) { - throw handleIOException(ex,"getDomains"); - } - } - - // From MBeanServerConnection: catch & handles IOException - @Override - public Integer getMBeanCount() { - try { - return super.getMBeanCount(); - } catch (IOException ex) { - throw handleIOException(ex,"getMBeanCount"); - } - } - - // From MBeanServerConnection: catch & handles IOException - @Override - public void setAttribute(ObjectName name, Attribute attribute) - throws InstanceNotFoundException, AttributeNotFoundException, - InvalidAttributeValueException, MBeanException, - ReflectionException { - try { - check(name, - (attribute==null?null:attribute.getName()), - "setAttribute"); - super.setAttribute(name,attribute); - } catch (IOException ex) { - throw handleIOException(ex,"setAttribute",name, attribute); - } - } - - // From MBeanServerConnection: catch & handles IOException - @Override - public Set<ObjectName> queryNames(ObjectName name, QueryExp query) { - if (name == null) name=ObjectName.WILDCARD; - try { - checkPattern(name,null,"queryNames"); - return super.queryNames(name,query); - } catch (IOException ex) { - throw handleIOException(ex,"queryNames",name, query); - } - } - - // From MBeanServerConnection: catch & handles IOException - @Override - public Set<ObjectInstance> queryMBeans(ObjectName name, QueryExp query) { - if (name == null) name=ObjectName.WILDCARD; - try { - checkPattern(name,null,"queryMBeans"); - return super.queryMBeans(name,query); - } catch (IOException ex) { - throw handleIOException(ex,"queryMBeans",name, query); - } - } - - // From MBeanServerConnection: catch & handles IOException - @Override - public boolean isInstanceOf(ObjectName name, String className) - throws InstanceNotFoundException { - try { - check(name, null, "isInstanceOf"); - return super.isInstanceOf(name, className); - } catch (IOException ex) { - throw handleIOException(ex,"isInstanceOf",name, className); - } - } - - // From MBeanServerConnection: catch & handles IOException - @Override - public ObjectInstance createMBean(String className, ObjectName name) - throws ReflectionException, InstanceAlreadyExistsException, - MBeanRegistrationException, MBeanException, - NotCompliantMBeanException { - try { - checkCreate(name, className, "instantiate"); - checkCreate(name, className, "registerMBean"); - return super.createMBean(className, name); - } catch (IOException ex) { - throw handleIOException(ex,"createMBean",className, name); - } - } - - // From MBeanServerConnection: catch & handles IOException - @Override - public ObjectInstance createMBean(String className, ObjectName name, - ObjectName loaderName) - throws ReflectionException, InstanceAlreadyExistsException, - MBeanRegistrationException, MBeanException, - NotCompliantMBeanException, InstanceNotFoundException { - try { - checkCreate(name, className, "instantiate"); - checkCreate(name, className, "registerMBean"); - return super.createMBean(className, name, loaderName); - } catch (IOException ex) { - throw handleIOException(ex,"createMBean",className, name, loaderName); - } - } - - // From MBeanServerConnection: catch & handles IOException - @Override - public Object getAttribute(ObjectName name, String attribute) - throws MBeanException, AttributeNotFoundException, - InstanceNotFoundException, ReflectionException { - try { - check(name, attribute, "getAttribute"); - return super.getAttribute(name, attribute); - } catch (IOException ex) { - throw handleIOException(ex,"getAttribute",name, attribute); - } - } - - // From MBeanServerConnection: catch & handles IOException - @Override - public void removeNotificationListener(ObjectName name, ObjectName listener, - NotificationFilter filter, Object handback) - throws InstanceNotFoundException, ListenerNotFoundException { - try { - check(name,null,"removeNotificationListener"); - super.removeNotificationListener(name, listener, filter, handback); - } catch (IOException ex) { - throw handleIOException(ex,"removeNotificationListener",name, - listener, filter, handback); - } - } - - // From MBeanServerConnection: catch & handles IOException - @Override - public void removeNotificationListener(ObjectName name, - NotificationListener listener, NotificationFilter filter, - Object handback) - throws InstanceNotFoundException, ListenerNotFoundException { - try { - check(name,null,"removeNotificationListener"); - super.removeNotificationListener(name, listener, filter, handback); - } catch (IOException ex) { - throw handleIOException(ex,"removeNotificationListener",name, - listener, filter, handback); - } - } - - // From MBeanServerConnection: catch & handles IOException - @Override - public void removeNotificationListener(ObjectName name, - NotificationListener listener) - throws InstanceNotFoundException, ListenerNotFoundException { - try { - check(name,null,"removeNotificationListener"); - super.removeNotificationListener(name, listener); - } catch (IOException ex) { - throw handleIOException(ex,"removeNotificationListener",name, - listener); - } - } - - // From MBeanServerConnection: catch & handles IOException - @Override - public void addNotificationListener(ObjectName name, - NotificationListener listener, NotificationFilter filter, - Object handback) throws InstanceNotFoundException { - try { - check(name,null,"addNotificationListener"); - super.addNotificationListener(name, listener, filter, handback); - } catch (IOException ex) { - throw handleIOException(ex,"addNotificationListener",name, - listener, filter, handback); - } - } - - // From MBeanServerConnection: catch & handles IOException - @Override - public void addNotificationListener(ObjectName name, ObjectName listener, - NotificationFilter filter, Object handback) - throws InstanceNotFoundException { - try { - check(name,null,"addNotificationListener"); - super.addNotificationListener(name, listener, filter, handback); - } catch (IOException ex) { - throw handleIOException(ex,"addNotificationListener",name, - listener, filter, handback); - } - } - - // From MBeanServerConnection: catch & handles IOException - @Override - public boolean isRegistered(ObjectName name) { - try { - return super.isRegistered(name); - } catch (IOException ex) { - throw handleIOException(ex,"isRegistered",name); - } - } - - // From MBeanServerConnection: catch & handles IOException - @Override - public void unregisterMBean(ObjectName name) - throws InstanceNotFoundException, MBeanRegistrationException { - try { - check(name, null, "unregisterMBean"); - super.unregisterMBean(name); - } catch (IOException ex) { - throw handleIOException(ex,"unregisterMBean",name); - } - } - - // From MBeanServerConnection: catch & handles IOException - @Override - public MBeanInfo getMBeanInfo(ObjectName name) - throws InstanceNotFoundException, IntrospectionException, - ReflectionException { - try { - check(name, null, "getMBeanInfo"); - return super.getMBeanInfo(name); - } catch (IOException ex) { - throw handleIOException(ex,"getMBeanInfo",name); - } - } - - // From MBeanServerConnection: catch & handles IOException - @Override - public ObjectInstance getObjectInstance(ObjectName name) - throws InstanceNotFoundException { - try { - check(name, null, "getObjectInstance"); - return super.getObjectInstance(name); - } catch (IOException ex) { - throw handleIOException(ex,"getObjectInstance",name); - } - } - - // From MBeanServerConnection: catch & handles IOException - @Override - public ObjectInstance createMBean(String className, ObjectName name, - Object[] params, String[] signature) - throws ReflectionException, InstanceAlreadyExistsException, - MBeanRegistrationException, MBeanException, - NotCompliantMBeanException { - try { - checkCreate(name, className, "instantiate"); - checkCreate(name, className, "registerMBean"); - return super.createMBean(className, name, params, signature); - } catch (IOException ex) { - throw handleIOException(ex,"createMBean",className, name, - params, signature); - } - } - - // From MBeanServerConnection: catch & handles IOException - @Override - public ObjectInstance createMBean(String className, ObjectName name, - ObjectName loaderName, Object[] params, String[] signature) - throws ReflectionException, InstanceAlreadyExistsException, - MBeanRegistrationException, MBeanException, - NotCompliantMBeanException, InstanceNotFoundException { - try { - checkCreate(name, className, "instantiate"); - checkCreate(name, className, "registerMBean"); - return super.createMBean(className, name, loaderName, params, - signature); - } catch (IOException ex) { - throw handleIOException(ex,"createMBean",className, name,loaderName, - params, signature); - } - } - - // From MBeanServerConnection: catch & handles IOException - @Override - public AttributeList setAttributes(ObjectName name,AttributeList attributes) - throws InstanceNotFoundException, ReflectionException { - try { - final AttributeList authorized = - checkAttributes(name, attributes, "setAttribute"); - return super.setAttributes(name, authorized); - } catch (IOException ex) { - throw handleIOException(ex,"setAttributes",name, attributes); - } - } - - // From MBeanServerConnection: catch & handles IOException - @Override - public Object invoke(ObjectName name, String operationName, Object[] params, - String[] signature) - throws InstanceNotFoundException, MBeanException, ReflectionException { - try { - check(name, operationName, "invoke"); - return super.invoke(name, operationName, params, signature); - } catch (IOException ex) { - throw handleIOException(ex,"invoke",name, operationName, - params, signature); - } - } - - // - // These methods are inherited from MBeanServer.... - // - - /** - * This method should never be called. - * Throws UnsupportedOperationException. - */ - public Object instantiate(String className) - throws ReflectionException, MBeanException { - if (LOG.isLoggable(Level.FINE)) - LOG.fine("call to unsupported instantiate method: " + - "trowing UnsupportedOperationException"); - throw new UnsupportedOperationException("Not applicable."); - } - - /** - * This method should never be called. - * Throws UnsupportedOperationException. - */ - public Object instantiate(String className, ObjectName loaderName) - throws ReflectionException, MBeanException, - InstanceNotFoundException { - if (LOG.isLoggable(Level.FINE)) - LOG.fine("call to unsupported method: instantiate(...) -" + - "throwing UnsupportedOperationException"); - throw new UnsupportedOperationException("Not applicable."); - } - - /** - * This method should never be called. - * Throws UnsupportedOperationException. - */ - public Object instantiate(String className, Object[] params, - String[] signature) throws ReflectionException, MBeanException { - if (LOG.isLoggable(Level.FINE)) - LOG.fine("call to unsupported method: instantiate(...) -" + - "throwing UnsupportedOperationException"); - throw new UnsupportedOperationException("Not applicable."); - } - - /** - * This method should never be called. - * Throws UnsupportedOperationException. - */ - public Object instantiate(String className, ObjectName loaderName, - Object[] params, String[] signature) - throws ReflectionException, MBeanException, - InstanceNotFoundException { - if (LOG.isLoggable(Level.FINE)) - LOG.fine("call to unsupported method: instantiate(...) -" + - "throwing UnsupportedOperationException"); - throw new UnsupportedOperationException("Not applicable."); - } - - /** - * This method should never be called. - * Throws UnsupportedOperationException. - */ - @Deprecated - public ObjectInputStream deserialize(ObjectName name, byte[] data) - throws InstanceNotFoundException, OperationsException { - if (LOG.isLoggable(Level.FINE)) - LOG.fine("call to unsupported method: deserialize(...) -" + - "throwing UnsupportedOperationException"); - throw new UnsupportedOperationException("Not applicable."); - } - - /** - * This method should never be called. - * Throws UnsupportedOperationException. - */ - @Deprecated - public ObjectInputStream deserialize(String className, byte[] data) - throws OperationsException, ReflectionException { - if (LOG.isLoggable(Level.FINE)) - LOG.fine("call to unsupported method: deserialize(...) -" + - "throwing UnsupportedOperationException"); - throw new UnsupportedOperationException("Not applicable."); - } - - /** - * This method should never be called. - * Throws UnsupportedOperationException. - */ - @Deprecated - public ObjectInputStream deserialize(String className, - ObjectName loaderName, byte[] data) - throws InstanceNotFoundException, OperationsException, - ReflectionException { - if (LOG.isLoggable(Level.FINE)) - LOG.fine("call to unsupported method: deserialize(...) -" + - "throwing UnsupportedOperationException"); - throw new UnsupportedOperationException("Not applicable."); - } - - /** - * This method should never be called. - * Throws UnsupportedOperationException. - */ - public ClassLoaderRepository getClassLoaderRepository() { - if (LOG.isLoggable(Level.FINE)) - LOG.fine("call to unsupported method: getClassLoaderRepository() -" + - "throwing UnsupportedOperationException"); - throw new UnsupportedOperationException("Not applicable."); - } - - static RuntimeException newUnsupportedException(String namespace) { - return new RuntimeOperationsException( - new UnsupportedOperationException( - "Not supported in this namespace: "+namespace)); - } - - /** - * A result might be excluded for security reasons. - */ - @Override - boolean excludesFromResult(ObjectName targetName, String queryMethod) { - return !checkQuery(targetName, queryMethod); - } - - - //---------------------------------------------------------------------- - // Hooks for checking permissions - //---------------------------------------------------------------------- - - /** - * This method is a hook to implement permission checking in subclasses. - * A subclass may override this method and throw a {@link - * SecurityException} if the permission is denied. - * - * @param routingName The name of the MBean in the enclosing context. - * This is of the form {@code <namespace>//<ObjectName>}. - * @param member The {@link - * javax.management.namespace.JMXNamespacePermission#getMember member} - * name. - * @param action The {@link - * javax.management.namespace.JMXNamespacePermission#getActions action} - * name. - * @throws SecurityException if the caller doesn't have the permission - * to perform the given action on the MBean pointed to - * by routingName. - */ - abstract void check(ObjectName routingName, - String member, String action); - - // called in createMBean and registerMBean - abstract void checkCreate(ObjectName routingName, String className, - String action); - - /** - * This is a hook to implement permission checking in subclasses. - * - * Checks that the caller has sufficient permission for returning - * information about {@code sourceName} in {@code action}. - * - * Subclass may override this method and return false if the caller - * doesn't have sufficient permissions. - * - * @param routingName The name of the MBean to include or exclude from - * the query, expressed in the enclosing context. - * This is of the form {@code <namespace>//<ObjectName>}. - * @param action one of "queryNames" or "queryMBeans" - * @return true if {@code sourceName} can be returned. - */ - abstract boolean checkQuery(ObjectName routingName, String action); - - /** - * This method is a hook to implement permission checking in subclasses. - * - * @param routingName The name of the MBean in the enclosing context. - * This is of the form {@code <namespace>//<ObjectName>}. - * @param attributes The list of attributes to check permission for. - * @param action one of "getAttribute" or "setAttribute" - * @return The list of attributes for which the callers has the - * appropriate {@link - * javax.management.namespace.JMXNamespacePermission}. - * @throws SecurityException if the caller doesn't have the permission - * to perform {@code action} on the MBean pointed to by routingName. - */ - abstract String[] checkAttributes(ObjectName routingName, - String[] attributes, String action); - - /** - * This method is a hook to implement permission checking in subclasses. - * - * @param routingName The name of the MBean in the enclosing context. - * This is of the form {@code <namespace>//<ObjectName>}. - * @param attributes The list of attributes to check permission for. - * @param action one of "getAttribute" or "setAttribute" - * @return The list of attributes for which the callers has the - * appropriate {@link - * javax.management.namespace.JMXNamespacePermission}. - * @throws SecurityException if the caller doesn't have the permission - * to perform {@code action} on the MBean pointed to by routingName. - */ - abstract AttributeList checkAttributes(ObjectName routingName, - AttributeList attributes, String action); - - /** - * This method is a hook to implement permission checking in subclasses. - * Checks that the caller as the necessary permissions to view the - * given domain. If not remove the domains for which the caller doesn't - * have permission from the list. - * <p> - * By default, this method always returns {@code domains} - * - * @param domains The domains to return. - * @param action "getDomains" - * @return a filtered list of domains. - */ - String[] checkDomains(String[] domains, String action) { - return domains; - } - - // A priori check for queryNames/queryMBeans/ - void checkPattern(ObjectName routingPattern, - String member, String action) { - // pattern is checked only at posteriori by checkQuery. - // checking it a priori usually doesn't work, because ObjectName.apply - // does not work between two patterns. - // We only check that we have the permission requested for 'action'. - check(null,null,action); - } - - - -}
--- a/jdk/src/share/classes/com/sun/jmx/namespace/NamespaceInterceptor.java Wed Oct 21 16:28:57 2009 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,220 +0,0 @@ -/* - * Copyright 2008 Sun Microsystems, Inc. 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. Sun designates this - * particular file as subject to the "Classpath" exception as provided - * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, - * CA 95054 USA or visit www.sun.com if you need additional information or - * have any questions. - */ -package com.sun.jmx.namespace; - -import java.util.ArrayList; -import java.util.List; - -import javax.management.Attribute; -import javax.management.AttributeList; -import javax.management.MBeanServer; -import javax.management.ObjectName; -import javax.management.namespace.JMXNamespace; -import javax.management.namespace.JMXNamespacePermission; - -/** - * A NamespaceInterceptor wraps a JMXNamespace, performing - * ObjectName rewriting. - * <p><b> - * This API is a Sun internal API and is subject to changes without notice. - * </b></p> - * @since 1.7 - */ -public class NamespaceInterceptor extends HandlerInterceptor<JMXNamespace> { - - - // The target name space in which the NamepsaceHandler is mounted. - private final String targetNs; - - private final String serverName; - - private final ObjectNameRouter proc; - - /** - * Creates a new instance of NamespaceInterceptor - */ - public NamespaceInterceptor( - String serverName, - JMXNamespace handler, - String targetNamespace) { - super(handler); - this.serverName = serverName; - this.targetNs = - ObjectNameRouter.normalizeNamespacePath(targetNamespace, - true, true, false); - proc = new ObjectNameRouter(targetNamespace, ""); - } - - @Override - public String toString() { - return this.getClass().getName()+"(parent="+serverName+ - ", namespace="+this.targetNs+")"; - } - - /** - * This method will send a probe to detect self-linking name spaces. - * A self linking namespace is a namespace that links back directly - * on itslef. Calling a method on such a name space always results - * in an infinite loop going through: - * [1]MBeanServer -> [2]NamespaceDispatcher -> [3]NamespaceInterceptor - * [4]JMXNamespace -> { network // or cd // or ... } -> [5]MBeanServer - * with exactly the same request than [1]... - * - * The namespace interceptor [2] tries to detect such condition the - * *first time* that the connection is used. It does so by setting - * a flag, and sending a queryNames() through the name space. If the - * queryNames comes back, it knows that there's a loop. - * - * The DynamicProbe interface can also be used by a Sun JMXNamespace - * implementation to request the emission of a probe at any time - * (see JMXRemoteNamespace implementation). - */ - private MBeanServer connection() { - final MBeanServer c = super.source(); - if (c != null) return c; - // should not come here - throw new NullPointerException("getMBeanServerConnection"); - } - - - @Override - protected MBeanServer source() { - return connection(); - } - - @Override - protected MBeanServer getServerForLoading() { - // don't want to send probe on getClassLoader/getClassLoaderFor - return super.source(); - } - - @Override - protected ObjectName toSource(ObjectName targetName) { - return proc.toSourceContext(targetName, true); - } - - @Override - protected ObjectName toTarget(ObjectName sourceName) { - return proc.toTargetContext(sourceName, false); - } - - // - // Implements permission checks. - // - @Override - void check(ObjectName routingName, String member, String action) { - final SecurityManager sm = System.getSecurityManager(); - if (sm == null) return; - if ("getDomains".equals(action)) return; - final JMXNamespacePermission perm = - new JMXNamespacePermission(serverName,member, - routingName,action); - sm.checkPermission(perm); - } - - @Override - void checkCreate(ObjectName routingName, String className, String action) { - final SecurityManager sm = System.getSecurityManager(); - if (sm == null) return; - final JMXNamespacePermission perm = - new JMXNamespacePermission(serverName,className, - routingName,action); - sm.checkPermission(perm); - } - - // - // Implements permission filters for attributes... - // - @Override - AttributeList checkAttributes(ObjectName routingName, - AttributeList attributes, String action) { - check(routingName,null,action); - if (attributes == null || attributes.isEmpty()) return attributes; - final SecurityManager sm = System.getSecurityManager(); - if (sm == null) return attributes; - final AttributeList res = new AttributeList(); - for (Attribute at : attributes.asList()) { - try { - check(routingName,at.getName(),action); - res.add(at); - } catch (SecurityException x) { // DLS: OK - continue; - } - } - return res; - } - - // - // Implements permission filters for attributes... - // - @Override - String[] checkAttributes(ObjectName routingName, String[] attributes, - String action) { - check(routingName,null,action); - if (attributes == null || attributes.length==0) return attributes;